Skip to content

Commit bca2352

Browse files
authored
Merge pull request #1997 from jonhoo/conditional-update
Update to most recent viable nightly
2 parents 1e6b056 + 461bcb1 commit bca2352

File tree

6 files changed

+232
-85
lines changed

6 files changed

+232
-85
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ no-self-update = []
2222

2323
# Sorted by alphabetic order
2424
[dependencies]
25+
chrono = "0.4"
2526
clap = "2"
2627
download = { path = "download" }
2728
error-chain = "0.12"

src/dist/dist.rs

+74
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::dist::temp;
77
use crate::errors::*;
88
use crate::utils::utils;
99

10+
use chrono::prelude::*;
1011
use lazy_static::lazy_static;
1112
use regex::Regex;
1213

@@ -599,6 +600,77 @@ fn update_from_dist_<'a>(
599600
profile: Option<Profile>,
600601
prefix: &InstallPrefix,
601602
force_update: bool,
603+
) -> Result<Option<String>> {
604+
let mut toolchain = toolchain.clone();
605+
let mut fetched = String::new();
606+
let mut first_err = None;
607+
let backtrack = toolchain.channel == "nightly" && toolchain.date.is_none();
608+
loop {
609+
match try_update_from_dist_(
610+
download,
611+
update_hash,
612+
&toolchain,
613+
profile,
614+
prefix,
615+
force_update,
616+
&mut fetched,
617+
) {
618+
Ok(v) => break Ok(v),
619+
Err(e) => {
620+
if !backtrack {
621+
break Err(e);
622+
}
623+
624+
if let ErrorKind::RequestedComponentsUnavailable(components, ..) = e.kind() {
625+
(download.notify_handler)(Notification::SkippingNightlyMissingComponent(
626+
components,
627+
));
628+
629+
if first_err.is_none() {
630+
first_err = Some(e);
631+
}
632+
} else if let Some(e) = first_err {
633+
// if we fail to find a suitable nightly, we abort the search and give the
634+
// original "components unavailable for download" error.
635+
break Err(e);
636+
} else {
637+
break Err(e);
638+
}
639+
640+
// The user asked to update their nightly, but the latest nightly does not have all
641+
// the components that the user currently has installed. Let's try the previous
642+
// nightlies in reverse chronological order until we find a nightly that does,
643+
// starting at one date earlier than the current manifest's date.
644+
//
645+
// NOTE: we don't need to explicitly check for the case where the next nightly to
646+
// try is _older_ than the current nightly, since we know that the user's current
647+
// nightlys supports the components they have installed, and thus would always
648+
// terminate the search.
649+
toolchain.date = Some(
650+
Utc.from_utc_date(
651+
&NaiveDate::parse_from_str(
652+
toolchain.date.as_ref().unwrap_or(&fetched),
653+
"%Y-%m-%d",
654+
)
655+
.expect("Malformed manifest date"),
656+
)
657+
.pred()
658+
.format("%Y-%m-%d")
659+
.to_string(),
660+
);
661+
}
662+
}
663+
}
664+
}
665+
666+
fn try_update_from_dist_<'a>(
667+
download: DownloadCfg<'a>,
668+
update_hash: Option<&Path>,
669+
toolchain: &ToolchainDesc,
670+
profile: Option<Profile>,
671+
prefix: &InstallPrefix,
672+
force_update: bool,
673+
fetched: &mut String,
602674
) -> Result<Option<String>> {
603675
let toolchain_str = toolchain.to_string();
604676
let manifestation = Manifestation::open(prefix.clone(), toolchain.target.clone())?;
@@ -622,6 +694,8 @@ fn update_from_dist_<'a>(
622694
remove_components: Vec::new(),
623695
};
624696

