From f959736dd1d62ac45dc61f4b908deb80b42459bd Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Fri, 27 Sep 2019 21:59:15 +0200 Subject: [PATCH 1/8] update_from_dist_: Better panic on malformed manifest date Signed-off-by: Daniel Silverstone --- src/dist/dist.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/dist/dist.rs b/src/dist/dist.rs index ab01575d2c..b789a12b52 100644 --- a/src/dist/dist.rs +++ b/src/dist/dist.rs @@ -670,7 +670,10 @@ fn update_from_dist_<'a>( toolchain.date.as_ref().unwrap_or(&fetched), "%Y-%m-%d", ) - .expect("Malformed manifest date"), + .expect(&format!( + "Malformed manifest date: {:?}", + toolchain.date.as_ref().unwrap_or(&fetched) + )), ) .pred(); From bdcf19470200917f7f52c96c4c38cb49dd07711d Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Fri, 27 Sep 2019 18:49:51 +0200 Subject: [PATCH 2/8] Support installation with additional components and targets Add support for "-c" and "-t" to `rustup toolchain install` and to `rustup-init` itself. Signed-off-by: Daniel Silverstone --- rustup-init.sh | 2 ++ src/cli/rustup_mode.rs | 26 +++++++++++++++++++++++- src/cli/self_update.rs | 10 ++++++++-- src/cli/setup_mode.rs | 28 ++++++++++++++++++++++++++ src/config.rs | 6 +++--- src/dist/dist.rs | 45 ++++++++++++++++++++++++++++++++++++++++-- src/install.rs | 8 ++++++++ src/toolchain.rs | 11 ++++++++++- tests/cli-self-upd.rs | 29 +++++++++++++++++++++++++++ tests/cli-v2.rs | 31 +++++++++++++++++++++++++++++ 10 files changed, 187 insertions(+), 9 deletions(-) diff --git a/rustup-init.sh b/rustup-init.sh index f45fbb6936..5097ee5ec6 100755 --- a/rustup-init.sh +++ b/rustup-init.sh @@ -31,6 +31,8 @@ OPTIONS: --default-toolchain Choose a default toolchain to install --default-toolchain none Do not install any toolchains --profile [minimal|default|complete] Choose a profile + -c, --component ... Component name to also install + -t, --target ... Target name to also install EOF } diff --git a/src/cli/rustup_mode.rs b/src/cli/rustup_mode.rs index 790abbba74..4bd6008490 100644 --- a/src/cli/rustup_mode.rs +++ b/src/cli/rustup_mode.rs @@ -256,6 +256,22 @@ pub fn cli() -> App<'static, 'static> { .help("Don't perform self update when running the `rustup toolchain install` command") .long("no-self-update") .takes_value(false) + ) + .arg( + Arg::with_name("components") + .help("Add specific components on installation") + .long("component") + .short("c") + .takes_value(true) + .multiple(true) + ) + .arg( + Arg::with_name("targets") + .help("Add specific targets on installation") + .long("target") + .short("t") + .takes_value(true) + .multiple(true) ), ) .subcommand( @@ -741,7 +757,15 @@ fn update(cfg: &Cfg, m: &ArgMatches<'_>) -> Result<()> { let toolchain = cfg.get_toolchain(name, false)?; let status = if !toolchain.is_custom() { - Some(toolchain.install_from_dist(m.is_present("force"))?) + let components: Vec<_> = m + .values_of("components") + .map(|v| v.collect()) + .unwrap_or_else(Vec::new); + let targets: Vec<_> = m + .values_of("targets") + .map(|v| v.collect()) + .unwrap_or_else(Vec::new); + Some(toolchain.install_from_dist(m.is_present("force"), &components, &targets)?) } else if !toolchain.exists() { return Err(ErrorKind::InvalidToolchainName(toolchain.name().to_string()).into()); } else { diff --git a/src/cli/self_update.rs b/src/cli/self_update.rs index 3dee088320..77d60a166e 100644 --- a/src/cli/self_update.rs +++ b/src/cli/self_update.rs @@ -45,11 +45,13 @@ use std::fs; use std::path::{Component, Path, PathBuf}; use std::process::{self, Command}; -pub struct InstallOpts { +pub struct InstallOpts<'a> { pub default_host_triple: String, pub default_toolchain: String, pub profile: String, pub no_modify_path: bool, + pub components: &'a [&'a str], + pub targets: &'a [&'a str], } #[cfg(feature = "no-self-update")] @@ -283,6 +285,8 @@ pub fn install(no_prompt: bool, verbose: bool, quiet: bool, mut opts: InstallOpt &opts.default_toolchain, &opts.profile, &opts.default_host_triple, + opts.components, + opts.targets, verbose, quiet, )?; @@ -737,6 +741,8 @@ fn maybe_install_rust( toolchain_str: &str, profile_str: &str, default_host_triple: &str, + components: &[&str], + targets: &[&str], verbose: bool, quiet: bool, ) -> Result<()> { @@ -754,7 +760,7 @@ fn maybe_install_rust( // Set host triple first as it will affect resolution of toolchain_str cfg.set_default_host_triple(default_host_triple)?; let toolchain = cfg.get_toolchain(toolchain_str, false)?; - let status = toolchain.install_from_dist(false)?; + let status = toolchain.install_from_dist(false, components, targets)?; cfg.set_default(toolchain_str)?; println!(); common::show_channel_update(&cfg, toolchain_str, Ok(status))?; diff --git a/src/cli/setup_mode.rs b/src/cli/setup_mode.rs index 301409c25a..16713d3881 100644 --- a/src/cli/setup_mode.rs +++ b/src/cli/setup_mode.rs @@ -61,6 +61,22 @@ pub fn main() -> Result<()> { .possible_values(Profile::names()) .default_value(Profile::default_name()), ) + .arg( + Arg::with_name("components") + .help("Component name to also install") + .long("component") + .short("c") + .takes_value(true) + .multiple(true), + ) + .arg( + Arg::with_name("targets") + .help("Target name to also install") + .long("target") + .short("target") + .takes_value(true) + .multiple(true), + ) .arg( Arg::with_name("no-modify-path") .long("no-modify-path") @@ -81,11 +97,23 @@ pub fn main() -> Result<()> { .expect("Unreachable: Clap should supply a default"); let no_modify_path = matches.is_present("no-modify-path"); + let components: Vec<_> = matches + .values_of("components") + .map(|v| v.collect()) + .unwrap_or_else(Vec::new); + + let targets: Vec<_> = matches + .values_of("targets") + .map(|v| v.collect()) + .unwrap_or_else(Vec::new); + let opts = InstallOpts { default_host_triple: default_host, default_toolchain: default_toolchain.to_owned(), profile: profile.to_owned(), no_modify_path, + components: &components, + targets: &targets, }; self_update::install(no_prompt, verbose, quiet, opts)?; diff --git a/src/config.rs b/src/config.rs index bb065f9469..68c1364e82 100644 --- a/src/config.rs +++ b/src/config.rs @@ -304,7 +304,7 @@ impl Cfg { ErrorKind::OverrideToolchainNotInstalled(name.to_string()) }) } else { - toolchain.install_from_dist(false)?; + toolchain.install_from_dist(false, &[], &[])?; Ok(Some((toolchain, reason))) } } @@ -413,7 +413,7 @@ impl Cfg { // Update toolchains and collect the results let channels = channels.map(|(n, t)| { let t = t.and_then(|t| { - let t = t.install_from_dist(force_update); + let t = t.install_from_dist(force_update, &[], &[]); if let Err(ref e) = t { (self.notify_handler)(Notification::NonFatalError(e)); } @@ -465,7 +465,7 @@ impl Cfg { ) -> Result { let toolchain = self.get_toolchain(toolchain, false)?; if install_if_missing && !toolchain.exists() { - toolchain.install_from_dist(false)?; + toolchain.install_from_dist(false, &[], &[])?; } if let Some(cmd) = self.maybe_do_cargo_fallback(&toolchain, binary)? { diff --git a/src/dist/dist.rs b/src/dist/dist.rs index b789a12b52..0a37c53140 100644 --- a/src/dist/dist.rs +++ b/src/dist/dist.rs @@ -565,6 +565,8 @@ pub fn update_from_dist<'a>( prefix: &InstallPrefix, force_update: bool, old_date: Option<&str>, + components: &[&str], + targets: &[&str], ) -> Result> { let fresh_install = !prefix.path().exists(); let hash_exists = update_hash.map(Path::exists).unwrap_or(false); @@ -584,6 +586,8 @@ pub fn update_from_dist<'a>( prefix, force_update, old_date, + components, + targets, ); // Don't leave behind an empty / broken installation directory @@ -603,6 +607,8 @@ fn update_from_dist_<'a>( prefix: &InstallPrefix, force_update: bool, old_date: Option<&str>, + components: &[&str], + targets: &[&str], ) -> Result> { let mut toolchain = toolchain.clone(); let mut fetched = String::new(); @@ -633,6 +639,8 @@ fn update_from_dist_<'a>( profile, prefix, force_update, + components, + targets, &mut fetched, ) { Ok(v) => break Ok(v), @@ -701,6 +709,8 @@ fn try_update_from_dist_<'a>( profile: Option, prefix: &InstallPrefix, force_update: bool, + components: &[&str], + targets: &[&str], fetched: &mut String, ) -> Result> { let toolchain_str = toolchain.to_string(); @@ -708,7 +718,15 @@ fn try_update_from_dist_<'a>( // TODO: Add a notification about which manifest version is going to be used (download.notify_handler)(Notification::DownloadingManifest(&toolchain_str)); - match dl_v2_manifest(download, update_hash, toolchain) { + match dl_v2_manifest( + download, + if components.is_empty() && targets.is_empty() { + update_hash + } else { + None + }, + toolchain, + ) { Ok(Some((m, hash))) => { (download.notify_handler)(Notification::DownloadedManifest( &m.date, @@ -720,11 +738,34 @@ fn try_update_from_dist_<'a>( None => Vec::new(), }; - let changes = Changes { + let mut changes = Changes { explicit_add_components: profile_components, remove_components: Vec::new(), }; + for component in components { + let mut component = crate::dist::manifest::Component::new( + component.to_string(), + Some(toolchain.target.clone()), + false, + ); + if let Some(renamed) = m.rename_component(&component) { + component = renamed; + } + changes.explicit_add_components.push(component); + } + + for target in targets { + let triple = TargetTriple::new(target); + changes + .explicit_add_components + .push(crate::dist::manifest::Component::new( + "rust-std".to_string(), + Some(triple), + false, + )); + } + *fetched = m.date.clone(); return match manifestation.update( diff --git a/src/install.rs b/src/install.rs index fee576112c..17ffef170b 100644 --- a/src/install.rs +++ b/src/install.rs @@ -28,6 +28,10 @@ pub enum InstallMethod<'a> { bool, // currently installed date Option<&'a str>, + // Extra components to install from dist + &'a [&'a str], + // Extra targets to install from dist + &'a [&'a str], ), } @@ -64,6 +68,8 @@ impl<'a> InstallMethod<'a> { force_update, exists, old_date, + components, + targets, ) => { let prefix = &InstallPrefix::from(path.to_owned()); let maybe_new_hash = dist::update_from_dist( @@ -74,6 +80,8 @@ impl<'a> InstallMethod<'a> { prefix, force_update, old_date, + components, + targets, )?; if let Some(hash) = maybe_new_hash { diff --git a/src/toolchain.rs b/src/toolchain.rs index 2a8a5070bb..225e4e7f44 100644 --- a/src/toolchain.rs +++ b/src/toolchain.rs @@ -162,7 +162,12 @@ impl<'a> Toolchain<'a> { } } - pub fn install_from_dist(&self, force_update: bool) -> Result { + pub fn install_from_dist( + &self, + force_update: bool, + components: &[&str], + targets: &[&str], + ) -> Result { let update_hash = self.update_hash()?; let old_date = self.get_manifest().ok().and_then(|m| m.map(|m| m.date)); self.install(InstallMethod::Dist( @@ -173,6 +178,8 @@ impl<'a> Toolchain<'a> { force_update, self.exists(), old_date.as_ref().map(|s| &**s), + components, + targets, )) } @@ -186,6 +193,8 @@ impl<'a> Toolchain<'a> { false, false, None, + &[], + &[], )) } pub fn is_custom(&self) -> bool { diff --git a/tests/cli-self-upd.rs b/tests/cli-self-upd.rs index 95424347d2..b41bb96cbd 100644 --- a/tests/cli-self-upd.rs +++ b/tests/cli-self-upd.rs @@ -1258,3 +1258,32 @@ fn update_installs_clippy_cargo_and() { assert!(cargo_clippy_path.exists()); }); } + +#[test] +fn install_with_components_and_targets() { + setup(&|config| { + expect_ok( + config, + &[ + "rustup-init", + "--default-toolchain", + "nightly", + "-y", + "-c", + "rls", + "-t", + clitools::CROSS_ARCH1, + ], + ); + expect_stdout_ok( + config, + &["rustup", "target", "list"], + &format!("{} (installed)", clitools::CROSS_ARCH1), + ); + expect_stdout_ok( + config, + &["rustup", "component", "list"], + &format!("rls-{} (installed)", this_host_triple()), + ); + }) +} diff --git a/tests/cli-v2.rs b/tests/cli-v2.rs index eb1d0233c8..6fbfa07d11 100644 --- a/tests/cli-v2.rs +++ b/tests/cli-v2.rs @@ -1109,3 +1109,34 @@ fn target_list_ignores_unavailable_targets() { expect_not_stdout_ok(config, target_list, clitools::CROSS_ARCH1); }) } + +#[test] +fn install_with_component_and_target() { + setup(&|config| { + expect_ok(config, &["rustup", "default", "nightly"]); + expect_ok( + config, + &[ + "rustup", + "toolchain", + "install", + "nightly", + "-c", + "rls", + "-t", + clitools::CROSS_ARCH1, + "--no-self-update", + ], + ); + expect_stdout_ok( + config, + &["rustup", "component", "list"], + &format!("rls-{} (installed)", this_host_triple()), + ); + expect_stdout_ok( + config, + &["rustup", "target", "list"], + &format!("{} (installed)", clitools::CROSS_ARCH1), + ); + }) +} From e2e2aa8d1a2bc84438e96e53ad1c72b93e334e6a Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 28 Sep 2019 10:54:05 +0200 Subject: [PATCH 3/8] Deduplicate components during installation Signed-off-by: Daniel Silverstone --- src/dist/dist.rs | 30 +++++++++++++----------------- src/dist/manifest.rs | 2 +- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/dist/dist.rs b/src/dist/dist.rs index 0a37c53140..d095bdca90 100644 --- a/src/dist/dist.rs +++ b/src/dist/dist.rs @@ -738,34 +738,30 @@ fn try_update_from_dist_<'a>( None => Vec::new(), }; - let mut changes = Changes { - explicit_add_components: profile_components, - remove_components: Vec::new(), - }; + use crate::dist::manifest::Component; + use std::collections::HashSet; + + let mut all_components: HashSet = profile_components.into_iter().collect(); for component in components { - let mut component = crate::dist::manifest::Component::new( - component.to_string(), - Some(toolchain.target.clone()), - false, - ); + let mut component = + Component::new(component.to_string(), Some(toolchain.target.clone()), false); if let Some(renamed) = m.rename_component(&component) { component = renamed; } - changes.explicit_add_components.push(component); + all_components.insert(component); } for target in targets { let triple = TargetTriple::new(target); - changes - .explicit_add_components - .push(crate::dist::manifest::Component::new( - "rust-std".to_string(), - Some(triple), - false, - )); + all_components.insert(Component::new("rust-std".to_string(), Some(triple), false)); } + let changes = Changes { + explicit_add_components: all_components.into_iter().collect(), + remove_components: Vec::new(), + }; + *fetched = m.date.clone(); return match manifestation.update( diff --git a/src/dist/manifest.rs b/src/dist/manifest.rs index 4db405c7ab..ecc8586132 100644 --- a/src/dist/manifest.rs +++ b/src/dist/manifest.rs @@ -56,7 +56,7 @@ pub struct PackageBins { pub xz_hash: Option, } -#[derive(Clone, Debug, Eq, Ord, PartialOrd)] +#[derive(Clone, Debug, Eq, Ord, PartialOrd, Hash)] pub struct Component { pkg: String, pub target: Option, From 787edfe303ae49aa85a7eb141c43ea3c540a013d Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 28 Sep 2019 11:20:01 +0200 Subject: [PATCH 4/8] dist: Limit backtracking to 20 if we can't find a component In order to ensure that if the user names a component during installation which we will never be able to find we stop, introduce a limit to backtracking in the case of a fresh installation. Signed-off-by: Daniel Silverstone --- src/dist/dist.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/dist/dist.rs b/src/dist/dist.rs index d095bdca90..63edf54737 100644 --- a/src/dist/dist.rs +++ b/src/dist/dist.rs @@ -614,6 +614,19 @@ fn update_from_dist_<'a>( let mut fetched = String::new(); let mut first_err = None; let backtrack = toolchain.channel == "nightly" && toolchain.date.is_none(); + // We want to limit backtracking if we do not already have a toolchain + let mut backtrack_limit: Option = if toolchain.date.is_some() { + None + } else { + // We limit the backtracking to 21 days by default (half a release cycle). + // The limit of 21 days is an arbitrary selection, so we let the user override it. + const BACKTRACK_LIMIT_DEFAULT: i32 = 21; + let provided = env::var("RUSTUP_BACKTRACK_LIMIT") + .ok() + .and_then(|v| v.parse().ok()) + .unwrap_or(BACKTRACK_LIMIT_DEFAULT); + Some(if provided < 1 { 1 } else { provided }) + }; // We never want to backtrack further back than the nightly that's already installed. // @@ -657,6 +670,10 @@ fn update_from_dist_<'a>( if first_err.is_none() { first_err = Some(e); } + // We decrement the backtrack count only on unavailable component errors + // so that the limit only applies to nightlies that were indeed available, + // and ignores missing ones. + backtrack_limit = backtrack_limit.map(|n| n - 1); } else if let ErrorKind::MissingReleaseForToolchain(..) = e.kind() { // no need to even print anything for missing nightlies, // since we don't really "skip" them @@ -668,6 +685,14 @@ fn update_from_dist_<'a>( break Err(e); } + if let Some(backtrack_limit) = backtrack_limit { + if backtrack_limit < 1 { + // This unwrap is safe because we can only hit this if we've + // had a chance to set first_err + break Err(first_err.unwrap()); + } + } + // The user asked to update their nightly, but the latest nightly does not have all // the components that the user currently has installed. Let's try the previous // nightlies in reverse chronological order until we find a nightly that does, @@ -720,6 +745,9 @@ fn try_update_from_dist_<'a>( (download.notify_handler)(Notification::DownloadingManifest(&toolchain_str)); match dl_v2_manifest( download, + // Even if manifest has not changed, we must continue to install requested components. + // So if components or targets is not empty, we skip passing `update_hash` so that + // we essentially degenerate to `rustup component add` / `rustup target add` if components.is_empty() && targets.is_empty() { update_hash } else { From fe4f5b5e8aacd2dd865fb922248d61bc0e58098a Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 28 Sep 2019 17:52:57 +0200 Subject: [PATCH 5/8] Sort components to make tests stable Signed-off-by: Daniel Silverstone --- src/dist/dist.rs | 5 ++- tests/cli-exact.rs | 16 ++++---- tests/cli-rustup.rs | 92 +++++++++++++++++++++---------------------- tests/cli-self-upd.rs | 8 ++-- 4 files changed, 62 insertions(+), 59 deletions(-) diff --git a/src/dist/dist.rs b/src/dist/dist.rs index 63edf54737..f8703d6521 100644 --- a/src/dist/dist.rs +++ b/src/dist/dist.rs @@ -785,8 +785,11 @@ fn try_update_from_dist_<'a>( all_components.insert(Component::new("rust-std".to_string(), Some(triple), false)); } + let mut explicit_add_components: Vec<_> = all_components.into_iter().collect(); + explicit_add_components.sort(); + let changes = Changes { - explicit_add_components: all_components.into_iter().collect(), + explicit_add_components, remove_components: Vec::new(), }; diff --git a/tests/cli-exact.rs b/tests/cli-exact.rs index d8ea109767..8b9e64cc38 100644 --- a/tests/cli-exact.rs +++ b/tests/cli-exact.rs @@ -33,14 +33,14 @@ fn update() { for_host!( r"info: syncing channel updates for 'nightly-{0}' info: latest update on 2015-01-02, rust version 1.3.0 (hash-nightly-2) -info: downloading component 'rustc' info: downloading component 'cargo' -info: downloading component 'rust-std' info: downloading component 'rust-docs' -info: installing component 'rustc' +info: downloading component 'rust-std' +info: downloading component 'rustc' info: installing component 'cargo' -info: installing component 'rust-std' info: installing component 'rust-docs' +info: installing component 'rust-std' +info: installing component 'rustc' info: default toolchain set to 'nightly-{0}' " ), @@ -167,14 +167,14 @@ fn default() { for_host!( r"info: syncing channel updates for 'nightly-{0}' info: latest update on 2015-01-02, rust version 1.3.0 (hash-nightly-2) -info: downloading component 'rustc' info: downloading component 'cargo' -info: downloading component 'rust-std' info: downloading component 'rust-docs' -info: installing component 'rustc' +info: downloading component 'rust-std' +info: downloading component 'rustc' info: installing component 'cargo' -info: installing component 'rust-std' info: installing component 'rust-docs' +info: installing component 'rust-std' +info: installing component 'rustc' info: default toolchain set to 'nightly-{0}' " ), diff --git a/tests/cli-rustup.rs b/tests/cli-rustup.rs index edb2b2ad6b..3247e7a0a4 100644 --- a/tests/cli-rustup.rs +++ b/tests/cli-rustup.rs @@ -47,18 +47,18 @@ fn rustup_stable() { for_host!( r"info: syncing channel updates for 'stable-{0}' info: latest update on 2015-01-02, rust version 1.1.0 (hash-stable-1.1.0) -info: downloading component 'rustc' info: downloading component 'cargo' -info: downloading component 'rust-std' info: downloading component 'rust-docs' -info: removing previous version of component 'rustc' +info: downloading component 'rust-std' +info: downloading component 'rustc' info: removing previous version of component 'cargo' -info: removing previous version of component 'rust-std' info: removing previous version of component 'rust-docs' -info: installing component 'rustc' +info: removing previous version of component 'rust-std' +info: removing previous version of component 'rustc' info: installing component 'cargo' -info: installing component 'rust-std' info: installing component 'rust-docs' +info: installing component 'rust-std' +info: installing component 'rustc' " ), ); @@ -86,18 +86,18 @@ fn rustup_stable_quiet() { for_host!( r"info: syncing channel updates for 'stable-{0}' info: latest update on 2015-01-02, rust version 1.1.0 (hash-stable-1.1.0) -info: downloading component 'rustc' info: downloading component 'cargo' -info: downloading component 'rust-std' info: downloading component 'rust-docs' -info: removing previous version of component 'rustc' +info: downloading component 'rust-std' +info: downloading component 'rustc' info: removing previous version of component 'cargo' -info: removing previous version of component 'rust-std' info: removing previous version of component 'rust-docs' -info: installing component 'rustc' +info: removing previous version of component 'rust-std' +info: removing previous version of component 'rustc' info: installing component 'cargo' -info: installing component 'rust-std' info: installing component 'rust-docs' +info: installing component 'rust-std' +info: installing component 'rustc' " ), ); @@ -148,46 +148,46 @@ fn rustup_all_channels() { for_host!( r"info: syncing channel updates for 'stable-{0}' info: latest update on 2015-01-02, rust version 1.1.0 (hash-stable-1.1.0) -info: downloading component 'rustc' info: downloading component 'cargo' -info: downloading component 'rust-std' info: downloading component 'rust-docs' -info: removing previous version of component 'rustc' +info: downloading component 'rust-std' +info: downloading component 'rustc' info: removing previous version of component 'cargo' -info: removing previous version of component 'rust-std' info: removing previous version of component 'rust-docs' -info: installing component 'rustc' +info: removing previous version of component 'rust-std' +info: removing previous version of component 'rustc' info: installing component 'cargo' -info: installing component 'rust-std' info: installing component 'rust-docs' +info: installing component 'rust-std' +info: installing component 'rustc' info: syncing channel updates for 'beta-{0}' info: latest update on 2015-01-02, rust version 1.2.0 (hash-beta-1.2.0) -info: downloading component 'rustc' info: downloading component 'cargo' -info: downloading component 'rust-std' info: downloading component 'rust-docs' -info: removing previous version of component 'rustc' +info: downloading component 'rust-std' +info: downloading component 'rustc' info: removing previous version of component 'cargo' -info: removing previous version of component 'rust-std' info: removing previous version of component 'rust-docs' -info: installing component 'rustc' +info: removing previous version of component 'rust-std' +info: removing previous version of component 'rustc' info: installing component 'cargo' -info: installing component 'rust-std' info: installing component 'rust-docs' +info: installing component 'rust-std' +info: installing component 'rustc' info: syncing channel updates for 'nightly-{0}' info: latest update on 2015-01-02, rust version 1.3.0 (hash-nightly-2) -info: downloading component 'rustc' info: downloading component 'cargo' -info: downloading component 'rust-std' info: downloading component 'rust-docs' -info: removing previous version of component 'rustc' +info: downloading component 'rust-std' +info: downloading component 'rustc' info: removing previous version of component 'cargo' -info: removing previous version of component 'rust-std' info: removing previous version of component 'rust-docs' -info: installing component 'rustc' +info: removing previous version of component 'rust-std' +info: removing previous version of component 'rustc' info: installing component 'cargo' -info: installing component 'rust-std' info: installing component 'rust-docs' +info: installing component 'rust-std' +info: installing component 'rustc' " ), ); @@ -217,33 +217,33 @@ fn rustup_some_channels_up_to_date() { for_host!( r"info: syncing channel updates for 'stable-{0}' info: latest update on 2015-01-02, rust version 1.1.0 (hash-stable-1.1.0) -info: downloading component 'rustc' info: downloading component 'cargo' -info: downloading component 'rust-std' info: downloading component 'rust-docs' -info: removing previous version of component 'rustc' +info: downloading component 'rust-std' +info: downloading component 'rustc' info: removing previous version of component 'cargo' -info: removing previous version of component 'rust-std' info: removing previous version of component 'rust-docs' -info: installing component 'rustc' +info: removing previous version of component 'rust-std' +info: removing previous version of component 'rustc' info: installing component 'cargo' -info: installing component 'rust-std' info: installing component 'rust-docs' +info: installing component 'rust-std' +info: installing component 'rustc' info: syncing channel updates for 'beta-{0}' info: syncing channel updates for 'nightly-{0}' info: latest update on 2015-01-02, rust version 1.3.0 (hash-nightly-2) -info: downloading component 'rustc' info: downloading component 'cargo' -info: downloading component 'rust-std' info: downloading component 'rust-docs' -info: removing previous version of component 'rustc' +info: downloading component 'rust-std' +info: downloading component 'rustc' info: removing previous version of component 'cargo' -info: removing previous version of component 'rust-std' info: removing previous version of component 'rust-docs' -info: installing component 'rustc' +info: removing previous version of component 'rust-std' +info: removing previous version of component 'rustc' info: installing component 'cargo' -info: installing component 'rust-std' info: installing component 'rust-docs' +info: installing component 'rust-std' +info: installing component 'rustc' " ), ); @@ -280,14 +280,14 @@ fn default() { for_host!( r"info: syncing channel updates for 'nightly-{0}' info: latest update on 2015-01-02, rust version 1.3.0 (hash-nightly-2) -info: downloading component 'rustc' info: downloading component 'cargo' -info: downloading component 'rust-std' info: downloading component 'rust-docs' -info: installing component 'rustc' +info: downloading component 'rust-std' +info: downloading component 'rustc' info: installing component 'cargo' -info: installing component 'rust-std' info: installing component 'rust-docs' +info: installing component 'rust-std' +info: installing component 'rustc' info: default toolchain set to 'nightly-{0}' " ), diff --git a/tests/cli-self-upd.rs b/tests/cli-self-upd.rs index b41bb96cbd..be8962932b 100644 --- a/tests/cli-self-upd.rs +++ b/tests/cli-self-upd.rs @@ -870,14 +870,14 @@ fn first_install_exact() { for_host!( r"info: syncing channel updates for 'stable-{0}' info: latest update on 2015-01-02, rust version 1.1.0 (hash-stable-1.1.0) -info: downloading component 'rustc' info: downloading component 'cargo' -info: downloading component 'rust-std' info: downloading component 'rust-docs' -info: installing component 'rustc' +info: downloading component 'rust-std' +info: downloading component 'rustc' info: installing component 'cargo' -info: installing component 'rust-std' info: installing component 'rust-docs' +info: installing component 'rust-std' +info: installing component 'rustc' info: default toolchain set to 'stable' " ), From 56395c099652d7f4087e30105105361c9f5aac41 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 28 Sep 2019 22:29:14 +0200 Subject: [PATCH 6/8] manifest: Implement Hash directly on Component Signed-off-by: Daniel Silverstone --- src/dist/manifest.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/dist/manifest.rs b/src/dist/manifest.rs index ecc8586132..955a4c60f7 100644 --- a/src/dist/manifest.rs +++ b/src/dist/manifest.rs @@ -15,6 +15,7 @@ use crate::utils::toml_utils::*; use crate::dist::dist::{Profile, TargetTriple}; use std::collections::HashMap; +use std::hash::{Hash, Hasher}; use std::str::FromStr; pub const SUPPORTED_MANIFEST_VERSIONS: [&str; 1] = ["2"]; @@ -56,7 +57,7 @@ pub struct PackageBins { pub xz_hash: Option, } -#[derive(Clone, Debug, Eq, Ord, PartialOrd, Hash)] +#[derive(Clone, Debug, Eq, Ord, PartialOrd)] pub struct Component { pkg: String, pub target: Option, @@ -71,6 +72,16 @@ impl PartialEq for Component { } } +impl Hash for Component { + fn hash(&self, hasher: &mut H) + where + H: Hasher, + { + self.pkg.hash(hasher); + self.target.hash(hasher); + } +} + impl Manifest { pub fn parse(data: &str) -> Result { let value = toml::from_str(data).map_err(ErrorKind::Parsing)?; From 2bc6e87e51b40390ca2afea48feca888231feaec Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 28 Sep 2019 22:29:54 +0200 Subject: [PATCH 7/8] dist: Fix clippy issue with .expect Signed-off-by: Daniel Silverstone --- src/dist/dist.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/dist/dist.rs b/src/dist/dist.rs index f8703d6521..09cfb2f915 100644 --- a/src/dist/dist.rs +++ b/src/dist/dist.rs @@ -703,10 +703,12 @@ fn update_from_dist_<'a>( toolchain.date.as_ref().unwrap_or(&fetched), "%Y-%m-%d", ) - .expect(&format!( - "Malformed manifest date: {:?}", - toolchain.date.as_ref().unwrap_or(&fetched) - )), + .unwrap_or_else(|_| { + panic!( + "Malformed manifest date: {:?}", + toolchain.date.as_ref().unwrap_or(&fetched) + ) + }), ) .pred(); From 75c04916a899c47d580142fd7440af6316cac7c1 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Mon, 30 Sep 2019 08:04:54 +0200 Subject: [PATCH 8/8] CONTRIBUTING: Document the backtrack limit Signed-off-by: Daniel Silverstone --- CONTRIBUTING.md | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 78b8924c11..2999b69b13 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,7 +20,7 @@ affecting any existing installation. Remember to keep those two environment vari set when running your compiled `rustup-init` or the toolchains it installs, but _unset_ when rebuilding `rustup` itself. -We use `rustfmt` to keep our codebase consistently formatted. Please ensure that +We use `rustfmt` to keep our codebase consistently formatted. Please ensure that you have correctly formatted your code (most editors will do this automatically when saving) or it may not pass the CI tests. @@ -46,11 +46,11 @@ The first part is always the binary name as per `clap`'s normal operation. The version number is a combination of the most recent tag in the git repo, and the number of commits since that tag. The parenthesised information is, naturally, the SHA of the most recent commit and the date of that commit. If the indication -of a dirty tree is present, the number of changes is indicated. This combines +of a dirty tree is present, the number of changes is indicated. This combines adds, deletes, modifies, and unknown entries. You can request further information of a `rustup` binary with the -`rustup dump-testament` hidden command. It produces output of the form: +`rustup dump-testament` hidden command. It produces output of the form: ```shell $ rustup dump-testament @@ -64,25 +64,25 @@ Modified: CONTRIBUTING.md This can be handy when you are testing development versions on your PC and cannot remember exactly which version you had installed, or if you have given a development copy (or instruction to build such) to a user, and wish to have them -confirm *exactly* what they are using. +confirm _exactly_ what they are using. Finally, we tell `git-testament` that we trust the `stable` branch to carry -releases. If the build is being performed when not on the `stable` branch, and +releases. If the build is being performed when not on the `stable` branch, and the tag and `CARGO_PKG_VERSION` differ, then the short version string will include both, in the form `rustup-init 1.18.3 :: 1.18.2+99 (a54051502 2019-05-26)` which indicates the crate version before the rest of the commit. On the other hand, if the build was on the `stable` branch then regardless of the tag information, providing the commit was clean, the version is -always replaced by the crate version. The `dump-testament` hidden command can +always replaced by the crate version. The `dump-testament` hidden command can reveal the truth however. ## Making a release Before making a release, ensure that `rustup-init.sh` is behaving correctly, and that you're satisfied that nothing in the ecosystem is breaking because -of the update. A useful set of things to check includes verifying that +of the update. A useful set of things to check includes verifying that real-world toolchains install okay, and that `rls-vscode` isn't broken by -the release. While it's not our responsibility if they depend on non-stable +the release. While it's not our responsibility if they depend on non-stable APIs, we should behave well if we can. Producing the final release artifacts is a bit involved because of the way @@ -107,10 +107,10 @@ Rustup is distributed. The steps for a release are: anything egregious in which case abort the change and roll back. 8. Once the official release has happened, prepare and push a tag of that commit, and also push the content to master - * `git tag -as $VER_NUM -m $VER_NUM` (optionally without -s if not GPG + - `git tag -as $VER_NUM -m $VER_NUM` (optionally without -s if not GPG signing the tag) - * `git push origin HEAD:master` - * `git push origin $VER_NUM` + - `git push origin HEAD:master` + - `git push origin $VER_NUM` ## Developer tips and tricks @@ -125,6 +125,17 @@ run. $ RUSTUP_FORCE_ARG0=rustup cargo run -- uninstall nightly ``` +### `RUSTUP_BACKTRACK_LIMIT` + +If it's necessary to alter the backtracking limit from the default of half +a release cycle for some reason, you can set the `RUSTUP_BACKTRACK_LIMIT` +environment variable. If this is unparseable as an `i32` or if it's absent +then the default of 21 days (half a cycle) is used. If it parses and is less +than 1, it is clamped to 1 at minimum. + +This is not meant for use by users, but can be suggested in diagnosing an issue +should one arise with the backtrack limits. + ### `RUSTUP_BACKTRACE` By default while running tests, we unset some environment variables that will