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);
for arg in cli_args {
// 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()
);
}
let tmp_table = CV::from_toml(Definition::Cli, toml_v)
.chain_err(|| format!("failed to convert --config argument `{}`", arg))?;
let arg_as_path = self.cwd.join(arg);
let tmp_table = if !arg.is_empty() && arg_as_path.exists() {
// --config path_to_file
let str_path = arg_as_path
.to_str()
.ok_or_else(|| {
anyhow::format_err!("config path {:?} is not utf-8", arg_as_path)
})?
.to_string();
let mut map = HashMap::new();
let value = CV::String(str_path, Definition::Cli);
map.insert("include".to_string(), value);
CV::Table(map, Definition::Cli)
} 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 tmp_table = self
.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.
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
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.

View File

@ -3,7 +3,8 @@
use super::config::{
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]
fn gated() {
@ -208,3 +209,28 @@ Caused by:
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",
);
}