From 9a1057f7303af359a30aca003040d472de4f87cf Mon Sep 17 00:00:00 2001 From: InChh <2319397152@qq.com> Date: Mon, 14 Jul 2025 23:02:27 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat(libra):=20=E4=B8=BAlibra=20config?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E6=B7=BB=E5=8A=A0--name-only=E5=8F=82?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: InChh <2319397152@qq.com> --- .../docs/libra/command/config/index.mdx | 7 +- libra/src/command/config.rs | 25 ++- libra/tests/command/config_test.rs | 144 ++++++++++++++++++ 3 files changed, 170 insertions(+), 6 deletions(-) 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..6f41731d6 100644 --- a/libra/src/command/config.rs +++ b/libra/src/command/config.rs @@ -22,11 +22,15 @@ 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"))] + #[clap(value_name("key"), required_unless_present("list"), required_unless_present("name_only"))] pub key: Option, /// the value or the possible value pattern of the configuration entry - #[clap(value_name("value_pattern"), required_unless_present("mode"))] + #[clap(value_name("value_pattern"), required_unless_present("mode"), required_unless_present("name_only"))] pub valuepattern: Option, /// If the target key is not present, return the given default value. /// This is only valid when `get` is set. @@ -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..45755d0ae 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()); +} From 74e9c816cfb895821b7f8b080df7fc3002631eb5 Mon Sep 17 00:00:00 2001 From: InChh <2319397152@qq.com> Date: Mon, 14 Jul 2025 23:17:29 +0800 Subject: [PATCH 2/5] Update libra/src/command/config.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: InChh <2319397152@qq.com> --- libra/src/command/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libra/src/command/config.rs b/libra/src/command/config.rs index 6f41731d6..0e9afcd12 100644 --- a/libra/src/command/config.rs +++ b/libra/src/command/config.rs @@ -46,7 +46,7 @@ impl ConfigArgs { } // 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()); + return Err("--name-only is only valid when --list is set".to_string()); } Ok(()) From 93c049f0d1638dfbb58a1d743667b219bc588f58 Mon Sep 17 00:00:00 2001 From: InChh <2319397152@qq.com> Date: Tue, 15 Jul 2025 09:18:16 +0800 Subject: [PATCH 3/5] Update libra/tests/command/config_test.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: InChh <2319397152@qq.com> --- libra/tests/command/config_test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libra/tests/command/config_test.rs b/libra/tests/command/config_test.rs index 45755d0ae..13d0b0860 100644 --- a/libra/tests/command/config_test.rs +++ b/libra/tests/command/config_test.rs @@ -268,7 +268,7 @@ async fn test_config_list_name_only() { #[tokio::test] #[serial] -async fn test_config_list_name_only_without_list(){ +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; From 6028a547c42dd09f0b096178069527a01ddcdfa4 Mon Sep 17 00:00:00 2001 From: InChh <2319397152@qq.com> Date: Tue, 15 Jul 2025 11:45:02 +0800 Subject: [PATCH 4/5] Update libra/src/command/config.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: InChh <2319397152@qq.com> --- libra/src/command/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libra/src/command/config.rs b/libra/src/command/config.rs index 0e9afcd12..85a41cbae 100644 --- a/libra/src/command/config.rs +++ b/libra/src/command/config.rs @@ -27,7 +27,7 @@ pub struct ConfigArgs { #[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"), required_unless_present("name_only"))] + #[clap(value_name("key"), required_unless_present("list"))] pub key: Option, /// the value or the possible value pattern of the configuration entry #[clap(value_name("value_pattern"), required_unless_present("mode"), required_unless_present("name_only"))] From dd61082ae189f3a32f089d133d16b6e43db78ac0 Mon Sep 17 00:00:00 2001 From: InChh <2319397152@qq.com> Date: Tue, 15 Jul 2025 11:45:13 +0800 Subject: [PATCH 5/5] Update libra/src/command/config.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: InChh <2319397152@qq.com> --- libra/src/command/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libra/src/command/config.rs b/libra/src/command/config.rs index 85a41cbae..2ac85d0ca 100644 --- a/libra/src/command/config.rs +++ b/libra/src/command/config.rs @@ -30,7 +30,7 @@ pub struct ConfigArgs { #[clap(value_name("key"), required_unless_present("list"))] pub key: Option, /// the value or the possible value pattern of the configuration entry - #[clap(value_name("value_pattern"), required_unless_present("mode"), required_unless_present("name_only"))] + #[clap(value_name("value_pattern"), required_unless_present("mode"))] pub valuepattern: Option, /// If the target key is not present, return the given default value. /// This is only valid when `get` is set.