Skip to content

Commit 45941d6

Browse files
authored
refactor(gctx): ConfigValue getter cleanup (#16067)
### What does this PR try to resolve? When trying to add support of "array of tables" in config, there are some minor refactors that could help the migration a bit easier. This PR deals with unnecessary helper functions and tries to inline them. ### How to test and review this PR? No change in user-facing behavior.
2 parents 79df5f4 + baa3f92 commit 45941d6

File tree

5 files changed

+92
-74
lines changed

5 files changed

+92
-74
lines changed

src/cargo/ops/resolve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ pub fn add_overrides<'a>(
527527
ws: &Workspace<'a>,
528528
) -> CargoResult<()> {
529529
let gctx = ws.gctx();
530-
let Some(paths) = gctx.get_list("paths")? else {
530+
let Some(paths) = gctx.paths_overrides()? else {
531531
return Ok(());
532532
};
533533

src/cargo/util/context/de.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,24 @@ impl<'de, 'gctx> de::Deserializer<'de> for Deserializer<'gctx> {
155155
V: de::Visitor<'de>,
156156
{
157157
if name == "StringList" {
158-
let vals = self.gctx.get_list_or_string(&self.key)?;
159-
let vals: Vec<String> = vals.into_iter().map(|vd| vd.0).collect();
158+
let mut res = Vec::new();
159+
160+
match self.gctx.get_cv(&self.key)? {
161+
Some(CV::List(val, _def)) => res.extend(val),
162+
Some(CV::String(val, def)) => {
163+
let split_vs = val.split_whitespace().map(|s| (s.to_string(), def.clone()));
164+
res.extend(split_vs);
165+
}
166+
Some(val) => {
167+
self.gctx
168+
.expected("string or array of strings", &self.key, &val)?;
169+
}
170+
None => {}
171+
}
172+
173+
self.gctx.get_env_list(&self.key, &mut res)?;
174+
175+
let vals: Vec<String> = res.into_iter().map(|vd| vd.0).collect();
160176
visitor.visit_newtype_struct(vals.into_deserializer())
161177
} else {
162178
visitor.visit_newtype_struct(self)
@@ -386,8 +402,15 @@ struct ConfigSeqAccess {
386402
impl ConfigSeqAccess {
387403
fn new(de: Deserializer<'_>) -> Result<ConfigSeqAccess, ConfigError> {
388404
let mut res = Vec::new();
389-
if let Some(v) = de.gctx._get_list(&de.key)? {
390-
res.extend(v.val);
405+
406+
match de.gctx.get_cv(&de.key)? {
407+
Some(CV::List(val, _definition)) => {
408+
res.extend(val);
409+
}
410+
Some(val) => {
411+
de.gctx.expected("list", &de.key, &val)?;
412+
}
413+
None => {}
391414
}
392415

393416
de.gctx.get_env_list(&de.key, &mut res)?;

src/cargo/util/context/mod.rs

Lines changed: 11 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -986,47 +986,6 @@ impl GlobalContext {
986986
}
987987
}
988988

989-
/// Get a list of strings.
990-
///
991-
/// DO NOT USE outside of the config module. `pub` will be removed in the
992-
/// future.
993-
///
994-
/// NOTE: this does **not** support environment variables. Use `get` instead
995-
/// if you want that.
996-
pub fn get_list(&self, key: &str) -> CargoResult<OptValue<Vec<(String, Definition)>>> {
997-
let key = ConfigKey::from_str(key);
998-
self._get_list(&key)
999-
}
1000-
1001-
fn _get_list(&self, key: &ConfigKey) -> CargoResult<OptValue<Vec<(String, Definition)>>> {
1002-
match self.get_cv(key)? {
1003-
Some(CV::List(val, definition)) => Ok(Some(Value { val, definition })),
1004-
Some(val) => self.expected("list", key, &val),
1005-
None => Ok(None),
1006-
}
1007-
}
1008-
1009-
/// Helper for `StringList` type to get something that is a string or list.
1010-
fn get_list_or_string(&self, key: &ConfigKey) -> CargoResult<Vec<(String, Definition)>> {
1011-
let mut res = Vec::new();
1012-
1013-
match self.get_cv(key)? {
1014-
Some(CV::List(val, _def)) => res.extend(val),
1015-
Some(CV::String(val, def)) => {
1016-
let split_vs = val.split_whitespace().map(|s| (s.to_string(), def.clone()));
1017-
res.extend(split_vs);
1018-
}
1019-
Some(val) => {
1020-
return self.expected("string or array of strings", key, &val);
1021-
}
1022-
None => {}
1023-
}
1024-
1025-
self.get_env_list(key, &mut res)?;
1026-
1027-
Ok(res)
1028-
}
1029-
1030989
/// Internal method for getting an environment variable as a list.
1031990
/// If the key is a non-mergeable list and a value is found in the environment, existing values are cleared.
1032991
fn get_env_list(
@@ -1807,6 +1766,17 @@ impl GlobalContext {
18071766
.unwrap_or_else(|| PathBuf::from(tool_str))
18081767
}
18091768

1769+
/// Get the `paths` overrides config value.
1770+
pub fn paths_overrides(&self) -> CargoResult<OptValue<Vec<(String, Definition)>>> {
1771+
let key = ConfigKey::from_str("paths");
1772+
// paths overrides cannot be set via env config, so use get_cv here.
1773+
match self.get_cv(&key)? {
1774+
Some(CV::List(val, definition)) => Ok(Some(Value { val, definition })),
1775+
Some(val) => self.expected("list", &key, &val),
1776+
None => Ok(None),
1777+
}
1778+
}
1779+
18101780
pub fn jobserver_from_env(&self) -> Option<&jobserver::Client> {
18111781
self.jobserver.as_ref()
18121782
}

tests/testsuite/config_cli.rs

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
use std::{collections::HashMap, fs};
44

55
use crate::prelude::*;
6-
use cargo::util::context::Definition;
76
use cargo_test_support::compare::assert_e2e;
87
use cargo_test_support::paths;
98
use cargo_test_support::str;
@@ -264,33 +263,6 @@ fn merges_table() {
264263
assert_eq!(gctx.get::<i32>("foo.key5").unwrap(), 9);
265264
}
266265

267-
#[cargo_test]
268-
fn merge_array_mixed_def_paths() {
269-
// Merging of arrays with different def sites.
270-
write_config_toml(
271-
"
272-
paths = ['file']
273-
",
274-
);
275-
// Create a directory for CWD to differentiate the paths.
276-
let somedir = paths::root().join("somedir");
277-
fs::create_dir(&somedir).unwrap();
278-
let gctx = GlobalContextBuilder::new()
279-
.cwd(&somedir)
280-
.config_arg("paths=['cli']")
281-
// env is currently ignored for get_list()
282-
.env("CARGO_PATHS", "env")
283-
.build();
284-
let paths = gctx.get_list("paths").unwrap().unwrap();
285-
// The definition for the root value is somewhat arbitrary, but currently starts with the file because that is what is loaded first.
286-
assert_eq!(paths.definition, Definition::Path(paths::root()));
287-
assert_eq!(paths.val.len(), 2);
288-
assert_eq!(paths.val[0].0, "file");
289-
assert_eq!(paths.val[0].1.root(&gctx), paths::root());
290-
assert_eq!(paths.val[1].0, "cli");
291-
assert_eq!(paths.val[1].1.root(&gctx), somedir);
292-
}
293-
294266
#[cargo_test]
295267
fn enforces_format() {
296268
// These dotted key expressions should all be fine.

tests/testsuite/paths.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,56 @@ https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html
250250
"#]])
251251
.run();
252252
}
253+
254+
#[cargo_test]
255+
fn env_paths_overrides_not_supported() {
256+
Package::new("file", "0.1.0").publish();
257+
Package::new("cli", "0.1.0").publish();
258+
Package::new("env", "0.1.0").publish();
259+
260+
let p = project()
261+
.file(
262+
"Cargo.toml",
263+
r#"
264+
[package]
265+
name = "foo"
266+
edition = "2015"
267+
268+
[dependencies]
269+
file = "0.1.0"
270+
cli = "0.1.0"
271+
env = "0.1.0"
272+
"#,
273+
)
274+
.file("src/lib.rs", "")
275+
.file("file/Cargo.toml", &basic_manifest("file", "0.2.0"))
276+
.file("file/src/lib.rs", "")
277+
.file("cli/Cargo.toml", &basic_manifest("cli", "0.2.0"))
278+
.file("cli/src/lib.rs", "")
279+
.file("env/Cargo.toml", &basic_manifest("env", "0.2.0"))
280+
.file("env/src/lib.rs", "")
281+
.file(".cargo/config.toml", r#"paths = ["file"]"#)
282+
.build();
283+
284+
p.cargo("check")
285+
.arg("--config")
286+
.arg("paths=['cli']")
287+
// paths overrides ignore env
288+
.env("CARGO_PATHS", "env")
289+
.with_stderr_data(
290+
str![[r#"
291+
[UPDATING] `dummy-registry` index
292+
[LOCKING] 3 packages to latest compatible versions
293+
[DOWNLOADING] crates ...
294+
[DOWNLOADED] env v0.1.0 (registry `dummy-registry`)
295+
[CHECKING] file v0.2.0 ([ROOT]/foo/file)
296+
[CHECKING] cli v0.2.0 ([ROOT]/foo/cli)
297+
[CHECKING] env v0.1.0
298+
[CHECKING] foo v0.0.0 ([ROOT]/foo)
299+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
300+
301+
"#]]
302+
.unordered(),
303+
)
304+
.run();
305+
}

0 commit comments

Comments
 (0)