Skip to content

Commit b2d8a44

Browse files
committed
Rework config walk_tree in preparation for safe_directories
This reworks the walk_tree so that the home config can be loaded first in order to check safe_directories.
1 parent bbd41a4 commit b2d8a44

File tree

2 files changed

+45
-38
lines changed

2 files changed

+45
-38
lines changed

src/cargo/util/config/mod.rs

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,18 +1004,19 @@ impl Config {
10041004
}
10051005

10061006
pub(crate) fn load_values_unmerged(&self) -> CargoResult<Vec<ConfigValue>> {
1007+
self._load_values_unmerged()
1008+
.with_context(|| "could not load Cargo configuration")
1009+
}
1010+
1011+
fn _load_values_unmerged(&self) -> CargoResult<Vec<ConfigValue>> {
1012+
let (cvs, mut seen) = self.walk_tree(&self.cwd, false)?;
10071013
let mut result = Vec::new();
1008-
let mut seen = HashSet::new();
1009-
let home = self.home_path.clone().into_path_unlocked();
1010-
self.walk_tree(&self.cwd, &home, |path| {
1011-
let mut cv = self._load_file(path, &mut seen, false)?;
1014+
for mut cv in cvs {
10121015
if self.cli_unstable().config_include {
10131016
self.load_unmerged_include(&mut cv, &mut seen, &mut result)?;
10141017
}
10151018
result.push(cv);
1016-
Ok(())
1017-
})
1018-
.with_context(|| "could not load Cargo configuration")?;
1019+
}
10191020
Ok(result)
10201021
}
10211022

@@ -1037,20 +1038,19 @@ impl Config {
10371038
}
10381039

10391040
fn load_values_from(&self, path: &Path) -> CargoResult<HashMap<String, ConfigValue>> {
1041+
let (cvs, _) = self
1042+
.walk_tree(path, true)
1043+
.with_context(|| "could not load Cargo configuration")?;
1044+
1045+
// Merge all the files together.
10401046
// This definition path is ignored, this is just a temporary container
10411047
// representing the entire file.
10421048
let mut cfg = CV::Table(HashMap::new(), Definition::Path(PathBuf::from(".")));
1043-
let home = self.home_path.clone().into_path_unlocked();
1044-
1045-
self.walk_tree(path, &home, |path| {
1046-
let value = self.load_file(path, true)?;
1047-
cfg.merge(value, false).with_context(|| {
1049+
for cv in cvs {
1050+
cfg.merge(cv, false).with_context(|| {
10481051
format!("failed to merge configuration at `{}`", path.display())
10491052
})?;
1050-
Ok(())
1051-
})
1052-
.with_context(|| "could not load Cargo configuration")?;
1053-
1053+
}
10541054
match cfg {
10551055
CV::Table(map, _) => Ok(map),
10561056
_ => unreachable!(),
@@ -1355,29 +1355,39 @@ impl Config {
13551355
}
13561356
}
13571357

1358-
fn walk_tree<F>(&self, pwd: &Path, home: &Path, mut walk: F) -> CargoResult<()>
1359-
where
1360-
F: FnMut(&Path) -> CargoResult<()>,
1361-
{
1362-
let mut stash: HashSet<PathBuf> = HashSet::new();
1358+
/// Walks from the given path upwards, loading `config.toml` files along the way.
1359+
///
1360+
/// `includes` indicates whether or not `includes` directives should be loaded.
1361+
///
1362+
/// Returns a `Vec` of each config file in the order they were loaded (home directory is last).
1363+
fn walk_tree(&self, pwd: &Path, includes: bool) -> CargoResult<(Vec<CV>, HashSet<PathBuf>)> {
1364+
let mut seen: HashSet<PathBuf> = HashSet::new();
1365+
// Load "home" first so that safe.directories can be loaded. However,
1366+
// "home" will be last in the result.
1367+
let home = self.home_path.clone().into_path_unlocked();
1368+
let home_cv = if let Some(path) = self.get_file_path(&home, "config", true)? {
1369+
Some(self._load_file(&path, &mut seen, includes)?)
1370+
} else {
1371+
None
1372+
};
1373+
1374+
let mut result = Vec::new();
13631375

13641376
for current in paths::ancestors(pwd, self.search_stop_path.as_deref()) {
1365-
if let Some(path) = self.get_file_path(&current.join(".cargo"), "config", true)? {
1366-
walk(&path)?;
1367-
stash.insert(path);
1377+
let dot_cargo = current.join(".cargo");
1378+
if dot_cargo == home {
1379+
// home is already loaded, don't load again.
1380+
continue;
13681381
}
1369-
}
1370-
1371-
// Once we're done, also be sure to walk the home directory even if it's not
1372-
// in our history to be sure we pick up that standard location for
1373-
// information.
1374-
if let Some(path) = self.get_file_path(home, "config", true)? {
1375-
if !stash.contains(&path) {
1376-
walk(&path)?;
1382+
if let Some(path) = self.get_file_path(&dot_cargo, "config", true)? {
1383+
let cv = self._load_file(&path, &mut seen, includes)?;
1384+
result.push(cv);
13771385
}
13781386
}
1379-
1380-
Ok(())
1387+
if let Some(home_cv) = home_cv {
1388+
result.push(home_cv);
1389+
}
1390+
Ok((result, seen))
13811391
}
13821392

13831393
/// Gets the index for a registry.

tests/testsuite/config.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,10 +1181,7 @@ fn table_merge_failure() {
11811181
assert_error(
11821182
config.get::<Table>("table").unwrap_err(),
11831183
"\
1184-
could not load Cargo configuration
1185-
1186-
Caused by:
1187-
failed to merge configuration at `[..]/.cargo/config`
1184+
failed to merge configuration at `[ROOT]/foo`
11881185
11891186
Caused by:
11901187
failed to merge key `table` between [..]/foo/.cargo/config and [..]/.cargo/config

0 commit comments

Comments
 (0)