Skip to content

Commit c171a4e

Browse files
xtask: Fix channel of cargo operations
Starting in rustup 1.25.0, the environment is modified during `cargo` invocations in a way that breaks setting the channel arg (e.g. "+nightly") in a subprocess. Fix by unsetting those variables in the child cargo's env. See rust-lang/rustup#3031
1 parent 35051a3 commit c171a4e

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

xtask/src/cargo.rs

+41
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::arch::UefiArch;
22
use anyhow::{bail, Result};
3+
use std::env;
4+
use std::ffi::OsString;
35
use std::process::Command;
46

57
#[derive(Clone, Copy, Debug)]
@@ -86,6 +88,32 @@ pub enum CargoAction {
8688
Test,
8789
}
8890

91+
/// Get a modified PATH to remove entries added by rustup. This is
92+
/// necessary on Windows, see
93+
/// https://github.com/rust-lang/rustup/issues/3031.
94+
fn sanitized_path(orig_path: OsString) -> OsString {
95+
// Modify the PATH to remove entries added by rustup. This is
96+
// necessary on Windows, see https://github.com/rust-lang/rustup/issues/3031.
97+
let paths = env::split_paths(&orig_path);
98+
let sanitized_paths = paths.filter(|path| {
99+
!path
100+
.components()
101+
.any(|component| component.as_os_str() == ".rustup")
102+
});
103+
104+
env::join_paths(sanitized_paths).expect("invalid PATH")
105+
}
106+
107+
/// Cargo automatically sets some env vars that can prevent the
108+
/// channel arg (e.g. "+nightly") from working. Unset them in the
109+
/// child's environment.
110+
pub fn fix_nested_cargo_env(cmd: &mut Command) {
111+
cmd.env_remove("RUSTC");
112+
cmd.env_remove("RUSTDOC");
113+
let orig_path = env::var_os("PATH").unwrap_or_default();
114+
cmd.env("PATH", sanitized_path(orig_path));
115+
}
116+
89117
#[derive(Debug)]
90118
pub struct Cargo {
91119
pub action: CargoAction,
@@ -101,6 +129,8 @@ impl Cargo {
101129
pub fn command(&self) -> Result<Command> {
102130
let mut cmd = Command::new("cargo");
103131

132+
fix_nested_cargo_env(&mut cmd);
133+
104134
if let Some(toolchain) = &self.toolchain {
105135
cmd.arg(&format!("+{}", toolchain));
106136
}
@@ -193,6 +223,17 @@ mod tests {
193223
);
194224
}
195225

226+
#[test]
227+
fn test_sanitize_path() {
228+
let (input, expected) = match env::consts::FAMILY {
229+
"unix" => ("Abc:/path/.rustup/cargo:Xyz", "Abc:Xyz"),
230+
"windows" => ("Abc;/path/.rustup/cargo;Xyz", "Abc;Xyz"),
231+
_ => unimplemented!(),
232+
};
233+
234+
assert_eq!(sanitized_path(input.into()), expected);
235+
}
236+
196237
#[test]
197238
fn test_cargo_command() {
198239
let cargo = Cargo {

xtask/src/main.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mod qemu;
77
mod util;
88

99
use anyhow::Result;
10-
use cargo::{Cargo, CargoAction, Feature, Package};
10+
use cargo::{fix_nested_cargo_env, Cargo, CargoAction, Feature, Package};
1111
use cfg_if::cfg_if;
1212
use clap::Parser;
1313
use opt::{Action, BuildOpt, ClippyOpt, DocOpt, MiriOpt, Opt, QemuOpt};
@@ -172,6 +172,7 @@ fn test_latest_release() -> Result<()> {
172172
// Create cargo build command, not using the `cargo` module to make
173173
// it explicit that it matches the command in `BUILDING.md`.
174174
let mut build_cmd = Command::new("cargo");
175+
fix_nested_cargo_env(&mut build_cmd);
175176
build_cmd
176177
.args(&["+nightly", "build", "--target", "x86_64-unknown-uefi"])
177178
.current_dir(tmp_dir.join("template"));

xtask/src/util.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ use std::process::Command;
66
/// Example: "VAR=val program --arg1 arg2".
77
pub fn command_to_string(cmd: &Command) -> String {
88
// Format env vars as "name=val".
9+
let ignore_var = ["PATH", "RUSTC", "RUSTDOC"];
910
let mut parts = cmd
1011
.get_envs()
12+
// Filter out some internally-set variables that would just
13+
// clutter the output.
14+
.filter(|(name, _)| !ignore_var.contains(&name.to_str().unwrap_or_default()))
1115
.map(|(name, val)| {
1216
format!(
1317
"{}={}",
@@ -47,8 +51,13 @@ mod tests {
4751
#[test]
4852
fn test_command_to_string() {
4953
let mut cmd = Command::new("MyCommand");
50-
cmd.args(&["abc", "123"])
51-
.envs([("VAR1", "val1"), ("VAR2", "val2")]);
54+
cmd.args(&["abc", "123"]).envs([
55+
("VAR1", "val1"),
56+
("VAR2", "val2"),
57+
("PATH", "pathval"),
58+
("RUSTC", "rustcval"),
59+
("RUSTDOC", "rustdocval"),
60+
]);
5261
assert_eq!(
5362
command_to_string(&cmd),
5463
"VAR1=val1 VAR2=val2 MyCommand abc 123"

0 commit comments

Comments
 (0)