Skip to content

Commit 05acf73

Browse files
committed
Change env section parsing
`untagged` enum variants are not recognised by serde if the variant contains a `Value<T>` type. This change uses an transparent "inner" enum `Value<T>` member, which is handled correctly by serde.
1 parent 7990ab5 commit 05acf73

File tree

2 files changed

+49
-56
lines changed

2 files changed

+49
-56
lines changed

src/cargo/util/config/mod.rs

Lines changed: 35 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,37 +1248,9 @@ impl Config {
12481248
&self.progress_config
12491249
}
12501250

1251-
/// Create an EnvConfigValue hashmap from the "env" table
1252-
fn get_env_config(&self) -> CargoResult<EnvConfig> {
1253-
// We cannot use pure serde handling for this. The Value<_> type does not
1254-
// work when parsing the env table to a hashmap. So iterator through each
1255-
// entry in the "env" table, determine it's type and then use `get` method
1256-
// to deserialize it.
1257-
let env_table = &self.get_table(&ConfigKey::from_str("env"))?;
1258-
let mut vars = EnvConfig::new();
1259-
1260-
if env_table.is_none() {
1261-
return Ok(vars);
1262-
}
1263-
1264-
let env_table = &env_table.as_ref().unwrap().val;
1265-
1266-
for (key, value) in env_table.iter() {
1267-
let full_key = format!("env.{}", key);
1268-
let e = match value {
1269-
ConfigValue::Table(..) => self.get::<EnvConfigValue>(&full_key)?,
1270-
_ => {
1271-
let v = self.get::<Value<String>>(&full_key)?;
1272-
EnvConfigValue::from_value(v)
1273-
}
1274-
};
1275-
vars.insert(key.clone(), e);
1276-
}
1277-
Ok(vars)
1278-
}
1279-
12801251
pub fn env_config(&self) -> CargoResult<&EnvConfig> {
1281-
self.env_config.try_borrow_with(|| self.get_env_config())
1252+
self.env_config
1253+
.try_borrow_with(|| self.get::<EnvConfig>("env"))
12821254
}
12831255

12841256
/// This is used to validate the `term` table has valid syntax.
@@ -1991,33 +1963,47 @@ where
19911963
}
19921964

19931965
#[derive(Debug, Deserialize)]
1966+
#[serde(untagged)]
1967+
enum EnvConfigValueInner {
1968+
Simple(String),
1969+
WithOptions {
1970+
value: String,
1971+
#[serde(default)]
1972+
force: bool,
1973+
#[serde(default)]
1974+
relative: bool,
1975+
},
1976+
}
1977+
1978+
#[derive(Debug, Deserialize)]
1979+
#[serde(transparent)]
19941980
pub struct EnvConfigValue {
1995-
value: Value<String>,
1996-
#[serde(default)]
1997-
force: bool,
1998-
#[serde(default)]
1999-
relative: bool,
1981+
inner: Value<EnvConfigValueInner>,
20001982
}
20011983

20021984
impl EnvConfigValue {
2003-
fn from_value(value: Value<String>) -> EnvConfigValue {
2004-
EnvConfigValue {
2005-
value,
2006-
force: false,
2007-
relative: false,
2008-
}
2009-
}
2010-
20111985
pub fn is_force(&self) -> bool {
2012-
self.force
1986+
match self.inner.val {
1987+
EnvConfigValueInner::Simple(_) => false,
1988+
EnvConfigValueInner::WithOptions { force, .. } => force,
1989+
}
20131990
}
20141991

20151992
pub fn resolve<'a>(&'a self, config: &Config) -> Cow<'a, OsStr> {
2016-
if self.relative {
2017-
let p = self.value.definition.root(config).join(&self.value.val);
2018-
Cow::Owned(p.into_os_string())
2019-
} else {
2020-
Cow::Borrowed(OsStr::new(&self.value.val))
1993+
match self.inner.val {
1994+
EnvConfigValueInner::Simple(ref s) => Cow::Borrowed(OsStr::new(s.as_str())),
1995+
EnvConfigValueInner::WithOptions {
1996+
ref value,
1997+
relative,
1998+
..
1999+
} => {
2000+
if relative {
2001+
let p = self.inner.definition.root(config).join(&value);
2002+
Cow::Owned(p.into_os_string())
2003+
} else {
2004+
Cow::Borrowed(OsStr::new(value.as_str()))
2005+
}
2006+
}
20212007
}
20222008
}
20232009
}

