Skip to content

Commit 860a370

Browse files
committed
Update to most recent viable nightly
Previously, if the user had components installed on `nightly` which were not available for the latest nightly, `rustup update` would not update the user's nightly at all. With this patch, rustup will try progressively older nightlies until it finds a nightly that supports all the components the user has installed for their current nightly. Fixes rust-lang#1628. Makes progress towards rust-lang#1501. Fixes the underlying issue in rust-lang#1676.
1 parent ec6d1af commit 860a370

File tree

6 files changed

+217
-75
lines changed

6 files changed

+217
-75
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
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

Lines changed: 78 additions & 0 deletions
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,81 @@ 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 backtrack = toolchain.channel == "nightly" && toolchain.date.is_none();
607+
loop {
608+
match try_update_from_dist_(
609+
download,
610+
update_hash,
611+
&toolchain,
612+
profile,
613+
prefix,
614+
force_update,
615+
&mut fetched,
616+
) {
617+
Ok(v) => break Ok(v),
618+
Err(e) => {
619+
if !backtrack {
620+
break Err(e);
621+
}
622+
623+
let components =
624+
if let ErrorKind::RequestedComponentsUnavailable(components, ..) = e.kind() {
625+
components
626+
} else {
627+
break Err(e);
628+
};
629+
630+
(download.notify_handler)(Notification::SkippingNightlyMissingComponent(
631+
components,
632+
));
633+
634+
// The user asked to update their nightly, but the latest nightly does not have all
635+
// the components that the user currently has installed. Let's try the previous
636+
// nightly (recursively) until we find a nightly that does.
637+
//
638+
// NOTE: we don't need to explicitly check for the case where the next nightly to
639+
// try is _older_ than the current nightly, since we know that the user's current
640+
// nightlys supports the components they have installed, and thus would always
641+
// terminate the search.
642+
if let Some(ref mut date) = toolchain.date {
643+
// recurse
644+
toolchain.date = Some(
645+
Utc.from_utc_date(
646+
&NaiveDate::parse_from_str(date, "%Y-%m-%d")
647+
.expect("we constructed this date string below"),
648+
)
649+
.pred()
650+
.format("%Y-%m-%d")
651+
.to_string(),
652+
);
653+
} else {
654+
// Pick a nightly that is one day older than the latest.
655+
toolchain.date = Some(
656+
Utc.from_utc_date(
657+
&NaiveDate::parse_from_str(&fetched, "%Y-%m-%d")
658+
.expect("manifest carries invalid date"),
659+
)
660+
.pred()
661+
.format("%Y-%m-%d")
662+
.to_string(),
663+
);
664+
}
665+
}
666+
}
667+
}
668+
}
669+
670+
fn try_update_from_dist_<'a>(
671+
download: DownloadCfg<'a>,
672+
update_hash: Option<&Path>,
673+
toolchain: &ToolchainDesc,
674+
profile: Option<Profile>,
675+
prefix: &InstallPrefix,
676+
force_update: bool,
677+
fetched: &mut String,
602678
) -> Result<Option<String>> {
603679
let toolchain_str = toolchain.to_string();
604680
let manifestation = Manifestation::open(prefix.clone(), toolchain.target.clone())?;
@@ -622,6 +698,8 @@ fn update_from_dist_<'a>(
622698
remove_components: Vec::new(),
623699
};
624700

701+
*fetched = m.date.clone();
702+
625703
return match manifestation.update(
626704
&m,
627705
changes,

src/dist/notifications.rs

Lines changed: 8 additions & 0 deletions
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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,27 @@ fn update_unavailable_rustc() {
756756
});
757757
}
758758

759+
#[test]
760+
fn update_nightly_even_with_incompat() {
761+
clitools::setup(Scenario::MissingComponent, &|config| {
762+
set_current_dist_date(config, "2019-09-12");
763+
expect_ok(config, &["rustup", "default", "nightly"]);
764+
765+
expect_stdout_ok(config, &["rustc", "--version"], "hash-n-1");
766+
expect_ok(config, &["rustup", "component", "add", "rls"]);
767+
expect_component_executable(config, "rls");
768+
769+
// latest nightly is now one that does not have RLS
770+
set_current_dist_date(config, "2019-09-14");
771+
772+
expect_component_executable(config, "rls");
773+
// update should bring us to latest nightly that does
774+
expect_ok(config, &["rustup", "update", "nightly", "--no-self-update"]);
775+
expect_stdout_ok(config, &["rustc", "--version"], "hash-n-2");
776+
expect_component_executable(config, "rls");
777+
});
778+
}
779+
759780
#[test]
760781
fn completion_rustup() {
761782
setup(&|config| {

0 commit comments

Comments
 (0)