Skip to content

Commit 8376c54

Browse files
committed
feat(cli): warn when removing the last/host target for a toolchain
1 parent f2ecc75 commit 8376c54

File tree

4 files changed

+53
-8
lines changed

4 files changed

+53
-8
lines changed

Cargo.lock

Lines changed: 11 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ wait-timeout = "0.2"
9494
walkdir = { workspace = true, optional = true }
9595
xz2 = "0.1.3"
9696
zstd = "0.13"
97+
itertools = "0.12.0"
9798

9899
[target."cfg(windows)".dependencies]
99100
cc = "1"

src/cli/rustup_mode.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use clap::{
1010
Arg, ArgAction, ArgGroup, ArgMatches, Command, ValueEnum,
1111
};
1212
use clap_complete::Shell;
13+
use itertools::Itertools;
1314

1415
use crate::{
1516
cli::{
@@ -1334,11 +1335,22 @@ fn target_remove(cfg: &Cfg, m: &ArgMatches) -> Result<utils::ExitCode> {
13341335
let distributable = DistributableToolchain::try_from(&toolchain)?;
13351336

13361337
for target in m.get_many::<String>("target").unwrap() {
1337-
let new_component = Component::new(
1338-
"rust-std".to_string(),
1339-
Some(TargetTriple::new(target)),
1340-
false,
1341-
);
1338+
let target = TargetTriple::new(target);
1339+
let default_target = cfg.get_default_host_triple().ok();
1340+
if default_target.as_ref() == Some(&target) {
1341+
warn!("after removing the default host target, proc-macros and build scripts might no longer build");
1342+
}
1343+
let at_most_one_target = distributable.components().ok().and_then(|cs| {
1344+
// Every component target that is not `None` (wildcard).
1345+
let targets = cs
1346+
.iter()
1347+
.filter_map(|c| c.installed.then(|| c.component.target.clone()).flatten());
1348+
targets.unique().at_most_one().ok()
1349+
});
1350+
if at_most_one_target.is_some() {
1351+
warn!("after removing the last target, no build targets will be available");
1352+
}
1353+
let new_component = Component::new("rust-std".to_string(), Some(target), false);
13421354
distributable.remove_component(new_component)?;
13431355
}
13441356

tests/suite/cli_v2.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,9 +952,31 @@ fn remove_target_again() {
952952
#[test]
953953
fn remove_target_host() {
954954
setup(&|config| {
955-
let trip = this_host_triple();
955+
let host = this_host_triple();
956956
config.expect_ok(&["rustup", "default", "nightly"]);
957-
config.expect_ok(&["rustup", "target", "remove", &trip]);
957+
config.expect_ok(&["rustup", "target", "add", clitools::CROSS_ARCH1]);
958+
config.expect_stderr_ok(
959+
&["rustup", "target", "remove", &host],
960+
"after removing the default host target, proc-macros and build scripts might no longer build",
961+
);
962+
let path = format!("toolchains/nightly-{host}/lib/rustlib/{host}/lib/libstd.rlib");
963+
assert!(!config.rustupdir.has(path));
964+
let path = format!("toolchains/nightly-{host}/lib/rustlib/{host}/lib");
965+
assert!(!config.rustupdir.has(path));
966+
let path = format!("toolchains/nightly-{host}/lib/rustlib/{host}");
967+
assert!(!config.rustupdir.has(path));
968+
});
969+
}
970+
971+
#[test]
972+
fn remove_target_last() {
973+
setup(&|config| {
974+
let host = this_host_triple();
975+
config.expect_ok(&["rustup", "default", "nightly"]);
976+
config.expect_stderr_ok(
977+
&["rustup", "target", "remove", &host],
978+
"after removing the last target, no build targets will be available",
979+
);
958980
});
959981
}
960982

0 commit comments

Comments
 (0)