tests/testsuite/cargo_env_config.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ fn env_invalid() {
5555
p.cargo("build -Zconfigurable-env")
5656
.masquerade_as_nightly_cargo()
5757
.with_status(101)
58-
.with_stderr_contains("[..]`env.ENV_TEST_BOOL` expected a string, but found a boolean")
58+
.with_stderr_contains("[..]could not load config key `env.ENV_TEST_BOOL`")
5959
.run();
6060
}
6161

@@ -70,14 +70,16 @@ fn env_force() {
7070
fn main() {
7171
println!( "ENV_TEST_FORCED:{}", env!("ENV_TEST_FORCED") );
7272
println!( "ENV_TEST_UNFORCED:{}", env!("ENV_TEST_UNFORCED") );
73+
println!( "ENV_TEST_UNFORCED_DEFAULT:{}", env!("ENV_TEST_UNFORCED_DEFAULT") );
7374
}
7475
"#,
7576
)
7677
.file(
7778
".cargo/config",
7879
r#"
7980
[env]
80-
ENV_TEST_UNFORCED = "from-config"
81+
ENV_TEST_UNFORCED_DEFAULT = "from-config"
82+
ENV_TEST_UNFORCED = { value = "from-config", force = false }
8183
ENV_TEST_FORCED = { value = "from-config", force = true }
8284
"#,
8385
)
@@ -87,8 +89,10 @@ fn env_force() {
8789
.masquerade_as_nightly_cargo()
8890
.env("ENV_TEST_FORCED", "from-env")
8991
.env("ENV_TEST_UNFORCED", "from-env")
92+
.env("ENV_TEST_UNFORCED_DEFAULT", "from-env")
9093
.with_stdout_contains("ENV_TEST_FORCED:from-config")
9194
.with_stdout_contains("ENV_TEST_UNFORCED:from-env")
95+
.with_stdout_contains("ENV_TEST_UNFORCED_DEFAULT:from-env")
9296
.run();
9397
}
9498

@@ -102,20 +106,23 @@ fn env_relative() {
102106
use std::env;
103107
use std::path::Path;
104108
fn main() {
109+
println!( "ENV_TEST_REGULAR:{}", env!("ENV_TEST_REGULAR") );
110+
println!( "ENV_TEST_REGULAR_DEFAULT:{}", env!("ENV_TEST_REGULAR_DEFAULT") );
105111
println!( "ENV_TEST_RELATIVE:{}", env!("ENV_TEST_RELATIVE") );
106-
println!( "ENV_TEST_ABSOLUTE:{}", env!("ENV_TEST_ABSOLUTE") );
107112
108-
assert!( Path::new(env!("ENV_TEST_ABSOLUTE")).is_absolute() );
109-
assert!( !Path::new(env!("ENV_TEST_RELATIVE")).is_absolute() );
113+
assert!( Path::new(env!("ENV_TEST_RELATIVE")).is_absolute() );
114+
assert!( !Path::new(env!("ENV_TEST_REGULAR")).is_absolute() );
115+
assert!( !Path::new(env!("ENV_TEST_REGULAR_DEFAULT")).is_absolute() );
110116
}
111117
"#,
112118
)
113119
.file(
114120
".cargo/config",
115121
r#"
116122
[env]
117-
ENV_TEST_RELATIVE = "Cargo.toml"
118-
ENV_TEST_ABSOLUTE = { value = "Cargo.toml", relative = true }
123+
ENV_TEST_REGULAR = { value = "Cargo.toml", relative = false }
124+
ENV_TEST_REGULAR_DEFAULT = "Cargo.toml"
125+
ENV_TEST_RELATIVE = { value = "Cargo.toml", relative = true }
119126
"#,
120127
)
121128
.build();

0 commit comments

Comments
 (0)