Skip to content

Commit 05cd14e

Browse files
committed
Auto merge of #12298 - weihanglo:config-include-toml, r=epage
Add `.toml` file extension restriction for `-Zconfig-include`
2 parents 52b1ffb + 26b7725 commit 05cd14e

File tree

3 files changed

+105
-50
lines changed

3 files changed

+105
-50
lines changed

src/cargo/util/config/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,6 +1273,16 @@ impl Config {
12731273
return Ok(Vec::new());
12741274
}
12751275
};
1276+
1277+
for (path, abs_path, def) in &includes {
1278+
if abs_path.extension() != Some(OsStr::new("toml")) {
1279+
bail!(
1280+
"expected a config include path ending with `.toml`, \
1281+
but found `{path}` from `{def}`",
1282+
)
1283+
}
1284+
}
1285+
12761286
Ok(includes)
12771287
}
12781288

src/doc/src/reference/unstable.md

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -452,27 +452,30 @@ cargo check --keep-going -Z unstable-options
452452
### config-include
453453
* Tracking Issue: [#7723](https://github.com/rust-lang/cargo/issues/7723)
454454

455+
This feature requires the `-Zconfig-include` command-line option.
456+
455457
The `include` key in a config file can be used to load another config file. It
456-
takes a string for a path to another file relative to the config file, or a
457-
list of strings. It requires the `-Zconfig-include` command-line option.
458+
takes a string for a path to another file relative to the config file, or an
459+
array of config file paths. Only path ending with `.toml` is accepted.
458460

459461
```toml
460-
# .cargo/config
461-
include = '../../some-common-config.toml'
462-
```
463-
464-
The config values are first loaded from the include path, and then the config
465-
file's own values are merged on top of it.
462+
# a path ending with `.toml`
463+
include = "path/to/mordor.toml"
466464

467-
This can be paired with [config-cli](#config-cli) to specify a file to load
468-
from the command-line. Pass a path to a config file as the argument to
469-
`--config`:
470-
471-
```console
472-
cargo +nightly -Zunstable-options -Zconfig-include --config somefile.toml build
465+
# or an array of paths
466+
include = ["frodo.toml", "samwise.toml"]
473467
```
474468

475-
CLI paths are relative to the current working directory.
469+
Unlike other config values, the merge behavior of the `include` key is
470+
different. When a config file contains an `include` key:
471+
472+
1. The config values are first loaded from the `include` path.
473+
* If the value of the `include` key is an array of paths, the config values
474+
are loaded and merged from left to right for each path.
475+
* Recurse this step if the config values from the `include` path also
476+
contain an `include` key.
477+
2. Then, the config file's own values are merged on top of the config
478+
from the `include` path.
476479

477480
### target-applies-to-host
478481
* Original Pull Request: [#9322](https://github.com/rust-lang/cargo/pull/9322)

tests/testsuite/config_include.rs

Lines changed: 77 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ use cargo_test_support::{no_such_file_err_msg, project};
66
#[cargo_test]
77
fn gated() {
88
// Requires -Z flag.
9-
write_config("include='other'");
9+
write_config("include='other.toml'");
1010
write_config_at(
11-
".cargo/other",
11+
".cargo/other.toml",
1212
"
1313
othervalue = 1
1414
",
@@ -25,13 +25,13 @@ fn simple() {
2525
write_config_at(
2626
".cargo/config",
2727
"
28-
include = 'other'
28+
include = 'other.toml'
2929
key1 = 1
3030
key2 = 2
3131
",
3232
);
3333
write_config_at(
34-
".cargo/other",
34+
".cargo/other.toml",
3535
"
3636
key2 = 3
3737
key3 = 4
@@ -84,39 +84,63 @@ fn works_with_cli() {
8484
}
8585

8686
#[cargo_test]
87-
fn left_to_right() {
88-
// How it merges multiple includes.
87+
fn left_to_right_bottom_to_top() {
88+
// How it merges multiple nested includes.
8989
write_config_at(
9090
".cargo/config",
9191
"
92-
include = ['one', 'two']
93-
primary = 1
92+
include = ['left-middle.toml', 'right-middle.toml']
93+
top = 1
94+
",
95+
);
96+
write_config_at(
97+
".cargo/right-middle.toml",
98+
"
99+
include = 'right-bottom.toml'
100+
top = 0
101+
right-middle = 0
94102
",
95103
);
96104
write_config_at(
97-
".cargo/one",
105+
".cargo/right-bottom.toml",
98106
"
99-
one = 1
100-
primary = 2
107+
top = -1
108+
right-middle = -1
109+
right-bottom = -1
101110
",
102111
);
103112
write_config_at(
104-
".cargo/two",
113+
".cargo/left-middle.toml",
105114
"
106-
two = 2
107-
primary = 3
115+
include = 'left-bottom.toml'
116+
top = -2
117+
right-middle = -2
118+
right-bottom = -2
119+
left-middle = -2
120+
",
121+
);
122+
write_config_at(
123+
".cargo/left-bottom.toml",
124+
"
125+
top = -3
126+
right-middle = -3
127+
right-bottom = -3
128+
left-middle = -3
129+
left-bottom = -3
108130
",
109131
);
110132
let config = ConfigBuilder::new().unstable_flag("config-include").build();
111-
assert_eq!(config.get::<i32>("primary").unwrap(), 1);
112-
assert_eq!(config.get::<i32>("one").unwrap(), 1);
113-
assert_eq!(config.get::<i32>("two").unwrap(), 2);
133+
assert_eq!(config.get::<i32>("top").unwrap(), 1);
134+
assert_eq!(config.get::<i32>("right-middle").unwrap(), 0);
135+
assert_eq!(config.get::<i32>("right-bottom").unwrap(), -1);
136+
assert_eq!(config.get::<i32>("left-middle").unwrap(), -2);
137+
assert_eq!(config.get::<i32>("left-bottom").unwrap(), -3);
114138
}
115139

116140
#[cargo_test]
117141
fn missing_file() {
118142
// Error when there's a missing file.
119-
write_config("include='missing'");
143+
write_config("include='missing.toml'");
120144
let config = ConfigBuilder::new()
121145
.unstable_flag("config-include")
122146
.build_err();
@@ -127,10 +151,10 @@ fn missing_file() {
127151
could not load Cargo configuration
128152
129153
Caused by:
130-
failed to load config include `missing` from `[..]/.cargo/config`
154+
failed to load config include `missing.toml` from `[..]/.cargo/config`
131155
132156
Caused by:
133-
failed to read configuration file `[..]/.cargo/missing`
157+
failed to read configuration file `[..]/.cargo/missing.toml`
134158
135159
Caused by:
136160
{}",
@@ -139,12 +163,30 @@ Caused by:
139163
);
140164
}
141165

166+
#[cargo_test]
167+
fn wrong_file_extension() {
168+
// Error when it doesn't end with `.toml`.
169+
write_config("include='config.png'");
170+
let config = ConfigBuilder::new()
171+
.unstable_flag("config-include")
172+
.build_err();
173+
assert_error(
174+
config.unwrap_err(),
175+
"\
176+
could not load Cargo configuration
177+
178+
Caused by:
179+
expected a config include path ending with `.toml`, but found `config.png` from `[..]/.cargo/config`
180+
",
181+
);
182+
}
183+
142184
#[cargo_test]
143185
fn cycle() {
144186
// Detects a cycle.
145-
write_config_at(".cargo/config", "include='one'");
146-
write_config_at(".cargo/one", "include='two'");
147-
write_config_at(".cargo/two", "include='config'");
187+
write_config_at(".cargo/config.toml", "include='one.toml'");
188+
write_config_at(".cargo/one.toml", "include='two.toml'");
189+
write_config_at(".cargo/two.toml", "include='config.toml'");
148190
let config = ConfigBuilder::new()
149191
.unstable_flag("config-include")
150192
.build_err();
@@ -154,16 +196,16 @@ fn cycle() {
154196
could not load Cargo configuration
155197
156198
Caused by:
157-
failed to load config include `one` from `[..]/.cargo/config`
199+
failed to load config include `one.toml` from `[..]/.cargo/config.toml`
158200
159201
Caused by:
160-
failed to load config include `two` from `[..]/.cargo/one`
202+
failed to load config include `two.toml` from `[..]/.cargo/one.toml`
161203
162204
Caused by:
163-
failed to load config include `config` from `[..]/.cargo/two`
205+
failed to load config include `config.toml` from `[..]/.cargo/two.toml`
164206
165207
Caused by:
166-
config `include` cycle detected with path `[..]/.cargo/config`",
208+
config `include` cycle detected with path `[..]/.cargo/config.toml`",
167209
);
168210
}
169211

@@ -178,10 +220,10 @@ fn cli_include() {
178220
bar = 2
179221
",
180222
);
181-
write_config_at(".cargo/config-foo", "foo = 2");
223+
write_config_at(".cargo/config-foo.toml", "foo = 2");
182224
let config = ConfigBuilder::new()
183225
.unstable_flag("config-include")
184-
.config_arg("include='.cargo/config-foo'")
226+
.config_arg("include='.cargo/config-foo.toml'")
185227
.build();
186228
assert_eq!(config.get::<i32>("foo").unwrap(), 2);
187229
assert_eq!(config.get::<i32>("bar").unwrap(), 2);
@@ -209,7 +251,7 @@ fn cli_include_failed() {
209251
// Error message when CLI include fails to load.
210252
let config = ConfigBuilder::new()
211253
.unstable_flag("config-include")
212-
.config_arg("include='foobar'")
254+
.config_arg("include='foobar.toml'")
213255
.build_err();
214256
assert_error(
215257
config.unwrap_err(),
@@ -218,10 +260,10 @@ fn cli_include_failed() {
218260
failed to load --config include
219261
220262
Caused by:
221-
failed to load config include `foobar` from `--config cli option`
263+
failed to load config include `foobar.toml` from `--config cli option`
222264
223265
Caused by:
224-
failed to read configuration file `[..]/foobar`
266+
failed to read configuration file `[..]/foobar.toml`
225267
226268
Caused by:
227269
{}",
@@ -235,14 +277,14 @@ fn cli_merge_failed() {
235277
// Error message when CLI include merge fails.
236278
write_config("foo = ['a']");
237279
write_config_at(
238-
".cargo/other",
280+
".cargo/other.toml",
239281
"
240282
foo = 'b'
241283
",
242284
);
243285
let config = ConfigBuilder::new()
244286
.unstable_flag("config-include")
245-
.config_arg("include='.cargo/other'")
287+
.config_arg("include='.cargo/other.toml'")
246288
.build_err();
247289
// Maybe this error message should mention it was from an include file?
248290
assert_error(
@@ -251,7 +293,7 @@ fn cli_merge_failed() {
251293
failed to merge --config key `foo` into `[..]/.cargo/config`
252294
253295
Caused by:
254-
failed to merge config value from `[..]/.cargo/other` into `[..]/.cargo/config`: \
296+
failed to merge config value from `[..]/.cargo/other.toml` into `[..]/.cargo/config`: \
255297
expected array, but found string",
256298
);
257299
}

0 commit comments

Comments
 (0)