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
2 changes: 1 addition & 1 deletion src/cargo/util/context/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl fmt::Display for ConfigKey {
}
}

fn escape_key_part<'a>(part: &'a str) -> Cow<'a, str> {
pub(super) fn escape_key_part<'a>(part: &'a str) -> Cow<'a, str> {
let ok = part.chars().all(|c| {
matches!(c,
'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_')
Expand Down
50 changes: 43 additions & 7 deletions src/cargo/util/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2155,6 +2155,12 @@ impl From<anyhow::Error> for ConfigError {
}
}

#[derive(Debug)]
enum KeyOrIdx {
Key(String),
Idx(usize),
}

#[derive(Eq, PartialEq, Clone)]
pub enum ConfigValue {
Integer(i64, Definition),
Expand Down Expand Up @@ -2197,26 +2203,56 @@ impl ConfigValue {
}

fn from_toml(def: Definition, toml: toml::Value) -> CargoResult<ConfigValue> {
let mut error_path = Vec::new();
Self::from_toml_inner(def, toml, &mut error_path).with_context(|| {
let mut it = error_path.iter().rev().peekable();
let mut key_path = String::with_capacity(error_path.len() * 3);
while let Some(k) = it.next() {
match k {
KeyOrIdx::Key(s) => key_path.push_str(&key::escape_key_part(&s)),
KeyOrIdx::Idx(i) => key_path.push_str(&format!("[{i}]")),
}
if matches!(it.peek(), Some(KeyOrIdx::Key(_))) {
key_path.push('.');
}
}
format!("failed to parse config at `{key_path}`")
})
}

fn from_toml_inner(
def: Definition,
toml: toml::Value,
path: &mut Vec<KeyOrIdx>,
) -> CargoResult<ConfigValue> {
match toml {
toml::Value::String(val) => Ok(CV::String(val, def)),
toml::Value::Boolean(b) => Ok(CV::Boolean(b, def)),
toml::Value::Integer(i) => Ok(CV::Integer(i, def)),
toml::Value::Array(val) => Ok(CV::List(
val.into_iter()
.map(|toml| match toml {
.enumerate()
.map(|(i, toml)| match toml {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though this part is going to be obsolete when we start supporting array of table (and array of any type).

toml::Value::String(val) => Ok((val, def.clone())),
v => bail!("expected string but found {} in list", v.type_str()),
v => {
path.push(KeyOrIdx::Idx(i));
bail!("expected string but found {} at index {i}", v.type_str())
}
})
.collect::<CargoResult<_>>()?,
def,
)),
toml::Value::Table(val) => Ok(CV::Table(
val.into_iter()
.map(|(key, value)| {
let value = CV::from_toml(def.clone(), value)
.with_context(|| format!("failed to parse key `{}`", key))?;
Ok((key, value))
})
.map(
|(key, value)| match CV::from_toml_inner(def.clone(), value, path) {
Ok(value) => Ok((key, value)),
Err(e) => {
path.push(KeyOrIdx::Key(key));
Err(e)
}
},
)
.collect::<CargoResult<_>>()?,
def,
)),
Expand Down
5 changes: 1 addition & 4 deletions tests/testsuite/bad_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ Caused by:
failed to load TOML configuration from `[ROOT]/foo/.cargo/config.toml`

Caused by:
failed to parse key `http`

Caused by:
failed to parse key `proxy`
failed to parse config at `http.proxy`

Caused by:
found TOML configuration value of unknown type `float`
Expand Down
7 changes: 2 additions & 5 deletions tests/testsuite/cargo_alias_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,10 @@ Caused by:
failed to load TOML configuration from `[ROOT]/foo/.cargo/config.toml`

Caused by:
failed to parse key `alias`
failed to parse config at `alias.b-cargo-test[0]`

Caused by:
failed to parse key `b-cargo-test`

Caused by:
expected string but found integer in list
expected string but found integer at index 0

"#]])
.run();
Expand Down
4 changes: 2 additions & 2 deletions tests/testsuite/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1363,10 +1363,10 @@ Caused by:
failed to load TOML configuration from `[ROOT]/.cargo/config.toml`

Caused by:
failed to parse key `foo`
failed to parse config at `foo[0]`

Caused by:
expected string but found integer in list
expected string but found integer at index 0
"#]],
);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/testsuite/config_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ fn bad_cv_convert() {
failed to convert --config argument `a=2019-12-01`

Caused by:
failed to parse key `a`
failed to parse config at `a`

Caused by:
found TOML configuration value of unknown type `datetime`
Expand Down
Loading