##// END OF EJS Templates
rhg: Add support for --config CLI arguments...
Simon Sapin -
r47232:87fd7f47 default draft
parent child Browse files
Show More
@@ -65,9 +65,9 b' impl Config {'
65 /// Load system and user configuration from various files.
65 /// Load system and user configuration from various files.
66 ///
66 ///
67 /// This is also affected by some environment variables.
67 /// This is also affected by some environment variables.
68 ///
68 pub fn load(
69 /// TODO: add a parameter for `--config` CLI arguments
69 cli_config_args: impl IntoIterator<Item = impl AsRef<[u8]>>,
70 pub fn load() -> Result<Self, ConfigError> {
70 ) -> Result<Self, ConfigError> {
71 let mut config = Self { layers: Vec::new() };
71 let mut config = Self { layers: Vec::new() };
72 let opt_rc_path = env::var_os("HGRCPATH");
72 let opt_rc_path = env::var_os("HGRCPATH");
73 // HGRCPATH replaces system config
73 // HGRCPATH replaces system config
@@ -92,6 +92,9 b' impl Config {'
92 }
92 }
93 }
93 }
94 }
94 }
95 if let Some(layer) = ConfigLayer::parse_cli_args(cli_config_args)? {
96 config.layers.push(layer)
97 }
95 Ok(config)
98 Ok(config)
96 }
99 }
97
100
@@ -51,6 +51,49 b' impl ConfigLayer {'
51 }
51 }
52 }
52 }
53
53
54 /// Parse `--config` CLI arguments and return a layer if there’s any
55 pub(crate) fn parse_cli_args(
56 cli_config_args: impl IntoIterator<Item = impl AsRef<[u8]>>,
57 ) -> Result<Option<Self>, ConfigError> {
58 fn parse_one(arg: &[u8]) -> Option<(Vec<u8>, Vec<u8>, Vec<u8>)> {
59 use crate::utils::SliceExt;
60
61 let (section_and_item, value) = split_2(arg, b'=')?;
62 let (section, item) = split_2(section_and_item.trim(), b'.')?;
63 Some((
64 section.to_owned(),
65 item.to_owned(),
66 value.trim().to_owned(),
67 ))
68 }
69
70 fn split_2(bytes: &[u8], separator: u8) -> Option<(&[u8], &[u8])> {
71 let mut iter = bytes.splitn(2, |&byte| byte == separator);
72 let a = iter.next()?;
73 let b = iter.next()?;
74 Some((a, b))
75 }
76
77 let mut layer = Self::new(ConfigOrigin::CommandLine);
78 for arg in cli_config_args {
79 let arg = arg.as_ref();
80 if let Some((section, item, value)) = parse_one(arg) {
81 layer.add(section, item, value, None);
82 } else {
83 Err(HgError::abort(format!(
84 "malformed --config option: \"{}\" \
85 (use --config section.name=value)",
86 String::from_utf8_lossy(arg),
87 )))?
88 }
89 }
90 if layer.sections.is_empty() {
91 Ok(None)
92 } else {
93 Ok(Some(layer))
94 }
95 }
96
54 /// Returns whether this layer comes from `--config` CLI arguments
97 /// Returns whether this layer comes from `--config` CLI arguments
55 pub(crate) fn is_from_command_line(&self) -> bool {
98 pub(crate) fn is_from_command_line(&self) -> bool {
56 if let ConfigOrigin::CommandLine = self.origin {
99 if let ConfigOrigin::CommandLine = self.origin {
@@ -20,6 +20,17 b" fn add_global_args<'a, 'b>(app: App<'a, "
20 .value_name("REPO")
20 .value_name("REPO")
21 .takes_value(true),
21 .takes_value(true),
22 )
22 )
23 .arg(
24 Arg::with_name("config")
25 .help("set/override config option (use 'section.name=value')")
26 .long("--config")
27 .value_name("CONFIG")
28 .takes_value(true)
29 // Ok: `--config section.key1=val --config section.key2=val2`
30 .multiple(true)
31 // Not ok: `--config section.key1=val section.key2=val2`
32 .number_of_values(1),
33 )
23 }
34 }
24
35
25 fn main() {
36 fn main() {
@@ -47,12 +58,22 b' fn main() {'
47
58
48 // Global arguments can be in either based on e.g. `hg -R ./foo log` v.s.
59 // Global arguments can be in either based on e.g. `hg -R ./foo log` v.s.
49 // `hg log -R ./foo`
60 // `hg log -R ./foo`
50 let global_arg =
61 let value_of_global_arg =
51 |name| args.value_of_os(name).or_else(|| matches.value_of_os(name));
62 |name| args.value_of_os(name).or_else(|| matches.value_of_os(name));
63 // For arguments where multiple occurences are allowed, return a
64 // possibly-iterator of all values.
65 let values_of_global_arg = |name: &str| {
66 let a = matches.values_of_os(name).into_iter().flatten();
67 let b = args.values_of_os(name).into_iter().flatten();
68 a.chain(b)
69 };
52
70
53 let repo_path = global_arg("repository").map(Path::new);
71 let repo_path = value_of_global_arg("repository").map(Path::new);
54 let result = (|| -> Result<(), CommandError> {
72 let result = (|| -> Result<(), CommandError> {
55 let config = hg::config::Config::load()?;
73 let config_args = values_of_global_arg("config")
74 // `get_bytes_from_path` works for OsStr the same as for Path
75 .map(hg::utils::files::get_bytes_from_path);
76 let config = hg::config::Config::load(config_args)?;
56 run(&ui, &config, repo_path, args)
77 run(&ui, &config, repo_path, args)
57 })();
78 })();
58
79
General Comments 0
You need to be logged in to leave comments. Login now