Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 30 additions & 24 deletions src/cargo/util/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1286,9 +1286,9 @@ impl GlobalContext {

/// Start a config file discovery from a path and merges all config values found.
fn load_values_from(&self, path: &Path) -> CargoResult<HashMap<String, ConfigValue>> {
// This definition path is ignored, this is just a temporary container
// representing the entire file.
let mut cfg = CV::Table(HashMap::new(), Definition::Path(PathBuf::from(".")));
// The root config value container isn't from any external source,
// so its definition should be built-in.
let mut cfg = CV::Table(HashMap::new(), Definition::BuiltIn);
let home = self.home_path.clone().into_path_unlocked();

self.walk_tree(path, &home, |path| {
Expand Down Expand Up @@ -1546,24 +1546,18 @@ impl GlobalContext {

/// Add config arguments passed on the command line.
fn merge_cli_args(&mut self) -> CargoResult<()> {
let CV::Table(loaded_map, _def) = self.cli_args_as_table()? else {
unreachable!()
};
let values = self.values_mut()?;
for (key, value) in loaded_map.into_iter() {
match values.entry(key) {
Vacant(entry) => {
entry.insert(value);
}
Occupied(mut entry) => entry.get_mut().merge(value, true).with_context(|| {
format!(
"failed to merge --config key `{}` into `{}`",
entry.key(),
entry.get().definition(),
)
})?,
};
}
let cv_from_cli = self.cli_args_as_table()?;
assert!(cv_from_cli.is_table(), "cv from CLI must be a table");

let root_cv = mem::take(self.values_mut()?);
// The root config value container isn't from any external source,
// so its definition should be built-in.
let mut root_cv = CV::Table(root_cv, Definition::BuiltIn);
root_cv.merge(cv_from_cli, true)?;

// Put it back to gctx
mem::swap(self.values_mut()?, root_cv.table_mut("<root>")?.0);

Ok(())
}

Expand Down Expand Up @@ -1710,9 +1704,7 @@ impl GlobalContext {
let mut value = self.load_file(&credentials)?;
// Backwards compatibility for old `.cargo/credentials` layout.
{
let CV::Table(ref mut value_map, ref def) = value else {
unreachable!();
};
let (value_map, def) = value.table_mut("<root>")?;

if let Some(token) = value_map.remove("token") {
if let Vacant(entry) = value_map.entry("registry".into()) {
Expand Down Expand Up @@ -2299,6 +2291,20 @@ impl ConfigValue {
}
}

pub fn table_mut(
&mut self,
key: &str,
) -> CargoResult<(&mut HashMap<String, ConfigValue>, &mut Definition)> {
match self {
CV::Table(table, def) => Ok((table, def)),
_ => self.expected("table", key),
}
}

pub fn is_table(&self) -> bool {
matches!(self, CV::Table(_table, _def))
}

pub fn string_list(&self, key: &str) -> CargoResult<Vec<(String, Definition)>> {
match self {
CV::List(list, _) => list
Expand Down
17 changes: 16 additions & 1 deletion tests/testsuite/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ Caused by:
assert_error(
gctx.unwrap_err(),
str![[r#"
failed to merge --config key `a` into `[ROOT]/.cargo/config.toml`
failed to merge key `a` between [ROOT]/.cargo/config.toml and --config cli option

Caused by:
failed to merge config value from `--config cli option` into `[ROOT]/.cargo/config.toml`: expected boolean, but found array
Expand Down Expand Up @@ -2209,6 +2209,21 @@ credential-provider = ['c', 'd']
.unwrap();
assert_eq!(provider.path.raw_value(), "c");
assert_eq!(provider.args, ["d"]);

let cli_arg = "registries.example.credential-provider=['cli', 'cli-arg']";
let gctx = GlobalContextBuilder::new()
.config_arg(cli_arg)
.cwd("foo")
.build();
let provider = gctx
.get::<Option<RegistryConfig>>(&format!("registries.example"))
.unwrap()
.unwrap()
.credential_provider
.unwrap();
// expect: no merge happens; config CLI takes precedence
assert_eq!(provider.path.raw_value(), "cli");
assert_eq!(provider.args, ["cli-arg"]);
}

#[cargo_test]
Expand Down
2 changes: 1 addition & 1 deletion tests/testsuite/config_include.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ fn cli_merge_failed() {
assert_error(
gctx.unwrap_err(),
str![[r#"
failed to merge --config key `foo` into `[ROOT]/.cargo/config.toml`
failed to merge key `foo` between [ROOT]/.cargo/config.toml and [ROOT]/.cargo/other.toml

Caused by:
failed to merge config value from `[ROOT]/.cargo/other.toml` into `[ROOT]/.cargo/config.toml`: expected array, but found string
Expand Down