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,6 +864,20 @@ 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 {
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 // TODO: This should probably use a more narrow parser, reject
// comments, blank lines, [headers], etc. // comments, blank lines, [headers], etc.
let toml_v: toml::Value = toml::de::from_str(arg) let toml_v: toml::Value = toml::de::from_str(arg)
@ -876,8 +890,9 @@ impl Config {
toml_table.len() toml_table.len()
); );
} }
let tmp_table = CV::from_toml(Definition::Cli, toml_v) CV::from_toml(Definition::Cli, toml_v)
.chain_err(|| format!("failed to convert --config argument `{}`", arg))?; .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",
);
}