Skip to content

Commit

Permalink
Merge pull request #1997 from jonhoo/conditional-update
Browse files Browse the repository at this point in the history
Update to most recent viable nightly
  • Loading branch information
kinnison committed Sep 17, 2019
2 parents 1e6b056 + 461bcb1 commit bca2352
Show file tree
Hide file tree
Showing 6 changed files with 232 additions and 85 deletions.
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
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
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
@@ -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
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

0 comments on commit bca2352

Please sign in to comment.