Auto merge of #7901 - ehuss:config-cli-path, r=alexcrichton

Support `--config path_to_config.toml` cli syntax.

Updates the `--config` flag so that if the argument appears to be a file, it will load the file.

cc #7722, #7723
This commit is contained in:
bors 2020-02-18 20:08:05 +00:00
commit e0678fbbf8
3 changed files with 59 additions and 17 deletions

View File

@ -864,20 +864,35 @@ impl Config {
}; };
let mut loaded_args = CV::Table(HashMap::new(), Definition::Cli); let mut loaded_args = CV::Table(HashMap::new(), Definition::Cli);
for arg in cli_args { for arg in cli_args {
// TODO: This should probably use a more narrow parser, reject let arg_as_path = self.cwd.join(arg);
// comments, blank lines, [headers], etc. let tmp_table = if !arg.is_empty() && arg_as_path.exists() {
let toml_v: toml::Value = toml::de::from_str(arg) // --config path_to_file
.chain_err(|| format!("failed to parse --config argument `{}`", arg))?; let str_path = arg_as_path
let toml_table = toml_v.as_table().unwrap(); .to_str()
if toml_table.len() != 1 { .ok_or_else(|| {
bail!( anyhow::format_err!("config path {:?} is not utf-8", arg_as_path)
"--config argument `{}` expected exactly one key=value pair, got {} keys", })?
arg, .to_string();
toml_table.len() let mut map = HashMap::new();
); let value = CV::String(str_path, Definition::Cli);
} map.insert("include".to_string(), value);
let tmp_table = CV::from_toml(Definition::Cli, toml_v) CV::Table(map, Definition::Cli)
.chain_err(|| format!("failed to convert --config argument `{}`", arg))?; } else {
// TODO: This should probably use a more narrow parser, reject
// comments, blank lines, [headers], etc.
let toml_v: toml::Value = toml::de::from_str(arg)
.chain_err(|| format!("failed to parse --config argument `{}`", arg))?;
let toml_table = toml_v.as_table().unwrap();
if toml_table.len() != 1 {
bail!(
"--config argument `{}` expected exactly one key=value pair, got {} keys",
arg,
toml_table.len()
);
}
CV::from_toml(Definition::Cli, toml_v)
.chain_err(|| format!("failed to convert --config argument `{}`", arg))?
};
let mut seen = HashSet::new(); let mut seen = HashSet::new();
let tmp_table = self let tmp_table = self
.load_includes(tmp_table, &mut seen) .load_includes(tmp_table, &mut seen)

View File

@ -465,10 +465,11 @@ The config values are first loaded from the include path, and then the config
file's own values are merged on top of it. file's own values are merged on top of it.
This can be paired with [config-cli](#config-cli) to specify a file to load This can be paired with [config-cli](#config-cli) to specify a file to load
from the command-line: from the command-line. Pass a path to a config file as the argument to
`--config`:
```console ```console
cargo +nightly -Zunstable-options -Zconfig-include --config 'include="somefile.toml"' build cargo +nightly -Zunstable-options -Zconfig-include --config somefile.toml build
``` ```
CLI paths are relative to the current working directory. CLI paths are relative to the current working directory.

View File

@ -3,7 +3,8 @@
use super::config::{ use super::config::{
assert_error, assert_match, read_output, write_config, write_config_at, ConfigBuilder, assert_error, assert_match, read_output, write_config, write_config_at, ConfigBuilder,
}; };
use cargo_test_support::NO_SUCH_FILE_ERR_MSG; use cargo_test_support::{paths, NO_SUCH_FILE_ERR_MSG};
use std::fs;
#[cargo_test] #[cargo_test]
fn gated() { fn gated() {
@ -208,3 +209,28 @@ Caused by:
expected array, but found string", expected array, but found string",
); );
} }
#[cargo_test]
fn cli_path() {
// --config path_to_file
fs::write(paths::root().join("myconfig.toml"), "key = 123").unwrap();
let config = ConfigBuilder::new()
.cwd(paths::root())
.unstable_flag("config-include")
.config_arg("myconfig.toml")
.build();
assert_eq!(config.get::<u32>("key").unwrap(), 123);
let config = ConfigBuilder::new()
.unstable_flag("config-include")
.config_arg("missing.toml")
.build_err();
assert_error(
config.unwrap_err(),
"\
failed to parse --config argument `missing.toml`
Caused by:
expected an equals, found eof at line 1 column 13",
);
}