Skip to content

Commit 8e77e51

Browse files
authored
Merge pull request #2384 from dmarcoux/address-issue-2355
Describe how to remove components when update fails
2 parents fb49ed9 + df38b33 commit 8e77e51

File tree

3 files changed

+229
-9
lines changed

3 files changed

+229
-9
lines changed

src/dist/dist.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::env;
22
use std::fmt;
3+
use std::ops::Deref;
34
use std::path::Path;
45
use std::str::FromStr;
56

@@ -178,6 +179,13 @@ impl FromStr for ParsedToolchainDesc {
178179
}
179180
}
180181

182+
impl Deref for TargetTriple {
183+
type Target = str;
184+
fn deref(&self) -> &Self::Target {
185+
&self.0
186+
}
187+
}
188+
181189
impl TargetTriple {
182190
pub fn new(name: &str) -> Self {
183191
Self(name.to_string())

src/errors.rs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,29 @@ fn valid_profile_names() -> String {
394394
.join(", ")
395395
}
396396

397+
fn remove_component_msg(cs: &Component, manifest: &Manifest, toolchain: &str) -> String {
398+
if cs.short_name_in_manifest() == "rust-std" {
399+
// We special-case rust-std as it's the stdlib so really you want to do
400+
// rustup target remove
401+
format!(
402+
" rustup target remove --toolchain {} {}",
403+
toolchain,
404+
cs.target.as_deref().unwrap_or(toolchain)
405+
)
406+
} else {
407+
format!(
408+
" rustup component remove --toolchain {}{} {}",
409+
toolchain,
410+
if let Some(target) = cs.target.as_ref() {
411+
format!(" --target {}", target)
412+
} else {
413+
String::default()
414+
},
415+
cs.short_name(manifest)
416+
)
417+
}
418+
}
419+
397420
fn component_unavailable_msg(cs: &[Component], manifest: &Manifest, toolchain: &str) -> String {
398421
assert!(!cs.is_empty());
399422

@@ -411,6 +434,12 @@ fn component_unavailable_msg(cs: &[Component], manifest: &Manifest, toolchain: &
411434
""
412435
}
413436
);
437+
438+
let _ = write!(
439+
buf,
440+
"If you don't need the component, you can remove it with:\n\n{}",
441+
remove_component_msg(&cs[0], manifest, toolchain)
442+
);
414443
} else {
415444
let same_target = cs
416445
.iter()
@@ -421,21 +450,33 @@ fn component_unavailable_msg(cs: &[Component], manifest: &Manifest, toolchain: &
421450
.map(|c| format!("'{}'", c.short_name(manifest)))
422451
.collect::<Vec<_>>()
423452
.join(", ");
453+
let remove_msg = cs
454+
.iter()
455+
.map(|c| remove_component_msg(c, manifest, toolchain))
456+
.collect::<Vec<_>>()
457+
.join("\n");
424458
let _ = write!(
425459
buf,
426-
"some components unavailable for download for channel {}: {}\n{}",
427-
toolchain, cs_str, TOOLSTATE_MSG,
460+
"some components unavailable for download for channel {}: {}
461+
If you don't need the components, you can remove them with:\n\n{}\n\n{}",
462+
toolchain, cs_str, remove_msg, TOOLSTATE_MSG,
428463
);
429464
} else {
430465
let cs_str = cs
431466
.iter()
432467
.map(|c| c.description(manifest))
433468
.collect::<Vec<_>>()
434469
.join(", ");
470+
let remove_msg = cs
471+
.iter()
472+
.map(|c| remove_component_msg(c, manifest, toolchain))
473+
.collect::<Vec<_>>()
474+
.join("\n");
435475
let _ = write!(
436476
buf,
437-
"some components unavailable for download for channel {}: {}\n{}",
438-
toolchain, cs_str, TOOLSTATE_MSG,
477+
"some components unavailable for download for channel {}: {}
478+
If you don't need the components, you can remove them with:\n{}\n{}",
479+
toolchain, cs_str, remove_msg, TOOLSTATE_MSG,
439480
);
440481
}
441482
}

tests/dist.rs

Lines changed: 176 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,9 @@ fn unavailable_component() {
764764
)
765765
.unwrap_err();
766766
match *err.kind() {
767-
ErrorKind::RequestedComponentsUnavailable(..) => {}
767+
ErrorKind::RequestedComponentsUnavailable(..) => {
768+
assert!(err.to_string().contains("rustup component remove --toolchain nightly --target x86_64-apple-darwin bonus"));
769+
}
768770
_ => panic!(),
769771
}
770772
},
@@ -823,7 +825,9 @@ fn unavailable_component_from_profile() {
823825
)
824826
.unwrap_err();
825827
match *err.kind() {
826-
ErrorKind::RequestedComponentsUnavailable(..) => {}
828+
ErrorKind::RequestedComponentsUnavailable(..) => {
829+
assert!(err.to_string().contains("rustup component remove --toolchain nightly --target x86_64-apple-darwin rustc"));
830+
}
827831
_ => panic!(),
828832
}
829833

