Skip to content

Commit

Permalink
Merge pull request #2384 from dmarcoux/address-issue-2355
Browse files Browse the repository at this point in the history
Describe how to remove components when update fails
  • Loading branch information
kinnison authored Nov 17, 2020
2 parents fb49ed9 + df38b33 commit 8e77e51
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 9 deletions.
8 changes: 8 additions & 0 deletions src/dist/dist.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::env;
use std::fmt;
use std::ops::Deref;
use std::path::Path;
use std::str::FromStr;

Expand Down Expand Up @@ -178,6 +179,13 @@ impl FromStr for ParsedToolchainDesc {
}
}

impl Deref for TargetTriple {
type Target = str;
fn deref(&self) -> &Self::Target {
&self.0
}
}

impl TargetTriple {
pub fn new(name: &str) -> Self {
Self(name.to_string())
Expand Down
49 changes: 45 additions & 4 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,29 @@ fn valid_profile_names() -> String {
.join(", ")
}

fn remove_component_msg(cs: &Component, manifest: &Manifest, toolchain: &str) -> String {
if cs.short_name_in_manifest() == "rust-std" {
// We special-case rust-std as it's the stdlib so really you want to do
// rustup target remove
format!(
" rustup target remove --toolchain {} {}",
toolchain,
cs.target.as_deref().unwrap_or(toolchain)
)
} else {
format!(
" rustup component remove --toolchain {}{} {}",
toolchain,
if let Some(target) = cs.target.as_ref() {
format!(" --target {}", target)
} else {
String::default()
},
cs.short_name(manifest)
)
}
}

fn component_unavailable_msg(cs: &[Component], manifest: &Manifest, toolchain: &str) -> String {
assert!(!cs.is_empty());

Expand All @@ -411,6 +434,12 @@ fn component_unavailable_msg(cs: &[Component], manifest: &Manifest, toolchain: &
""
}
);

let _ = write!(
buf,
"If you don't need the component, you can remove it with:\n\n{}",
remove_component_msg(&cs[0], manifest, toolchain)
);
} else {
let same_target = cs
.iter()
Expand All @@ -421,21 +450,33 @@ fn component_unavailable_msg(cs: &[Component], manifest: &Manifest, toolchain: &
.map(|c| format!("'{}'", c.short_name(manifest)))
.collect::<Vec<_>>()
.join(", ");
let remove_msg = cs
.iter()
.map(|c| remove_component_msg(c, manifest, toolchain))
.collect::<Vec<_>>()
.join("\n");
let _ = write!(
buf,
"some components unavailable for download for channel {}: {}\n{}",
toolchain, cs_str, TOOLSTATE_MSG,
"some components unavailable for download for channel {}: {}
If you don't need the components, you can remove them with:\n\n{}\n\n{}",
toolchain, cs_str, remove_msg, TOOLSTATE_MSG,
);
} else {
let cs_str = cs
.iter()
.map(|c| c.description(manifest))
.collect::<Vec<_>>()
.join(", ");
let remove_msg = cs
.iter()
.map(|c| remove_component_msg(c, manifest, toolchain))
.collect::<Vec<_>>()
.join("\n");
let _ = write!(
buf,
"some components unavailable for download for channel {}: {}\n{}",
toolchain, cs_str, TOOLSTATE_MSG,
"some components unavailable for download for channel {}: {}
If you don't need the components, you can remove them with:\n{}\n{}",
toolchain, cs_str, remove_msg, TOOLSTATE_MSG,
);
}
}
Expand Down
181 changes: 176 additions & 5 deletions tests/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,9 @@ fn unavailable_component() {
)
.unwrap_err();
match *err.kind() {
ErrorKind::RequestedComponentsUnavailable(..) => {}
ErrorKind::RequestedComponentsUnavailable(..) => {
assert!(err.to_string().contains("rustup component remove --toolchain nightly --target x86_64-apple-darwin bonus"));
}
_ => panic!(),
}
},
Expand Down Expand Up @@ -823,7 +825,9 @@ fn unavailable_component_from_profile() {
)
.unwrap_err();
match *err.kind() {
ErrorKind::RequestedComponentsUnavailable(..) => {}
ErrorKind::RequestedComponentsUnavailable(..) => {
assert!(err.to_string().contains("rustup component remove --toolchain nightly --target x86_64-apple-darwin rustc"));
}
_ => panic!(),
}

