Skip to content

Update to most recent viable nightly #1997

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

Merged
merged 2 commits into from
Sep 17, 2019
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ no-self-update = []

# Sorted by alphabetic order
[dependencies]
chrono = "0.4"
clap = "2"
download = { path = "download" }
error-chain = "0.12"
Expand Down
74 changes: 74 additions & 0 deletions src/dist/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::dist::temp;
use crate::errors::*;
use crate::utils::utils;

use chrono::prelude::*;
use lazy_static::lazy_static;
use regex::Regex;

Expand Down Expand Up @@ -599,6 +600,77 @@ fn update_from_dist_<'a>(
profile: Option<Profile>,
prefix: &InstallPrefix,
force_update: bool,
) -> Result<Option<String>> {
let mut toolchain = toolchain.clone();
let mut fetched = String::new();
let mut first_err = None;
let backtrack = toolchain.channel == "nightly" && toolchain.date.is_none();
loop {
match try_update_from_dist_(
download,
update_hash,
&toolchain,
profile,
prefix,
force_update,
&mut fetched,
) {
Ok(v) => break Ok(v),
Err(e) => {
if !backtrack {
break Err(e);
}

if let ErrorKind::RequestedComponentsUnavailable(components, ..) = e.kind() {
(download.notify_handler)(Notification::SkippingNightlyMissingComponent(
components,
));

if first_err.is_none() {
first_err = Some(e);
}
} else if let Some(e) = first_err {
// if we fail to find a suitable nightly, we abort the search and give the
// original "components unavailable for download" error.
break Err(e);
} else {
break Err(e);
}

// 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,
// starting at one date earlier than the current manifest's date.
//
// NOTE: we don't need to explicitly check for the case where the next nightly to
// try is _older_ than the current nightly, since we know that the user's current
// nightlys supports the components they have installed, and thus would always
// terminate the search.
toolchain.date = Some(
Utc.from_utc_date(
&NaiveDate::parse_from_str(
toolchain.date.as_ref().unwrap_or(&fetched),
"%Y-%m-%d",
)
.expect("Malformed manifest date"),
)
.pred()
.format("%Y-%m-%d")
.to_string(),
);
}
}
}
}

fn try_update_from_dist_<'a>(
download: DownloadCfg<'a>,
update_hash: Option<&Path>,
toolchain: &ToolchainDesc,
profile: Option<Profile>,
prefix: &InstallPrefix,
force_update: bool,
fetched: &mut String,
) -> Result<Option<String>> {
let toolchain_str = toolchain.to_string();
let manifestation = Manifestation::open(prefix.clone(), toolchain.target.clone())?;
Expand All @@ -622,6 +694,8 @@ fn update_from_dist_<'a>(
remove_components: Vec::new(),
};

*fetched = m.date.clone();

return match manifestation.update(
&m,
changes,
Expand Down
8 changes: 8 additions & 0 deletions src/dist/notifications.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::dist::dist::TargetTriple;
use crate::dist::manifest::Component;
use crate::dist::temp;
use crate::errors::*;
use crate::utils::notify::NotificationLevel;
Expand Down Expand Up @@ -29,6 +30,7 @@ pub enum Notification<'a> {
DownloadingManifest(&'a str),
DownloadedManifest(&'a str, Option<&'a str>),
DownloadingLegacyManifest,
SkippingNightlyMissingComponent(&'a [Component]),
ManifestChecksumFailedHack,
ComponentUnavailable(&'a str, Option<&'a TargetTriple>),
StrayHash(&'a Path),
Expand Down Expand Up @@ -66,6 +68,7 @@ impl<'a> Notification<'a> {
| ManifestChecksumFailedHack
| RollingBack
| DownloadingManifest(_)
| SkippingNightlyMissingComponent(_)
| DownloadedManifest(_, _) => NotificationLevel::Info,
CantReadUpdateHash(_)
| ExtensionNotInstalled(_)
Expand Down Expand Up @@ -158,6 +161,11 @@ impl<'a> Display for Notification<'a> {
"removing stray hash found at '{}' in order to continue",
path.display()
),
SkippingNightlyMissingComponent(components) => write!(
f,
"skipping nightly which is missing installed component '{}'",
components[0].short_name_in_manifest()
),
}
}
}
50 changes: 40 additions & 10 deletions tests/cli-misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use crate::mock::clitools::{
expect_ok_eq, expect_ok_ex, expect_stderr_ok, expect_stdout_ok, run, set_current_dist_date,
this_host_triple, Config, Scenario,
};
use rustup::errors::TOOLSTATE_MSG;
use rustup::utils::{raw, utils};

use std::env::consts::EXE_SUFFIX;
Expand Down Expand Up @@ -741,17 +740,48 @@ fn update_unavailable_rustc() {

expect_stdout_ok(config, &["rustc", "--version"], "hash-n-1");

// latest nightly is unavailable
set_current_dist_date(config, "2015-01-02");
expect_err(
config,
&["rustup", "update", "nightly"],
format!(
"some components unavailable for download for channel nightly: 'rustc', 'cargo', 'rust-std', 'rust-docs'\n{}",
TOOLSTATE_MSG
)
.as_str(),
);
// update should do nothing
expect_ok(config, &["rustup", "update", "nightly", "--no-self-update"]);
expect_stdout_ok(config, &["rustc", "--version"], "hash-n-1");
});
}

#[test]
fn update_nightly_even_with_incompat() {
clitools::setup(Scenario::MissingComponent, &|config| {
set_current_dist_date(config, "2019-09-12");
expect_ok(config, &["rustup", "default", "nightly"]);

expect_stdout_ok(config, &["rustc", "--version"], "hash-n-1");
expect_ok(config, &["rustup", "component", "add", "rls"]);
expect_component_executable(config, "rls");

// latest nightly is now one that does not have RLS
set_current_dist_date(config, "2019-09-14");

expect_component_executable(config, "rls");
// update should bring us to latest nightly that does
expect_ok(config, &["rustup", "update", "nightly", "--no-self-update"]);
expect_stdout_ok(config, &["rustc", "--version"], "hash-n-2");
expect_component_executable(config, "rls");
});
}

#[test]
fn nightly_backtrack_skips_missing() {
clitools::setup(Scenario::Unavailable, &|config| {
set_current_dist_date(config, "2015-01-01");
expect_ok(config, &["rustup", "default", "nightly"]);

expect_stdout_ok(config, &["rustc", "--version"], "hash-n-1");

// nightly is missing on latest
set_current_dist_date(config, "2015-01-02");

// update should not change nightly, and should not error
expect_ok(config, &["rustup", "update", "nightly", "--no-self-update"]);
expect_stdout_ok(config, &["rustc", "--version"], "hash-n-1");
});
}
Expand Down
Loading