@@ -889,17 +893,184 @@ fn removed_component() {
889893

890894
// Update without bonus, should fail with RequestedComponentsUnavailable
891895
change_channel_date(url, "nightly", "2016-02-02");
892-
assert!(update_from_dist(
896+
let err = update_from_dist(
897+
url,
898+
toolchain,
899+
prefix,
900+
&[],
901+
&[],
902+
&download_cfg,
903+
temp_cfg,
904+
false,
905+
)
906+
.unwrap_err();
907+
match *err.kind() {
908+
ErrorKind::RequestedComponentsUnavailable(..) => {
909+
assert!(err.to_string().contains("rustup component remove --toolchain nightly --target x86_64-apple-darwin bonus"));
910+
}
911+
_ => panic!(),
912+
}
913+
},
914+
);
915+
}
916+
917+
#[test]
918+
fn unavailable_components_is_target() {
919+
// On day 2 the rust-std component is no longer available
920+
let edit = &|date: &str, chan: &mut MockChannel| {
921+
// Mark the rust-std package as unavailable in 2016-02-02
922+
if date == "2016-02-02" {
923+
let pkg = chan
924+
.packages
925+
.iter_mut()
926+
.find(|p| p.name == "rust-std")
927+
.unwrap();
928+
929+
for target in &mut pkg.targets {
930+
target.available = false;
931+
}
932+
}
933+
};
934+
935+
setup(
936+
Some(edit),
937+
false,
938+
&|url, toolchain, prefix, download_cfg, temp_cfg| {
939+
let adds = [
940+
Component::new(
941+
"rust-std".to_string(),
942+
Some(TargetTriple::new("i686-apple-darwin")),
943+
false,
944+
),
945+
Component::new(
946+
"rust-std".to_string(),
947+
Some(TargetTriple::new("i686-unknown-linux-gnu")),
948+
false,
949+
),
950+
];
951+
952+
// Update with rust-std
953+
change_channel_date(url, "nightly", "2016-02-01");
954+
update_from_dist(
955+
url,
956+
toolchain,
957+
prefix,
958+
&adds,
959+
&[],
960+
&download_cfg,
961+
temp_cfg,
962+
false,
963+
)
964+
.unwrap();
965+
966+
assert!(utils::path_exists(
967+
&prefix.path().join("lib/i686-apple-darwin/libstd.rlib")
968+
));
969+
assert!(utils::path_exists(
970+
&prefix.path().join("lib/i686-unknown-linux-gnu/libstd.rlib")
971+
));
972+
973+
// Update without rust-std
974+
change_channel_date(url, "nightly", "2016-02-02");
975+
let err = update_from_dist(
976+
url,
977+
toolchain,
978+
prefix,
979+
&[],
980+
&[],
981+
&download_cfg,
982+
temp_cfg,
983+
false,
984+
)
985+
.unwrap_err();
986+
match *err.kind() {
987+
ErrorKind::RequestedComponentsUnavailable(..) => {
988+
let err_str = err.to_string();
989+
assert!(err_str
990+
.contains("rustup target remove --toolchain nightly i686-apple-darwin"));
991+
assert!(err_str.contains(
992+
"rustup target remove --toolchain nightly i686-unknown-linux-gnu"
993+
));
994+
}
995+
_ => panic!(),
996+
}
997+
},
998+
);
999+
}
1000+
1001+
#[test]
1002+
fn unavailable_components_with_same_target() {
1003+
// On day 2, the rust-std and rustc components are no longer available
1004+
let edit = &|date: &str, chan: &mut MockChannel| {
1005+
// Mark the rust-std package as unavailable in 2016-02-02
1006+
if date == "2016-02-02" {
1007+
let pkg = chan
1008+
.packages
1009+
.iter_mut()
1010+
.find(|p| p.name == "rust-std")
1011+
.unwrap();
1012+
1013+
for target in &mut pkg.targets {
1014+
target.available = false;
1015+
}
1016+
}
1017+
1018+
// Mark the rustc package as unavailable in 2016-02-02
1019+
if date == "2016-02-02" {
1020+
let pkg = chan
1021+
.packages
1022+
.iter_mut()
1023+
.find(|p| p.name == "rustc")
1024+
.unwrap();
1025+
1026+
for target in &mut pkg.targets {
1027+
target.available = false;
1028+
}
1029+
}
1030+
};
1031+
1032+
setup(
1033+
Some(edit),
1034+
false,
1035+
&|url, toolchain, prefix, download_cfg, temp_cfg| {
1036+
// Update with rust-std and rustc
1037+
change_channel_date(url, "nightly", "2016-02-01");
1038+
update_from_dist(
1039+
url,
1040+
toolchain,
1041+
prefix,
1042+
&[],
1043+
&[],
1044+
&download_cfg,
1045+
temp_cfg,
1046+
false,
1047+
)
1048+
.unwrap();
1049+
assert!(utils::path_exists(&prefix.path().join("bin/rustc")));
1050+
assert!(utils::path_exists(&prefix.path().join("lib/libstd.rlib")));
1051+
1052+
// Update without rust-std and rustc
1053+
change_channel_date(url, "nightly", "2016-02-02");
1054+
let err = update_from_dist(
8931055
url,
8941056
toolchain,
8951057
prefix,
8961058
&[],
8971059
&[],
8981060
&download_cfg,
8991061
temp_cfg,
900-
false
1062+
false,
9011063
)
902-
.is_err());
1064+
.unwrap_err();
1065+
match *err.kind() {
1066+
ErrorKind::RequestedComponentsUnavailable(..) => {
1067+
let err_str = err.to_string();
1068+
assert!(err_str
1069+
.contains("rustup target remove --toolchain nightly x86_64-apple-darwin"));
1070+
assert!(err_str.contains("rustup component remove --toolchain nightly --target x86_64-apple-darwin rustc"));
1071+
}
1072+
_ => panic!(),
1073+
}
9031074
},
9041075
);
9051076
}

0 commit comments

Comments
 (0)