Skip to content

Commit e0678fb

Browse files
committed
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
2 parents e029740 + 1d5d7a2 commit e0678fb

File tree

3 files changed

+59
-17
lines changed

3 files changed

+59
-17
lines changed

src/cargo/util/config/mod.rs

+29-14
Original file line numberDiff line numberDiff line change
@@ -864,20 +864,35 @@ impl Config {
864864
};
865865
let mut loaded_args = CV::Table(HashMap::new(), Definition::Cli);
866866
for arg in cli_args {
867-
// TODO: This should probably use a more narrow parser, reject
868-
// comments, blank lines, [headers], etc.
869-
let toml_v: toml::Value = toml::de::from_str(arg)
870-
.chain_err(|| format!("failed to parse --config argument `{}`", arg))?;
871-
let toml_table = toml_v.as_table().unwrap();
872-
if toml_table.len() != 1 {
873-
bail!(
874-
"--config argument `{}` expected exactly one key=value pair, got {} keys",
875-
arg,
876-
toml_table.len()
877-
);
878-
}
879-
let tmp_table = CV::from_toml(Definition::Cli, toml_v)
880-
.chain_err(|| format!("failed to convert --config argument `{}`", arg))?;
867+
let arg_as_path = self.cwd.join(arg);
868+
let tmp_table = if !arg.is_empty() && arg_as_path.exists() {
869+
// --config path_to_file
870+
let str_path = arg_as_path
871+
.to_str()
872+
.ok_or_else(|| {
873+
anyhow::format_err!("config path {:?} is not utf-8", arg_as_path)
874+
})?
875+
.to_string();
876+
let mut map = HashMap::new();
877+
let value = CV::String(str_path, Definition::Cli);
878+
map.insert("include".to_string(), value);
879+
CV::Table(map, Definition::Cli)
880+
} else {
881+
// TODO: This should probably use a more narrow parser, reject
882+
// comments, blank lines, [headers], etc.
883+
let toml_v: toml::Value = toml::de::from_str(arg)
884+
.chain_err(|| format!("failed to parse --config argument `{}`", arg))?;
885+
let toml_table = toml_v.as_table().unwrap();
886+
if toml_table.len() != 1 {
887+
bail!(
888+
"--config argument `{}` expected exactly one key=value pair, got {} keys",
889+
arg,
890+
toml_table.len()
891+
);
892+
}
893+
CV::from_toml(Definition::Cli, toml_v)
894+
.chain_err(|| format!("failed to convert --config argument `{}`", arg))?
895+
};
881896
let mut seen = HashSet::new();
882897
let tmp_table = self
883898
.load_includes(tmp_table, &mut seen)

src/doc/src/reference/unstable.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -465,10 +465,11 @@ The config values are first loaded from the include path, and then the config
465465
file's own values are merged on top of it.
466466

467467
This can be paired with [config-cli](#config-cli) to specify a file to load
468-
from the command-line:
468+
from the command-line. Pass a path to a config file as the argument to
469+
`--config`:
469470

470471
```console
471-
cargo +nightly -Zunstable-options -Zconfig-include --config 'include="somefile.toml"' build
472+
cargo +nightly -Zunstable-options -Zconfig-include --config somefile.toml build
472473
```
473474

474475
CLI paths are relative to the current working directory.

tests/testsuite/config_include.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
use super::config::{
44
assert_error, assert_match, read_output, write_config, write_config_at, ConfigBuilder,
55
};
6-
use cargo_test_support::NO_SUCH_FILE_ERR_MSG;
6+
use cargo_test_support::{paths, NO_SUCH_FILE_ERR_MSG};
7+
use std::fs;
78

89
#[cargo_test]
910
fn gated() {
@@ -208,3 +209,28 @@ Caused by:
208209
expected array, but found string",
209210
);
210211
}
212+
213+
#[cargo_test]
214+
fn cli_path() {
215+
// --config path_to_file
216+
fs::write(paths::root().join("myconfig.toml"), "key = 123").unwrap();
217+
let config = ConfigBuilder::new()
218+
.cwd(paths::root())
219+
.unstable_flag("config-include")
220+
.config_arg("myconfig.toml")
221+
.build();
222+
assert_eq!(config.get::<u32>("key").unwrap(), 123);
223+
224+
let config = ConfigBuilder::new()
225+
.unstable_flag("config-include")
226+
.config_arg("missing.toml")
227+
.build_err();
228+
assert_error(
229+
config.unwrap_err(),
230+
"\
231+
failed to parse --config argument `missing.toml`
232+
233+
Caused by:
234+
expected an equals, found eof at line 1 column 13",
235+
);
236+
}

0 commit comments

Comments
 (0)