697+
*fetched = m.date.clone();
698+
625699
return match manifestation.update(
626700
&m,
627701
changes,

src/dist/notifications.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::dist::dist::TargetTriple;
2+
use crate::dist::manifest::Component;
23
use crate::dist::temp;
34
use crate::errors::*;
45
use crate::utils::notify::NotificationLevel;
@@ -29,6 +30,7 @@ pub enum Notification<'a> {
2930
DownloadingManifest(&'a str),
3031
DownloadedManifest(&'a str, Option<&'a str>),
3132
DownloadingLegacyManifest,
33+
SkippingNightlyMissingComponent(&'a [Component]),
3234
ManifestChecksumFailedHack,
3335
ComponentUnavailable(&'a str, Option<&'a TargetTriple>),
3436
StrayHash(&'a Path),
@@ -66,6 +68,7 @@ impl<'a> Notification<'a> {
6668
| ManifestChecksumFailedHack
6769
| RollingBack
6870
| DownloadingManifest(_)
71+
| SkippingNightlyMissingComponent(_)
6972
| DownloadedManifest(_, _) => NotificationLevel::Info,
7073
CantReadUpdateHash(_)
7174
| ExtensionNotInstalled(_)
@@ -158,6 +161,11 @@ impl<'a> Display for Notification<'a> {
158161
"removing stray hash found at '{}' in order to continue",
159162
path.display()
160163
),
164+
SkippingNightlyMissingComponent(components) => write!(
165+
f,
166+
"skipping nightly which is missing installed component '{}'",
167+
components[0].short_name_in_manifest()
168+
),
161169
}
162170
}
163171
}

tests/cli-misc.rs

+40-10
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use crate::mock::clitools::{
88
expect_ok_eq, expect_ok_ex, expect_stderr_ok, expect_stdout_ok, run, set_current_dist_date,
99
this_host_triple, Config, Scenario,
1010
};
11-
use rustup::errors::TOOLSTATE_MSG;
1211
use rustup::utils::{raw, utils};
1312

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

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

743+
// latest nightly is unavailable
744744
set_current_dist_date(config, "2015-01-02");
745-
expect_err(
746-
config,
747-
&["rustup", "update", "nightly"],
748-
format!(
749-
"some components unavailable for download for channel nightly: 'rustc', 'cargo', 'rust-std', 'rust-docs'\n{}",
750-
TOOLSTATE_MSG
751-
)
752-
.as_str(),
753-
);
745+
// update should do nothing
746+
expect_ok(config, &["rustup", "update", "nightly", "--no-self-update"]);
747+
expect_stdout_ok(config, &["rustc", "--version"], "hash-n-1");
748+
});
749+
}
750+
751+
#[test]
752+
fn update_nightly_even_with_incompat() {
753+
clitools::setup(Scenario::MissingComponent, &|config| {
754+
set_current_dist_date(config, "2019-09-12");
755+
expect_ok(config, &["rustup", "default", "nightly"]);
756+
757+
expect_stdout_ok(config, &["rustc", "--version"], "hash-n-1");
758+
expect_ok(config, &["rustup", "component", "add", "rls"]);
759+
expect_component_executable(config, "rls");
760+
761+
// latest nightly is now one that does not have RLS
762+
set_current_dist_date(config, "2019-09-14");
754763

764+
expect_component_executable(config, "rls");
765+
// update should bring us to latest nightly that does
766+
expect_ok(config, &["rustup", "update", "nightly", "--no-self-update"]);
767+
expect_stdout_ok(config, &["rustc", "--version"], "hash-n-2");
768+
expect_component_executable(config, "rls");
769+
});
770+
}
771+
772+
#[test]
773+
fn nightly_backtrack_skips_missing() {
774+
clitools::setup(Scenario::Unavailable, &|config| {
775+
set_current_dist_date(config, "2015-01-01");
776+
expect_ok(config, &["rustup", "default", "nightly"]);
777+
778+
expect_stdout_ok(config, &["rustc", "--version"], "hash-n-1");
779+
780+
// nightly is missing on latest
781+
set_current_dist_date(config, "2015-01-02");
782+
783+
// update should not change nightly, and should not error
784+
expect_ok(config, &["rustup", "update", "nightly", "--no-self-update"]);
755785
expect_stdout_ok(config, &["rustc", "--version"], "hash-n-1");
756786
});
757787
}

0 commit comments

Comments
 (0)