diff --git a/crates/datapod/src/cli.rs b/crates/datapod/src/cli.rs index 739d0dc..78f4938 100644 --- a/crates/datapod/src/cli.rs +++ b/crates/datapod/src/cli.rs @@ -1,5 +1,6 @@ use clap::{Parser, Subcommand}; +use crate::commands::config::Config; use crate::commands::init::Init; use crate::commands::version::Version; @@ -13,5 +14,6 @@ pub(crate) struct Args { #[derive(Debug, Subcommand)] pub(crate) enum Command { Init(Init), + Config(Config), Version(Version), } diff --git a/crates/datapod/src/commands/config.rs b/crates/datapod/src/commands/config.rs new file mode 100644 index 0000000..de66e63 --- /dev/null +++ b/crates/datapod/src/commands/config.rs @@ -0,0 +1,96 @@ +use clap::Parser; + +use crate::config::Runtime; +use crate::datapod::Datapod; +use crate::error::{bail, DatapodError, DatapodResult}; + +/// Get and set dataset options. +#[derive(Debug, Parser)] +pub(crate) struct Config { + /// Get the value for the given key. + #[arg(long, conflicts_with_all = ["value", "unset", "set"])] + get: bool, + + /// Remove the key from the config. + #[arg(long, conflicts_with_all = ["value", "get", "set"])] + unset: bool, + + /// Set the value for the given key. + #[arg(long, requires = "value", conflicts_with_all = ["get", "unset"])] + set: bool, + + key: String, + + #[arg(conflicts_with_all = ["get", "unset"])] + value: Option, +} + +#[inline] +fn print_option(key: &str, value: Option) +where + T: ToString, +{ + println!( + "{key} = {}", + match value { + Some(value) => value.to_string(), + None => "None".to_string(), + } + ); +} + +pub(crate) fn execute(args: Config) -> DatapodResult<()> { + let datapod = Datapod::discover()?; + let mut config = datapod.config()?; + let key = args.key.as_str(); + + if args.value.is_some() { + let value = args.value.unwrap(); + match key { + "runtime.num_jobs" => { + if let Ok(value) = value.parse::() { + if let Some(ref mut runtime) = config.runtime { + runtime.num_jobs = Some(value); + } else { + config.runtime = Some(Runtime { + num_jobs: Some(value), + }); + } + + config.save()?; + } else { + bail!("invalid value `{value}`"); + } + } + _ => { + bail!("unknown or unsupported config option `{key}`"); + } + } + } else if args.get || (!args.unset && !args.set) { + match key { + "runtime.num_jobs" => { + print_option( + key, + config.runtime.and_then(|rt| rt.num_jobs), + ); + } + _ => { + bail!("unknown or unsupported config option `{key}`"); + } + } + } else if args.unset { + match key { + "runtime.num_jobs" => { + config.runtime = None; + config.save()?; + } + _ => { + bail!("unknown or unsupported config option `{key}`"); + } + } + } else { + unreachable!() + } + + Ok(()) +} diff --git a/crates/datapod/src/commands/mod.rs b/crates/datapod/src/commands/mod.rs index b4b73e4..6f8249d 100644 --- a/crates/datapod/src/commands/mod.rs +++ b/crates/datapod/src/commands/mod.rs @@ -1,2 +1,3 @@ +pub(crate) mod config; pub(crate) mod init; pub(crate) mod version; diff --git a/crates/datapod/src/config.rs b/crates/datapod/src/config.rs index 6941f4d..d26bdb5 100644 --- a/crates/datapod/src/config.rs +++ b/crates/datapod/src/config.rs @@ -17,6 +17,9 @@ pub(crate) struct Config { /// Datapod metadata. pub(crate) metadata: Metadata, + /// Runtime options. + pub(crate) runtime: Option, + /// This structure should always be constructed using a public /// constructor or using the update syntax: /// @@ -60,6 +63,14 @@ impl Default for Metadata { } } +#[derive(Debug, Default, Serialize, Deserialize)] +pub(crate) struct Runtime { + /// Number of threads to use. If this options isn't set or a value + /// of "0" is chosen, the maximum number of available threads + /// is used. + pub(crate) num_jobs: Option, +} + impl Config { /// Creates a new default config and sets the file location. pub(crate) fn create

(path: P) -> DatapodResult diff --git a/crates/datapod/src/error.rs b/crates/datapod/src/error.rs index 17501cc..fcab6f7 100644 --- a/crates/datapod/src/error.rs +++ b/crates/datapod/src/error.rs @@ -1,5 +1,13 @@ pub(crate) type DatapodResult = Result; +macro_rules! bail { + ($($arg:tt)*) => {{ + return Err(DatapodError::Other(format!($($arg)*))); + }}; +} + +pub(crate) use bail; + #[derive(Debug, thiserror::Error)] pub(crate) enum DatapodError { #[error(transparent)] diff --git a/crates/datapod/src/main.rs b/crates/datapod/src/main.rs index 8370e39..8c7c1dc 100644 --- a/crates/datapod/src/main.rs +++ b/crates/datapod/src/main.rs @@ -9,11 +9,13 @@ mod cli; mod commands; mod config; mod datapod; +#[macro_use] mod error; fn run(args: Args) -> DatapodResult<()> { match args.cmd { Command::Init(args) => commands::init::execute(args), + Command::Config(args) => commands::config::execute(args), Command::Version(args) => commands::version::execute(args), } }