diff --git a/aria/contents/docs/libra/command/config/index.mdx b/aria/contents/docs/libra/command/config/index.mdx index a523e94a2..3a1c97e24 100644 --- a/aria/contents/docs/libra/command/config/index.mdx +++ b/aria/contents/docs/libra/command/config/index.mdx @@ -41,6 +41,10 @@ Manage configuration entries by adding, retrieving, listing, or deleting them in List all configuration entries from the database. _Does not require `key` or `value_pattern`._ +- `--name-only` + Output only the names of config variables for --list + _Only valid with `--list`._ + - `-d`, `--default ` Return the given default value if no matching key is found. _Only valid with `--get` `--get-all`._ @@ -49,5 +53,6 @@ Manage configuration entries by adding, retrieving, listing, or deleting them in Print help information. - Only one of `--add`, `--get`, `--get-all`, `--unset`, `--unset-all`, or `--list` can be used at a time. Use `--default` only with `--get` and `--get-all`. + Only one of `--add`, `--get`, `--get-all`, `--unset`, `--unset-all`, or `--list` can be used at a time. Use `--default` only with `--get` and `--get-all`. + Use `--name-only` only with `--list`. diff --git a/libra/src/command/config.rs b/libra/src/command/config.rs index 7ee023c7e..2ac85d0ca 100644 --- a/libra/src/command/config.rs +++ b/libra/src/command/config.rs @@ -22,6 +22,10 @@ pub struct ConfigArgs { /// List all the configuration entries from database #[clap(long, short, group("mode"))] pub list: bool, + /// If set, only print the key string of the configuration entry instead of the key=value. + /// This is only valid when `list` is set. + #[clap(long("name-only"), requires = "list")] + pub name_only: bool, /// The key string of the configuration entry, should be like configuration.[name].key #[clap(value_name("key"), required_unless_present("list"))] pub key: Option, @@ -40,6 +44,11 @@ impl ConfigArgs { if self.default.is_some() && !(self.get || self.get_all) { return Err("default value is only valid when get (get_all) is set".to_string()); } + // validate that name_only is only valid when list is set + if self.name_only && !self.list { + return Err("--name-only is only valid when --list is set".to_string()); + } + Ok(()) } } @@ -56,7 +65,7 @@ pub async fn execute(args: ConfigArgs) { return; } if args.list { - list_config().await; + list_config(args.name_only).await; } else { let origin_key = args.key.unwrap(); let key: Key = parse_key(origin_key).await; @@ -201,9 +210,15 @@ async fn unset_all_config(key: &Key, valuepattern: Option<&str>) { } /// List all configurations -async fn list_config() { +async fn list_config(name_only: bool) { let configurations = config::Config::list_all().await; for (key, value) in configurations { - println!("{key}={value}"); + // If name_only is set, only print the key string + // Otherwise, print the key=value pair + if name_only { + println!("{key}"); + } else { + println!("{key}={value}"); + } } } diff --git a/libra/tests/command/config_test.rs b/libra/tests/command/config_test.rs index ed47ed49d..13d0b0860 100644 --- a/libra/tests/command/config_test.rs +++ b/libra/tests/command/config_test.rs @@ -20,6 +20,7 @@ async fn test_config_get_failed() { key: Some("user.name".to_string()), valuepattern: Some("value".to_string()), default: Some("erasernoob".to_string()), + name_only: false, }; config::execute(args).await; } @@ -45,6 +46,7 @@ async fn test_config_get_all() { key: Some("user.name".to_string()), valuepattern: Some("erasernoob".to_string()), default: None, + name_only: false, }; config::execute(arg1).await; @@ -58,6 +60,7 @@ async fn test_config_get_all() { key: Some("user.name".to_string()), valuepattern: None, default: None, + name_only: false, }; config::execute(args).await; } @@ -82,6 +85,7 @@ async fn test_config_get_all_with_default() { key: Some("user.name".to_string()), valuepattern: Some("value".to_string()), default: Some("erasernoob".to_string()), + name_only: false, }; config::execute(args).await; } @@ -107,6 +111,7 @@ async fn test_config_get() { key: Some("user.name".to_string()), valuepattern: Some("erasernoob".to_string()), default: None, + name_only: false, }; config::execute(arg1).await; @@ -120,6 +125,7 @@ async fn test_config_get() { key: Some("user.name".to_string()), valuepattern: None, default: None, + name_only: false, }; config::execute(args).await; } @@ -143,6 +149,144 @@ async fn test_config_get_with_default() { key: Some("user.name".to_string()), valuepattern: None, default: Some("erasernoob".to_string()), + name_only: false, }; config::execute(args).await; } + +#[tokio::test] +#[serial] +async fn test_config_list() { + let temp_path = tempdir().unwrap(); + // start a new libra repository in a temporary directory + test::setup_with_new_libra_in(temp_path.path()).await; + + // set the current working directory to the temporary path + let _guard = test::ChangeDirGuard::new(temp_path.path()); + + // Add the config first + let arg1 = config::ConfigArgs { + add: true, + get: false, + get_all: false, + unset: false, + unset_all: false, + list: false, + key: Some("user.name".to_string()), + valuepattern: Some("erasernoob".to_string()), + default: None, + name_only: false, + }; + config::execute(arg1).await; + + let arg2 = config::ConfigArgs { + add: true, + get: false, + get_all: false, + unset: false, + unset_all: false, + list: false, + key: Some("user.email".to_string()), + valuepattern: Some("erasernoob@example.com".to_string()), + default: None, + name_only: false, + }; + config::execute(arg2).await; + + // List configs + let args = config::ConfigArgs { + add: false, + get: false, + get_all: false, + unset: false, + unset_all: false, + list: true, + key: None, + valuepattern: None, + default: None, + name_only: false, + }; + assert!(args.validate().is_ok()); + config::execute(args).await; +} + +#[tokio::test] +#[serial] +async fn test_config_list_name_only() { + let temp_path = tempdir().unwrap(); + // start a new libra repository in a temporary directory + test::setup_with_new_libra_in(temp_path.path()).await; + + // set the current working directory to the temporary path + let _guard = test::ChangeDirGuard::new(temp_path.path()); + + // Add the config first + let arg1 = config::ConfigArgs { + add: true, + get: false, + get_all: false, + unset: false, + unset_all: false, + list: false, + key: Some("user.name".to_string()), + valuepattern: Some("erasernoob".to_string()), + default: None, + name_only: false, + }; + config::execute(arg1).await; + + let arg2 = config::ConfigArgs { + add: true, + get: false, + get_all: false, + unset: false, + unset_all: false, + list: false, + key: Some("user.email".to_string()), + valuepattern: Some("erasernoob@example.com".to_string()), + default: None, + name_only: false, + }; + config::execute(arg2).await; + + // List configs with name_only set to true + let args = config::ConfigArgs { + add: false, + get: false, + get_all: false, + unset: false, + unset_all: false, + list: true, + key: None, + valuepattern: None, + default: None, + name_only: true, + }; + assert!(args.validate().is_ok()); + config::execute(args).await; +} + +#[tokio::test] +#[serial] +async fn test_config_list_name_only_without_list() { + let temp_path = tempdir().unwrap(); + // start a new libra repository in a temporary directory + test::setup_with_new_libra_in(temp_path.path()).await; + + // set the current working directory to the temporary path + let _guard = test::ChangeDirGuard::new(temp_path.path()); + + let args = config::ConfigArgs { + add: false, + get: false, + get_all: false, + unset: false, + unset_all: false, + list: false, + key: None, + valuepattern: None, + default: None, + name_only: true, + }; + assert!(args.validate().is_err()); +}