Expand Down Expand Up @@ -889,17 +893,184 @@ fn removed_component() {

// Update without bonus, should fail with RequestedComponentsUnavailable
change_channel_date(url, "nightly", "2016-02-02");
assert!(update_from_dist(
let err = update_from_dist(
url,
toolchain,
prefix,
&[],
&[],
&download_cfg,
temp_cfg,
false,
)
.unwrap_err();
match *err.kind() {
ErrorKind::RequestedComponentsUnavailable(..) => {
assert!(err.to_string().contains("rustup component remove --toolchain nightly --target x86_64-apple-darwin bonus"));
}
_ => panic!(),
}
},
);
}

#[test]
fn unavailable_components_is_target() {
// On day 2 the rust-std component is no longer available
let edit = &|date: &str, chan: &mut MockChannel| {
// Mark the rust-std package as unavailable in 2016-02-02
if date == "2016-02-02" {
let pkg = chan
.packages
.iter_mut()
.find(|p| p.name == "rust-std")
.unwrap();

for target in &mut pkg.targets {
target.available = false;
}
}
};

setup(
Some(edit),
false,
&|url, toolchain, prefix, download_cfg, temp_cfg| {
let adds = [
Component::new(
"rust-std".to_string(),
Some(TargetTriple::new("i686-apple-darwin")),
false,
),
Component::new(
"rust-std".to_string(),
Some(TargetTriple::new("i686-unknown-linux-gnu")),
false,
),
];

// Update with rust-std
change_channel_date(url, "nightly", "2016-02-01");
update_from_dist(
url,
toolchain,
prefix,
&adds,
&[],
&download_cfg,
temp_cfg,
false,
)
.unwrap();

assert!(utils::path_exists(
&prefix.path().join("lib/i686-apple-darwin/libstd.rlib")
));
assert!(utils::path_exists(
&prefix.path().join("lib/i686-unknown-linux-gnu/libstd.rlib")
));

// Update without rust-std
change_channel_date(url, "nightly", "2016-02-02");
let err = update_from_dist(
url,
toolchain,
prefix,
&[],
&[],
&download_cfg,
temp_cfg,
false,
)
.unwrap_err();
match *err.kind() {
ErrorKind::RequestedComponentsUnavailable(..) => {
let err_str = err.to_string();
assert!(err_str
.contains("rustup target remove --toolchain nightly i686-apple-darwin"));
assert!(err_str.contains(
"rustup target remove --toolchain nightly i686-unknown-linux-gnu"
));
}
_ => panic!(),
}
},
);
}

#[test]
fn unavailable_components_with_same_target() {
// On day 2, the rust-std and rustc components are no longer available
let edit = &|date: &str, chan: &mut MockChannel| {
// Mark the rust-std package as unavailable in 2016-02-02
if date == "2016-02-02" {
let pkg = chan
.packages
.iter_mut()
.find(|p| p.name == "rust-std")
.unwrap();

for target in &mut pkg.targets {
target.available = false;
}
}

// Mark the rustc package as unavailable in 2016-02-02
if date == "2016-02-02" {
let pkg = chan
.packages
.iter_mut()
.find(|p| p.name == "rustc")
.unwrap();

for target in &mut pkg.targets {
target.available = false;
}
}
};

setup(
Some(edit),
false,
&|url, toolchain, prefix, download_cfg, temp_cfg| {
// Update with rust-std and rustc
change_channel_date(url, "nightly", "2016-02-01");
update_from_dist(
url,
toolchain,
prefix,
&[],
&[],
&download_cfg,
temp_cfg,
false,
)
.unwrap();
assert!(utils::path_exists(&prefix.path().join("bin/rustc")));
assert!(utils::path_exists(&prefix.path().join("lib/libstd.rlib")));

// Update without rust-std and rustc
change_channel_date(url, "nightly", "2016-02-02");
let err = update_from_dist(
url,
toolchain,
prefix,
&[],
&[],
&download_cfg,
temp_cfg,
false
false,
)
.is_err());
.unwrap_err();
match *err.kind() {
ErrorKind::RequestedComponentsUnavailable(..) => {
let err_str = err.to_string();
assert!(err_str
.contains("rustup target remove --toolchain nightly x86_64-apple-darwin"));
assert!(err_str.contains("rustup component remove --toolchain nightly --target x86_64-apple-darwin rustc"));
}
_ => panic!(),
}
},
);
}
Expand Down

0 comments on commit 8e77e51

Please sign in to comment.