just playing with tangled
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

config: migrate "config get"/"set" to TOML-based name argument parsing

+54 -15
+4
CHANGELOG.md
··· 20 20 * `jj config list` now uses multi-line strings and single-quoted strings in the 21 21 output when appropriate. 22 22 23 + * `jj config get`/`list`/`set` now parse `name` argument as [TOML 24 + key](https://toml.io/en/v1.0.0#keys). Quote meta characters as needed. 25 + Example: `jj config get "revset-aliases.'trunk()'"` 26 + 23 27 ### Deprecations 24 28 25 29 - Attempting to alias a built-in command now gives a warning, rather than being silently ignored.
+6 -6
cli/src/commands/config.rs
··· 116 116 #[command(verbatim_doc_comment)] 117 117 pub(crate) struct ConfigGetArgs { 118 118 #[arg(required = true)] 119 - name: String, 119 + name: ConfigNamePathBuf, 120 120 } 121 121 122 122 /// Update config file to set the given option to a given value. 123 123 #[derive(clap::Args, Clone, Debug)] 124 124 pub(crate) struct ConfigSetArgs { 125 125 #[arg(required = true)] 126 - name: String, 126 + name: ConfigNamePathBuf, 127 127 #[arg(required = true)] 128 128 value: String, 129 129 #[command(flatten)] ··· 277 277 command: &CommandHelper, 278 278 args: &ConfigGetArgs, 279 279 ) -> Result<(), CommandError> { 280 - let value = command 281 - .settings() 282 - .config() 283 - .get_string(&args.name) 280 + let value = args 281 + .name 282 + .lookup_value(command.settings().config()) 283 + .and_then(|value| value.into_string()) 284 284 .map_err(|err| match err { 285 285 config::ConfigError::Type { 286 286 origin,
+9 -5
cli/src/config.rs
··· 17 17 use std::path::{Path, PathBuf}; 18 18 use std::process::Command; 19 19 use std::str::FromStr; 20 - use std::{env, fmt}; 20 + use std::{env, fmt, slice}; 21 21 22 22 use config::Source; 23 23 use itertools::Itertools; ··· 52 52 /// Returns true if the path is empty (i.e. pointing to the root table.) 53 53 pub fn is_root(&self) -> bool { 54 54 self.0.is_empty() 55 + } 56 + 57 + /// Returns iterator of path components (or keys.) 58 + pub fn components(&self) -> slice::Iter<'_, toml_edit::Key> { 59 + self.0.iter() 55 60 } 56 61 57 62 /// Appends the given `key` component. ··· 525 530 } 526 531 527 532 pub fn write_config_value_to_file( 528 - key: &str, 533 + key: &ConfigNamePathBuf, 529 534 value_str: &str, 530 535 path: &Path, 531 536 ) -> Result<(), CommandError> { ··· 555 560 _ => toml_edit::value(value_str), 556 561 }; 557 562 let mut target_table = doc.as_table_mut(); 558 - let mut key_parts_iter = key.split('.'); 559 - // Note: split guarantees at least one item. 560 - let last_key_part = key_parts_iter.next_back().unwrap(); 563 + let mut key_parts_iter = key.components(); 564 + let last_key_part = key_parts_iter.next_back().expect("key must not be empty"); 561 565 for key_part in key_parts_iter { 562 566 target_table = target_table 563 567 .entry(key_part)
+34 -3
cli/tests/test_config_command.rs
··· 420 420 } 421 421 422 422 #[test] 423 - fn test_config_set_missing_opts() { 423 + fn test_config_set_bad_opts() { 424 424 let test_env = TestEnvironment::default(); 425 425 let stderr = test_env.jj_cmd_cli_error(test_env.env_root(), &["config", "set"]); 426 426 insta::assert_snapshot!(stderr, @r###" ··· 433 433 434 434 For more information, try '--help'. 435 435 "###); 436 + 437 + let stderr = 438 + test_env.jj_cmd_cli_error(test_env.env_root(), &["config", "set", "--user", "", "x"]); 439 + insta::assert_snapshot!(stderr, @r###" 440 + error: invalid value '' for '<NAME>': TOML parse error at line 1, column 1 441 + | 442 + 1 | 443 + | ^ 444 + invalid key 445 + 446 + 447 + For more information, try '--help'. 448 + "###); 436 449 } 437 450 438 451 #[test] ··· 452 465 &repo_path, 453 466 &["config", "set", "--user", "test-table.foo", "true"], 454 467 ); 468 + test_env.jj_cmd_ok( 469 + &repo_path, 470 + &["config", "set", "--user", "test-table.'bar()'", "0"], 471 + ); 455 472 456 473 // Ensure test-key successfully written to user config. 457 474 let user_config_toml = std::fs::read_to_string(&user_config_path) ··· 461 478 462 479 [test-table] 463 480 foo = true 481 + "bar()" = 0 464 482 "###); 465 483 } 466 484 ··· 741 759 insta::assert_snapshot!(stdout, @r###" 742 760 'b c'.e.'f[]'=2 743 761 "###); 762 + let stdout = test_env.jj_cmd_success(test_env.env_root(), &["config", "get", "'b c'.e.'f[]'"]); 763 + insta::assert_snapshot!(stdout, @r###" 764 + 2 765 + "###); 744 766 745 767 // Not a table 746 768 let (stdout, stderr) = ··· 748 770 insta::assert_snapshot!(stdout, @""); 749 771 insta::assert_snapshot!(stderr, @r###" 750 772 Warning: No matching config key for a.'b()'.x 773 + "###); 774 + let stderr = test_env.jj_cmd_failure(test_env.env_root(), &["config", "get", "a.'b()'.x"]); 775 + insta::assert_snapshot!(stderr, @r###" 776 + Config error: configuration property "a.'b()'.x" not found 777 + For help, see https://github.com/martinvonz/jj/blob/main/docs/config.md. 751 778 "###); 752 779 753 780 // "-" and "_" are valid TOML keys ··· 765 792 insta::assert_snapshot!(stdout, @r###" 766 793 '.'=5 767 794 "###); 768 - let stderr = test_env.jj_cmd_cli_error(test_env.env_root(), &["config", "list", "."]); 795 + let stdout = test_env.jj_cmd_success(test_env.env_root(), &["config", "get", "'.'"]); 796 + insta::assert_snapshot!(stdout, @r###" 797 + 5 798 + "###); 799 + let stderr = test_env.jj_cmd_cli_error(test_env.env_root(), &["config", "get", "."]); 769 800 insta::assert_snapshot!(stderr, @r###" 770 - error: invalid value '.' for '[NAME]': TOML parse error at line 1, column 1 801 + error: invalid value '.' for '<NAME>': TOML parse error at line 1, column 1 771 802 | 772 803 1 | . 773 804 | ^
+1 -1
docs/contributing.md
··· 115 115 hidden from the default `jj log` output) by running the following in your repo: 116 116 117 117 ```shell 118 - jj config set --repo "revset-aliases.immutable_heads()" 'remote_branches(exact:"main") | remote_branches(exact:"gh-pages")' 118 + jj config set --repo "revset-aliases.'immutable_heads()'" 'remote_branches(exact:"main") | remote_branches(exact:"gh-pages")' 119 119 ``` 120 120 121 121 ### Summary