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

Don't add toolchain bin to PATH on Windows #3178

Merged
merged 2 commits into from
Mar 21, 2023
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
17 changes: 16 additions & 1 deletion src/toolchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,22 @@ impl<'a> InstalledCommonToolchain<'a> {
}

if cfg!(target_os = "windows") {
path_entries.push(self.0.path.join("bin"));
// Historically rustup has included the bin directory in PATH to
// work around some bugs (see
// https://github.com/rust-lang/rustup/pull/3178 for more
// information). This shouldn't be needed anymore, and it causes
// problems because calling tools recursively (like `cargo
// +nightly metadata` from within a cargo subcommand). The
// recursive call won't work because it is not executing the
// proxy, so the `+` toolchain override doesn't work.
//
// This is opt-in to allow us to get more real-world testing.
if process()
.var_os("RUSTUP_WINDOWS_PATH_ADD_BIN")
.map_or(true, |s| s == "1")
{
path_entries.push(self.0.path.join("bin"));
}
}

env_var::prepend_path("PATH", path_entries, cmd);
Expand Down
16 changes: 15 additions & 1 deletion tests/mock/mock_bin_src.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@ fn main() {
let rustc = &format!("rustc{}", EXE_SUFFIX);
Command::new(rustc).arg("--version").status().unwrap();
}
Some("--recursive-cargo-subcommand") => {
let status = Command::new("cargo-foo")
.arg("--recursive-cargo")
.status()
.unwrap();
assert!(status.success());
}
Some("--recursive-cargo") => {
let status = Command::new("cargo")
.args(&["+nightly", "--version"])
.status()
.unwrap();
assert!(status.success());
}
Some("--echo-args") => {
let mut out = io::stderr();
for arg in args {
Expand All @@ -71,7 +85,7 @@ fn main() {
let mut out = io::stderr();
writeln!(out, "{}", std::env::var("PATH").unwrap()).unwrap();
}
_ => panic!("bad mock proxy commandline"),
arg => panic!("bad mock proxy commandline: {:?}", arg),
}
}

Expand Down
57 changes: 57 additions & 0 deletions tests/suite/cli_rustup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,63 @@ fn fallback_cargo_calls_correct_rustc() {
});
}

// Checks that cargo can recursively invoke itself with rustup shorthand (via
// the proxy).
//
// This involves a series of chained commands:
//
// 1. Calls `cargo --recursive-cargo-subcommand`
// 2. The rustup `cargo` proxy launches, and launches the "mock" nightly cargo exe.
// 3. The nightly "mock" cargo sees --recursive-cargo-subcommand, and launches
// `cargo-foo --recursive-cargo`
// 4. `cargo-foo` sees `--recursive-cargo` and launches `cargo +nightly --version`
// 5. The rustup `cargo` proxy launches, and launches the "mock" nightly cargo exe.
// 6. The nightly "mock" cargo sees `--version` and prints the version.
//
// Previously, rustup would place the toolchain's `bin` directory in PATH for
// Windows due to some DLL issues. However, those aren't necessary anymore.
// If the toolchain `bin` directory is in PATH, then this test would fail in
// step 5 because the `cargo` executable would be the "mock" nightly cargo,
// and the first argument would be `+nightly` which would be an error.
#[test]
fn recursive_cargo() {
test(&|config| {
config.with_scenario(Scenario::ArchivesV2, &|config| {
config.expect_ok(&["rustup", "default", "nightly"]);

// We need an intermediary to run cargo itself.
// The "mock" cargo can't do that because on Windows it will check
// for a `cargo.exe` in the current directory before checking PATH.
//
// The solution here is to copy from the "mock" `cargo.exe` into
// `~/.cargo/bin/cargo-foo`. This is just for convenience to avoid
// needing to build another executable just for this test.
let output = config.run("rustup", &["which", "cargo"], &[]);
let real_mock_cargo = output.stdout.trim();
let cargo_bin_path = config.cargodir.join("bin");
let cargo_subcommand = cargo_bin_path.join(format!("cargo-foo{}", EXE_SUFFIX));
fs::create_dir_all(&cargo_bin_path).unwrap();
fs::copy(&real_mock_cargo, &cargo_subcommand).unwrap();

// Verify the default behavior, which is currently broken on Windows.
let args = &["cargo", "--recursive-cargo-subcommand"];
if cfg!(windows) {
config.expect_err(
&["cargo", "--recursive-cargo-subcommand"],
"bad mock proxy commandline",
);
}

// Try the opt-in, which should fix it.
let out = config.run(args[0], &args[1..], &[("RUSTUP_WINDOWS_PATH_ADD_BIN", "0")]);
if !out.ok || !out.stdout.contains("hash-nightly-2") {
clitools::print_command(args, &out);
panic!("expected hash-nightly-2 in output");
}
});
});
}

#[test]
fn show_home() {
test(&|config| {
Expand Down