Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Describe how to remove components when update fails #2384

Merged
merged 3 commits into from
Nov 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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