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
24 changes: 20 additions & 4 deletions xtask/src/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,28 @@ fn sanitized_path(orig_path: OsString) -> OsString {
env::join_paths(sanitized_paths).expect("invalid PATH")
}

/// Cargo automatically sets some env vars that can prevent the
/// channel arg (e.g. "+nightly") from working. Unset them in the
/// child's environment.
pub fn fix_nested_cargo_env(cmd: &mut Command) {
/// Update a command env to make nested cargo invocations work correctly.
///
/// Cargo automatically sets some env vars that cause problems with nested cargo
/// invocations. In particular, these env vars can:
/// * Cause unwanted rebuilds, e.g. running `cargo xtask test` multiple times
/// will rebuild every time because cached dependencies are marked as stale.
/// * Prevent channels args (e.g. "+nightly") from working.
///
/// Some related issues:
/// * <https://github.com/rust-lang/cargo/issues/15099>
/// * <https://github.com/rust-lang/rustup/issues/3031>
fn fix_nested_cargo_env(cmd: &mut Command) {
cmd.env_remove("RUSTC");
cmd.env_remove("RUSTDOC");

// Clear all vars starting with `CARGO`.
for (name, _) in env::vars() {
if name.starts_with("CARGO") {
cmd.env_remove(name);
}
}

let orig_path = env::var_os("PATH").unwrap_or_default();
cmd.env("PATH", sanitized_path(orig_path));
}
Expand Down
22 changes: 11 additions & 11 deletions xtask/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ use std::process::Command;
/// Example: "VAR=val program --arg1 arg2".
pub fn command_to_string(cmd: &Command) -> String {
// Format env vars as "name=val".
let ignore_var = ["PATH", "RUSTC", "RUSTDOC"];
let mut parts = cmd
.get_envs()
// Filter out some internally-set variables that would just
// clutter the output.
.filter(|(name, _)| !ignore_var.contains(&name.to_str().unwrap_or_default()))
// Filter out variables that are set or cleared by
// `fix_nested_cargo_env`, as they would clutter the output.
.filter(|(name, val)| {
*name != "PATH"
// Exclude any variables cleared with `Command::env_remove`.
&& val.is_some()
})
.map(|(name, val)| {
format!(
"{}={}",
Expand Down Expand Up @@ -53,13 +56,10 @@ mod tests {
#[test]
fn test_command_to_string() {
let mut cmd = Command::new("MyCommand");
cmd.args(["abc", "123"]).envs([
("VAR1", "val1"),
("VAR2", "val2"),
("PATH", "pathval"),
("RUSTC", "rustcval"),
("RUSTDOC", "rustdocval"),
]);
cmd.args(["abc", "123"])
.envs([("VAR1", "val1"), ("VAR2", "val2"), ("PATH", "pathval")])
.env_remove("RUSTC")
.env_remove("CARGO");
assert_eq!(
command_to_string(&cmd),
"VAR1=val1 VAR2=val2 MyCommand abc 123"
Expand Down