diff --git a/xtask/src/cargo.rs b/xtask/src/cargo.rs index 3b815508f..cd982332d 100644 --- a/xtask/src/cargo.rs +++ b/xtask/src/cargo.rs @@ -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: +/// * +/// * +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)); } diff --git a/xtask/src/util.rs b/xtask/src/util.rs index 4b6a970b8..90e02dada 100644 --- a/xtask/src/util.rs +++ b/xtask/src/util.rs @@ -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!( "{}={}", @@ -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"