Skip to content

Commit a9a154f

Browse files
committed
Fix bug with PathAndArg config values
1 parent 4de00d2 commit a9a154f

File tree

5 files changed

+67
-9
lines changed

5 files changed

+67
-9
lines changed

src/cargo/core/compiler/compilation.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,7 @@ fn target_runner(
346346

347347
// try target.{}.runner
348348
let key = format!("target.{}.runner", target);
349+
349350
if let Some(v) = bcx.config.get::<Option<config::PathAndArgs>>(&key)? {
350351
let path = v.path.resolve_program(bcx.config);
351352
return Ok(Some((path, v.args)));

src/cargo/util/config/de.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ impl<'de, 'config> de::Deserializer<'de> for Deserializer<'config> {
5757
(None, Some(_)) => true,
5858
_ => false,
5959
};
60+
6061
if use_env {
6162
// Future note: If you ever need to deserialize a non-self describing
6263
// map type, this should implement a starts_with check (similar to how
@@ -187,13 +188,17 @@ impl<'de, 'config> de::Deserializer<'de> for Deserializer<'config> {
187188
where
188189
V: de::Visitor<'de>,
189190
{
190-
if name == "StringList" {
191-
let vals = self.config.get_list_or_string(&self.key)?;
192-
let vals: Vec<String> = vals.into_iter().map(|vd| vd.0).collect();
193-
visitor.visit_newtype_struct(vals.into_deserializer())
191+
let merge = if name == "StringList" {
192+
true
193+
} else if name == "UnmergedStringList" {
194+
false
194195
} else {
195-
visitor.visit_newtype_struct(self)
196-
}
196+
return visitor.visit_newtype_struct(self);
197+
};
198+
199+
let vals = self.config.get_list_or_string(&self.key, merge)?;
200+
let vals: Vec<String> = vals.into_iter().map(|vd| vd.0).collect();
201+
visitor.visit_newtype_struct(vals.into_deserializer())
197202
}
198203

199204
fn deserialize_enum<V>(

src/cargo/util/config/mod.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,8 +587,21 @@ impl Config {
587587
}
588588

589589
/// Helper for StringList type to get something that is a string or list.
590-
fn get_list_or_string(&self, key: &ConfigKey) -> CargoResult<Vec<(String, Definition)>> {
590+
fn get_list_or_string(
591+
&self,
592+
key: &ConfigKey,
593+
merge: bool,
594+
) -> CargoResult<Vec<(String, Definition)>> {
591595
let mut res = Vec::new();
596+
597+
if !merge {
598+
self.get_env_list(key, &mut res)?;
599+
600+
if !res.is_empty() {
601+
return Ok(res);
602+
}
603+
}
604+
592605
match self.get_cv(key)? {
593606
Some(CV::List(val, _def)) => res.extend(val),
594607
Some(CV::String(val, def)) => {
@@ -602,6 +615,7 @@ impl Config {
602615
}
603616

604617
self.get_env_list(key, &mut res)?;
618+
605619
Ok(res)
606620
}
607621

@@ -1766,6 +1780,14 @@ impl StringList {
17661780
}
17671781
}
17681782

1783+
/// StringList automatically merges config values with environment values,
1784+
/// this instead follows the precedence rules, so that eg. a string list found
1785+
/// in the environment will be used instead of one in a config file.
1786+
///
1787+
/// This is currently only used by `PathAndArgs`
1788+
#[derive(Debug, Deserialize)]
1789+
pub struct UnmergedStringList(Vec<String>);
1790+
17691791
#[macro_export]
17701792
macro_rules! __shell_print {
17711793
($config:expr, $which:ident, $newline:literal, $($arg:tt)*) => ({

src/cargo/util/config/path.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{Config, StringList, Value};
1+
use super::{Config, UnmergedStringList, Value};
22
use serde::{de::Error, Deserialize};
33
use std::path::PathBuf;
44

@@ -55,7 +55,7 @@ impl<'de> serde::Deserialize<'de> for PathAndArgs {
5555
where
5656
D: serde::Deserializer<'de>,
5757
{
58-
let vsl = Value::<StringList>::deserialize(deserializer)?;
58+
let vsl = Value::<UnmergedStringList>::deserialize(deserializer)?;
5959
let mut strings = vsl.val.0;
6060
if strings.is_empty() {
6161
return Err(D::Error::invalid_length(0, &"at least one element"));

tests/testsuite/tool_paths.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,36 @@ fn custom_runner_env() {
278278
.run();
279279
}
280280

281+
#[cargo_test]
282+
fn custom_runner_env_overrides_config() {
283+
let target = rustc_host();
284+
let p = project()
285+
.file("src/main.rs", "fn main() {}")
286+
.file(
287+
".cargo/config.toml",
288+
&format!(
289+
r#"
290+
[target.{}]
291+
runner = "should-not-run -r"
292+
"#,
293+
target
294+
),
295+
)
296+
.build();
297+
298+
let key = format!(
299+
"CARGO_TARGET_{}_RUNNER",
300+
target.to_uppercase().replace('-', "_")
301+
);
302+
303+
p.cargo("run")
304+
.env(&key, "should-run --foo")
305+
.stream()
306+
.with_status(101)
307+
.with_stderr_contains("[RUNNING] `should-run --foo target/debug/foo[EXE]`")
308+
.run();
309+
}
310+
281311
#[cargo_test]
282312
#[cfg(unix)] // Assumes `true` is in PATH.
283313
fn custom_runner_env_true() {

0 commit comments

Comments
 (0)