Skip to content

Commit a761572

Browse files
committed
Add RustupEnvironmentBuilder
This is the first of several commits to implement a fix for #11036. The changes fetch the `RUSTUP_TOOLCHAIN_SOURCE` environment variable set by Rustup, and warn if it is anything other than "default" or "cli".
1 parent 5854d39 commit a761572

File tree

1 file changed

+109
-54
lines changed

1 file changed

+109
-54
lines changed

tests/testsuite/rustup.rs

Lines changed: 109 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
//! Tests for Cargo's behavior under Rustup.
22
3+
use std::collections::BTreeMap;
34
use std::env;
45
use std::env::consts::EXE_EXTENSION;
56
use std::ffi::OsString;
7+
use std::fmt::Write;
68
use std::fs;
79
use std::path::{Path, PathBuf};
810

@@ -88,62 +90,115 @@ fn real_rustc_wrapper(bin_dir: &Path, message: &str) -> PathBuf {
8890
)
8991
}
9092

91-
/// Creates a simulation of a rustup environment with `~/.cargo/bin` and
92-
/// `~/.rustup` directories populated with some executables that simulate
93-
/// rustup.
94-
fn simulated_rustup_environment() -> RustupEnvironment {
95-
// Set up ~/.rustup/toolchains/test-toolchain/bin with a custom rustc and cargo.
96-
let rustup_home = home().join(".rustup");
97-
let toolchain_bin = rustup_home
98-
.join("toolchains")
99-
.join("test-toolchain")
100-
.join("bin");
101-
toolchain_bin.mkdir_p();
102-
let rustc_toolchain_exe = real_rustc_wrapper(&toolchain_bin, "real rustc running");
103-
let cargo_toolchain_exe = make_exe(
104-
&toolchain_bin,
105-
"cargo",
106-
r#"panic!("cargo toolchain should not be called");"#,
107-
&[],
108-
);
93+
/// A builder for a simulated rustup environment.
94+
///
95+
/// The environment has `~/.cargo/bin` and `~/.rustup` directories populated
96+
/// with some executables that simulate rustup.
97+
struct RustupEnvironmentBuilder {
98+
/// Whether the cargo proxy should call the cargo under test. By default,
99+
/// the proxy calls an executable that panics immediately.
100+
proxy_calls_cargo: bool,
101+
/// Environment variable setup the proxy should perform.
102+
env: BTreeMap<String, String>,
103+
}
109104

110-
// Set up ~/.cargo/bin with a typical set of rustup proxies.
111-
let cargo_bin = home().join(".cargo").join("bin");
112-
cargo_bin.mkdir_p();
105+
impl RustupEnvironmentBuilder {
106+
/// Creates a new [`RustupEnvironmentBuilder`].
107+
fn new() -> Self {
108+
Self {
109+
proxy_calls_cargo: false,
110+
env: BTreeMap::new(),
111+
}
112+
}
113113

114-
let rustc_proxy = make_exe(
115-
&cargo_bin,
116-
"rustc",
117-
&format!(
118-
r#"
119-
match std::env::args().next().unwrap().as_ref() {{
120-
"rustc" => {{}}
121-
arg => panic!("proxy only supports rustc, got {{arg:?}}"),
122-
}}
123-
eprintln!("rustc proxy running");
124-
let r = std::process::Command::new(env!("CARGO_RUSTUP_TEST_rustc_toolchain_exe"))
125-
.args(std::env::args_os().skip(1))
126-
.status();
127-
std::process::exit(r.unwrap().code().unwrap_or(2));
114+
/// Call the cargo under test rather than an executable that panics
115+
/// immediately.
116+
pub fn call_cargo_under_test(&mut self) -> &mut Self {
117+
self.proxy_calls_cargo = true;
118+
self
119+
}
120+
121+
/// (chainable) Sets an environment variable for the proxy.
122+
pub fn env<T: AsRef<str>>(&mut self, key: &str, val: T) -> &mut Self {
123+
self.env.insert(key.to_string(), val.as_ref().to_string());
124+
self
125+
}
126+
127+
pub fn build(&mut self) -> RustupEnvironment {
128+
// Set up ~/.rustup/toolchains/test-toolchain/bin with a custom rustc and cargo.
129+
let rustup_home = home().join(".rustup");
130+
let toolchain_bin = rustup_home
131+
.join("toolchains")
132+
.join("test-toolchain")
133+
.join("bin");
134+
toolchain_bin.mkdir_p();
135+
let rustc_toolchain_exe = real_rustc_wrapper(&toolchain_bin, "real rustc running");
136+
let cargo_toolchain_exe = if self.proxy_calls_cargo {
137+
crate::utils::cargo_exe()
138+
} else {
139+
make_exe(
140+
&toolchain_bin,
141+
"cargo",
142+
r#"panic!("cargo toolchain should not be called");"#,
143+
&[],
144+
)
145+
};
146+
147+
// Set up ~/.cargo/bin with a typical set of rustup proxies.
148+
let cargo_bin = home().join(".cargo").join("bin");
149+
cargo_bin.mkdir_p();
150+
151+
let mut env_setup = String::new();
152+
for (k, v) in &self.env {
153+
write!(env_setup, ".env(\"{k}\", \"{v}\")").unwrap();
154+
}
155+
156+
let rustc_proxy = make_exe(
157+
&cargo_bin,
158+
"rustc",
159+
&format!(
160+
r#"
161+
let file_stem = std::path::PathBuf::from(std::env::args().next().unwrap())
162+
.file_stem()
163+
.map(ToOwned::to_owned)
164+
.unwrap();
165+
let program = match file_stem.to_str().unwrap() {{
166+
"cargo" => env!("CARGO_RUSTUP_TEST_cargo_toolchain_exe"),
167+
"rustc" => env!("CARGO_RUSTUP_TEST_rustc_toolchain_exe"),
168+
arg => panic!("proxy only supports cargo and rustc, got {{arg:?}}"),
169+
}};
170+
eprintln!("`{{program}}` proxy running");
171+
let r = std::process::Command::new(program)
172+
.args(std::env::args_os().skip(1))
173+
{env_setup}
174+
.status();
175+
std::process::exit(r.unwrap().code().unwrap_or(2));
128176
"#
129-
),
130-
&[("CARGO_RUSTUP_TEST_rustc_toolchain_exe", rustc_toolchain_exe)],
131-
);
132-
fs::hard_link(
133-
&rustc_proxy,
134-
cargo_bin.join("cargo").with_extension(EXE_EXTENSION),
135-
)
136-
.unwrap();
137-
fs::hard_link(
138-
&rustc_proxy,
139-
cargo_bin.join("rustup").with_extension(EXE_EXTENSION),
140-
)
141-
.unwrap();
177+
),
178+
&[
179+
("CARGO_RUSTUP_TEST_rustc_toolchain_exe", rustc_toolchain_exe),
180+
(
181+
"CARGO_RUSTUP_TEST_cargo_toolchain_exe",
182+
cargo_toolchain_exe.clone(),
183+
),
184+
],
185+
);
186+
fs::hard_link(
187+
&rustc_proxy,
188+
cargo_bin.join("cargo").with_extension(EXE_EXTENSION),
189+
)
190+
.unwrap();
191+
fs::hard_link(
192+
&rustc_proxy,
193+
cargo_bin.join("rustup").with_extension(EXE_EXTENSION),
194+
)
195+
.unwrap();
142196

143-
RustupEnvironment {
144-
cargo_bin,
145-
rustup_home,
146-
cargo_toolchain_exe,
197+
RustupEnvironment {
198+
cargo_bin,
199+
rustup_home,
200+
cargo_toolchain_exe,
201+
}
147202
}
148203
}
149204

@@ -154,7 +209,7 @@ fn typical_rustup() {
154209
cargo_bin,
155210
rustup_home,
156211
cargo_toolchain_exe,
157-
} = simulated_rustup_environment();
212+
} = RustupEnvironmentBuilder::new().build();
158213

159214
// Set up a project and run a normal cargo build.
160215
let p = project().file("src/lib.rs", "").build();
@@ -202,7 +257,7 @@ fn custom_calls_other_cargo() {
202257
cargo_bin,
203258
rustup_home,
204259
cargo_toolchain_exe: _,
205-
} = simulated_rustup_environment();
260+
} = RustupEnvironmentBuilder::new().build();
206261

207262
// Create a directory with a custom toolchain (outside of the rustup universe).
208263
let custom_bin = root().join("custom-bin");

0 commit comments

Comments
 (0)