Skip to content

Commit 2157847

Browse files
committed
Implement cargo changes for 11036
1 parent 4c7f9d0 commit 2157847

File tree

2 files changed

+136
-22
lines changed

2 files changed

+136
-22
lines changed

src/cargo/ops/cargo_install.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
22
use std::path::{Path, PathBuf};
33
use std::sync::Arc;
4-
use std::{env, fs};
4+
use std::{env, fmt, fs};
55

66
use crate::core::compiler::{CompileKind, DefaultExecutor, Executor, UnitOutput};
77
use crate::core::{Dependency, Edition, Package, PackageId, SourceId, Target, Workspace};
@@ -39,6 +39,41 @@ impl Drop for Transaction {
3939
}
4040
}
4141

42+
enum RustupToolchainSource {
43+
Default,
44+
Environment,
45+
CommandLine,
46+
OverrideDB,
47+
ToolchainFile,
48+
}
49+
50+
impl RustupToolchainSource {
51+
fn get() -> Option<Self> {
52+
env::var("RUSTUP_TOOLCHAIN_SOURCE")
53+
.ok()
54+
.and_then(|val| match val.as_str() {
55+
"default" => Some(Self::Default),
56+
"env" => Some(Self::Environment),
57+
"cli" => Some(Self::CommandLine),
58+
"path-override" => Some(Self::OverrideDB),
59+
"toolchain-file" => Some(Self::ToolchainFile),
60+
_ => None,
61+
})
62+
}
63+
}
64+
65+
impl fmt::Display for RustupToolchainSource {
66+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67+
f.write_str(match self {
68+
Self::Default => "default",
69+
Self::Environment => "env",
70+
Self::CommandLine => "cli",
71+
Self::OverrideDB => "path-override",
72+
Self::ToolchainFile => "toolchain-file",
73+
})
74+
}
75+
}
76+
4277
struct InstallablePackage<'gctx> {
4378
gctx: &'gctx GlobalContext,
4479
opts: ops::CompileOptions,
@@ -316,6 +351,23 @@ impl<'gctx> InstallablePackage<'gctx> {
316351
fn install_one(mut self, dry_run: bool) -> CargoResult<bool> {
317352
self.gctx.shell().status("Installing", &self.pkg)?;
318353

354+
if let Some(source) = RustupToolchainSource::get()
355+
&& !matches!(
356+
source,
357+
RustupToolchainSource::Default | RustupToolchainSource::CommandLine
358+
)
359+
{
360+
let maybe_toolchain = env::var("RUSTUP_TOOLCHAIN")
361+
.ok()
362+
.map(|toolchain| format!(" `{toolchain}`"))
363+
.unwrap_or_default();
364+
self.gctx.shell().warn(format!(
365+
"\
366+
using non-default toolchain{maybe_toolchain} overridden by {source}
367+
Use `cargo +stable install` if you meant to use the stable toolchain."
368+
))?;
369+
}
370+
319371
let dst = self.root.join("bin").into_path_unlocked();
320372

321373
let mut td_opt = None;

tests/testsuite/rustup.rs

Lines changed: 83 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ use std::path::{Path, PathBuf};
88

99
use crate::prelude::*;
1010
use crate::utils::cargo_process;
11-
use cargo_test_support::paths::{home, root};
12-
use cargo_test_support::{process, project, str};
11+
use cargo_test_support::install::assert_has_installed_exe;
12+
use cargo_test_support::paths::{cargo_home, home, root};
13+
use cargo_test_support::{execs, process, project, str};
1314

1415
/// Helper to generate an executable.
1516
fn make_exe(dest: &Path, name: &str, contents: &str, env: &[(&str, PathBuf)]) -> PathBuf {
@@ -99,7 +100,13 @@ fn real_rustc_wrapper(bin_dir: &Path, message: &str) -> PathBuf {
99100
/// Creates a simulation of a rustup environment with `~/.cargo/bin` and
100101
/// `~/.rustup` directories populated with some executables that simulate
101102
/// rustup.
102-
fn simulated_rustup_environment() -> RustupEnvironment {
103+
///
104+
/// Arguments
105+
///
106+
/// - `proxy_calls_cargo`: if true, the cargo proxy calls the cargo under test;
107+
/// otherwise, the cargo proxy calls an executable that panics immediately
108+
/// - `env_setup`: environment variable setup the proxy should perform
109+
fn simulated_rustup_environment(proxy_calls_cargo: bool, env_setup: &str) -> RustupEnvironment {
103110
// Set up ~/.rustup/toolchains/test-toolchain/bin with a custom rustc and cargo.
104111
let rustup_home = home().join(".rustup");
105112
let toolchain_bin = rustup_home
@@ -108,42 +115,58 @@ fn simulated_rustup_environment() -> RustupEnvironment {
108115
.join("bin");
109116
toolchain_bin.mkdir_p();
110117
let rustc_toolchain_exe = real_rustc_wrapper(&toolchain_bin, "real rustc running");
111-
let cargo_toolchain_exe = make_exe(
112-
&toolchain_bin,
113-
"cargo",
114-
r#"panic!("cargo toolchain should not be called");"#,
115-
&[],
116-
);
118+
let cargo_toolchain_exe = if proxy_calls_cargo {
119+
crate::utils::cargo_exe()
120+
} else {
121+
make_exe(
122+
&toolchain_bin,
123+
"cargo",
124+
r#"panic!("cargo toolchain should not be called");"#,
125+
&[],
126+
)
127+
};
117128

118129
// Set up ~/.cargo/bin with a typical set of rustup proxies.
119130
let cargo_bin = home().join(".cargo").join("bin");
120131
cargo_bin.mkdir_p();
121132

122-
let rustc_proxy = make_exe(
133+
let proxy = make_exe(
123134
&cargo_bin,
124135
"rustc",
125136
&format!(
126137
r#"
127-
match std::env::args().next().unwrap().as_ref() {{
128-
"rustc" => {{}}
129-
arg => panic!("proxy only supports rustc, got {{arg:?}}"),
130-
}}
131-
eprintln!("rustc proxy running");
132-
let r = std::process::Command::new(env!("CARGO_RUSTUP_TEST_rustc_toolchain_exe"))
138+
let file_stem = std::path::PathBuf::from(std::env::args().next().unwrap())
139+
.file_stem()
140+
.map(ToOwned::to_owned)
141+
.unwrap();
142+
let program = match file_stem.to_str().unwrap() {{
143+
"cargo" => env!("CARGO_RUSTUP_TEST_cargo_toolchain_exe"),
144+
"rustc" => env!("CARGO_RUSTUP_TEST_rustc_toolchain_exe"),
145+
arg => panic!("proxy only supports cargo and rustc, got {{arg:?}}"),
146+
}};
147+
eprintln!("`{{program}}` proxy running");
148+
let r = std::process::Command::new(program)
133149
.args(std::env::args_os().skip(1))
150+
{env_setup}
134151
.status();
135152
std::process::exit(r.unwrap().code().unwrap_or(2));
136153
"#
137154
),
138-
&[("CARGO_RUSTUP_TEST_rustc_toolchain_exe", rustc_toolchain_exe)],
155+
&[
156+
("CARGO_RUSTUP_TEST_rustc_toolchain_exe", rustc_toolchain_exe),
157+
(
158+
"CARGO_RUSTUP_TEST_cargo_toolchain_exe",
159+
cargo_toolchain_exe.clone(),
160+
),
161+
],
139162
);
140163
fs::hard_link(
141-
&rustc_proxy,
164+
&proxy,
142165
cargo_bin.join("cargo").with_extension(EXE_EXTENSION),
143166
)
144167
.unwrap();
145168
fs::hard_link(
146-
&rustc_proxy,
169+
&proxy,
147170
cargo_bin.join("rustup").with_extension(EXE_EXTENSION),
148171
)
149172
.unwrap();
@@ -162,7 +185,7 @@ fn typical_rustup() {
162185
cargo_bin,
163186
rustup_home,
164187
cargo_toolchain_exe,
165-
} = simulated_rustup_environment();
188+
} = simulated_rustup_environment(false, "");
166189

167190
// Set up a project and run a normal cargo build.
168191
let p = project().file("src/lib.rs", "").build();
@@ -212,7 +235,7 @@ fn custom_calls_other_cargo() {
212235
cargo_bin,
213236
rustup_home,
214237
cargo_toolchain_exe: _,
215-
} = simulated_rustup_environment();
238+
} = simulated_rustup_environment(false, "");
216239

217240
// Create a directory with a custom toolchain (outside of the rustup universe).
218241
let custom_bin = root().join("custom-bin");
@@ -271,3 +294,42 @@ custom toolchain rustc running
271294
"#]])
272295
.run();
273296
}
297+
298+
/// Performs a `cargo install` with a non-default toolchain in a simulated
299+
/// rustup environment. The purpose is to verify the warning that is emitted.
300+
#[cargo_test]
301+
fn cargo_install_with_non_default_toolchain() {
302+
let RustupEnvironment {
303+
cargo_bin,
304+
rustup_home: _,
305+
cargo_toolchain_exe: _,
306+
} = simulated_rustup_environment(
307+
true,
308+
".env(\"RUSTUP_TOOLCHAIN_SOURCE\", \"env\")
309+
.env(\"RUSTUP_TOOLCHAIN\", \"test-toolchain\")",
310+
);
311+
312+
crate::utils::pkg("foo", "0.0.1");
313+
314+
let mut p = process(cargo_bin.join("cargo"));
315+
p.arg_line("install foo");
316+
execs()
317+
.with_process_builder(p)
318+
.with_stderr_data(str![[r#"
319+
`[..]/cargo` proxy running
320+
[UPDATING] `dummy-registry` index
321+
[DOWNLOADING] crates ...
322+
[DOWNLOADED] foo v0.0.1 (registry `dummy-registry`)
323+
[INSTALLING] foo v0.0.1
324+
[WARNING] using non-default toolchain `test-toolchain` overridden by env
325+
Use `cargo +stable install` if you meant to use the stable toolchain.
326+
[COMPILING] foo v0.0.1
327+
[FINISHED] `release` profile [optimized] target(s) in [ELAPSED]s
328+
[INSTALLING] [ROOT]/home/.cargo/bin/foo
329+
[INSTALLED] package `foo v0.0.1` (executable `foo`)
330+
[WARNING] be sure to add `[ROOT]/home/.cargo/bin` to your PATH to be able to run the installed binaries
331+
332+
"#]])
333+
.run();
334+
assert_has_installed_exe(cargo_home(), "foo");
335+
}

0 commit comments

Comments
 (0)