Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xtask: Fix channel of cargo operations #466

Merged
merged 1 commit into from Jul 12, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 41 additions & 0 deletions xtask/src/cargo.rs
@@ -1,5 +1,7 @@
use crate::arch::UefiArch;
use anyhow::{bail, Result};
use std::env;
use std::ffi::OsString;
use std::process::Command;

#[derive(Clone, Copy, Debug)]
Expand Down Expand Up @@ -86,6 +88,32 @@ pub enum CargoAction {
Test,
}

/// Get a modified PATH to remove entries added by rustup. This is
/// necessary on Windows, see
/// https://github.com/rust-lang/rustup/issues/3031.
fn sanitized_path(orig_path: OsString) -> OsString {
// Modify the PATH to remove entries added by rustup. This is
// necessary on Windows, see https://github.com/rust-lang/rustup/issues/3031.
let paths = env::split_paths(&orig_path);
let sanitized_paths = paths.filter(|path| {
!path
.components()
.any(|component| component.as_os_str() == ".rustup")
});

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) {
cmd.env_remove("RUSTC");
cmd.env_remove("RUSTDOC");
let orig_path = env::var_os("PATH").unwrap_or_default();
cmd.env("PATH", sanitized_path(orig_path));
}

#[derive(Debug)]
pub struct Cargo {
pub action: CargoAction,
Expand All @@ -101,6 +129,8 @@ impl Cargo {
pub fn command(&self) -> Result<Command> {
let mut cmd = Command::new("cargo");

fix_nested_cargo_env(&mut cmd);

if let Some(toolchain) = &self.toolchain {
cmd.arg(&format!("+{}", toolchain));
}
Expand Down Expand Up @@ -193,6 +223,17 @@ mod tests {
);
}

#[test]
fn test_sanitize_path() {
let (input, expected) = match env::consts::FAMILY {
"unix" => ("Abc:/path/.rustup/cargo:Xyz", "Abc:Xyz"),
"windows" => ("Abc;/path/.rustup/cargo;Xyz", "Abc;Xyz"),
_ => unimplemented!(),
};

assert_eq!(sanitized_path(input.into()), expected);
}

#[test]
fn test_cargo_command() {
let cargo = Cargo {
Expand Down
3 changes: 2 additions & 1 deletion xtask/src/main.rs
Expand Up @@ -7,7 +7,7 @@ mod qemu;
mod util;

use anyhow::Result;
use cargo::{Cargo, CargoAction, Feature, Package};
use cargo::{fix_nested_cargo_env, Cargo, CargoAction, Feature, Package};
use cfg_if::cfg_if;
use clap::Parser;
use opt::{Action, BuildOpt, ClippyOpt, DocOpt, MiriOpt, Opt, QemuOpt};
Expand Down Expand Up @@ -172,6 +172,7 @@ fn test_latest_release() -> Result<()> {
// Create cargo build command, not using the `cargo` module to make
// it explicit that it matches the command in `BUILDING.md`.
let mut build_cmd = Command::new("cargo");
fix_nested_cargo_env(&mut build_cmd);
build_cmd
.args(&["+nightly", "build", "--target", "x86_64-unknown-uefi"])
.current_dir(tmp_dir.join("template"));
Expand Down
13 changes: 11 additions & 2 deletions xtask/src/util.rs
Expand Up @@ -6,8 +6,12 @@ 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()))
.map(|(name, val)| {
format!(
"{}={}",
Expand Down Expand Up @@ -47,8 +51,13 @@ mod tests {
#[test]
fn test_command_to_string() {
let mut cmd = Command::new("MyCommand");
cmd.args(&["abc", "123"])
.envs([("VAR1", "val1"), ("VAR2", "val2")]);
cmd.args(&["abc", "123"]).envs([
("VAR1", "val1"),
("VAR2", "val2"),
("PATH", "pathval"),
("RUSTC", "rustcval"),
("RUSTDOC", "rustdocval"),
]);
assert_eq!(
command_to_string(&cmd),
"VAR1=val1 VAR2=val2 MyCommand abc 123"
Expand Down