Skip to content

Commit fd042e9

Browse files
committed
Don't search further back than installed nightly
This check is necessary for tests and other misbehaving repos where the currently installed nightly may suddenly turn out to no longer be a viable install candidate (e.g., because a component was retroactively removed).
1 parent 1b64788 commit fd042e9

File tree

3 files changed

+57
-14
lines changed

3 files changed

+57
-14
lines changed

src/dist/dist.rs

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@ pub fn update_from_dist<'a>(
564564
profile: Option<Profile>,
565565
prefix: &InstallPrefix,
566566
force_update: bool,
567+
old_date: Option<&str>,
567568
) -> Result<Option<String>> {
568569
let fresh_install = !prefix.path().exists();
569570
let hash_exists = update_hash.map(Path::exists).unwrap_or(false);
@@ -582,6 +583,7 @@ pub fn update_from_dist<'a>(
582583
profile,
583584
prefix,
584585
force_update,
586+
old_date,
585587
);
586588

587589
// Don't leave behind an empty / broken installation directory
@@ -600,11 +602,29 @@ fn update_from_dist_<'a>(
600602
profile: Option<Profile>,
601603
prefix: &InstallPrefix,
602604
force_update: bool,
605+
old_date: Option<&str>,
603606
) -> Result<Option<String>> {
604607
let mut toolchain = toolchain.clone();
605608
let mut fetched = String::new();
606609
let mut first_err = None;
607610
let backtrack = toolchain.channel == "nightly" && toolchain.date.is_none();
611+
612+
// We never want to backtrack further back than the nightly that's already installed.
613+
//
614+
// If no nightly is installed, it makes no sense to backtrack beyond the first ever manifest,
615+
// which is 2014-12-20 according to
616+
// https://static.rust-lang.org/cargo-dist/index.html.
617+
//
618+
// We could arguably use the date of the first rustup release here, but that would break a
619+
// bunch of the tests, which (inexplicably) use 2015-01-01 as their manifest dates.
620+
let first_manifest = old_date
621+
.map(|date| {
622+
Utc.from_utc_date(
623+
&NaiveDate::parse_from_str(date, "%Y-%m-%d").expect("Malformed manifest date"),
624+
)
625+
})
626+
.unwrap_or_else(|| Utc.from_utc_date(&NaiveDate::from_ymd(2014, 12, 20)));
627+
608628
loop {
609629
match try_update_from_dist_(
610630
download,
@@ -644,23 +664,28 @@ fn update_from_dist_<'a>(
644664
// the components that the user currently has installed. Let's try the previous
645665
// nightlies in reverse chronological order until we find a nightly that does,
646666
// starting at one date earlier than the current manifest's date.
647-
//
648-
// NOTE: we don't need to explicitly check for the case where the next nightly to
649-
// try is _older_ than the current nightly, since we know that the user's current
650-
// nightlys supports the components they have installed, and thus would always
651-
// terminate the search.
652-
toolchain.date = Some(
653-
Utc.from_utc_date(
667+
let try_next = Utc
668+
.from_utc_date(
654669
&NaiveDate::parse_from_str(
655670
toolchain.date.as_ref().unwrap_or(&fetched),
656671
"%Y-%m-%d",
657672
)
658673
.expect("Malformed manifest date"),
659674
)
660-
.pred()
661-
.format("%Y-%m-%d")
662-
.to_string(),
663-
);
675+
.pred();
676+
677+
if try_next < first_manifest {
678+
// Wouldn't be an update if we go further back than the user's current nightly.
679+
if let Some(e) = first_err {
680+
break Err(e);
681+
} else {
682+
// In this case, all newer nightlies are missing, which means there are no
683+
// updates, so the user is already at the latest nightly.
684+
break Ok(None);
685+
}
686+
}
687+
688+
toolchain.date = Some(try_next.format("%Y-%m-%d").to_string());
664689
}
665690
}
666691
}

src/install.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ pub enum InstallMethod<'a> {
2626
bool,
2727
// toolchain already exists
2828
bool,
29+
// currently installed date
30+
Option<&'a str>,
2931
),
3032
}
3133

@@ -54,7 +56,15 @@ impl<'a> InstallMethod<'a> {
5456
InstallMethod::tar_gz(src, path, &temp_cfg, notify_handler)?;
5557
Ok(true)
5658
}
57-
InstallMethod::Dist(toolchain, profile, update_hash, dl_cfg, force_update, exists) => {
59+
InstallMethod::Dist(
60+
toolchain,
61+
profile,
62+
update_hash,
63+
dl_cfg,
64+
force_update,
65+
exists,
66+
old_date,
67+
) => {
5868
let prefix = &InstallPrefix::from(path.to_owned());
5969
let maybe_new_hash = dist::update_from_dist(
6070
dl_cfg,
@@ -63,6 +73,7 @@ impl<'a> InstallMethod<'a> {
6373
if exists { None } else { profile },
6474
prefix,
6575
force_update,
76+
old_date,
6677
)?;
6778

6879
if let Some(hash) = maybe_new_hash {

src/toolchain.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,15 @@ impl<'a> Toolchain<'a> {
164164

165165
pub fn install_from_dist(&self, force_update: bool) -> Result<UpdateStatus> {
166166
let update_hash = self.update_hash()?;
167+
let old_date = self.get_manifest().ok().and_then(|m| m.map(|m| m.date));
167168
self.install(InstallMethod::Dist(
168169
&self.desc()?,
169170
self.cfg.get_profile()?,
170171
update_hash.as_ref().map(|p| &**p),
171172
self.download_cfg(),
172173
force_update,
173174
self.exists(),
175+
old_date.as_ref().map(|s| &**s),
174176
))
175177
}
176178

@@ -183,6 +185,7 @@ impl<'a> Toolchain<'a> {
183185
self.download_cfg(),
184186
false,
185187
false,
188+
None,
186189
))
187190
}
188191
pub fn is_custom(&self) -> bool {
@@ -470,7 +473,7 @@ impl<'a> Toolchain<'a> {
470473
})
471474
}
472475

473-
pub fn show_version(&self) -> Result<Option<String>> {
476+
pub fn get_manifest(&self) -> Result<Option<Manifest>> {
474477
if !self.exists() {
475478
return Err(ErrorKind::ToolchainNotInstalled(self.name.to_owned()).into());
476479
}
@@ -481,7 +484,11 @@ impl<'a> Toolchain<'a> {
481484
let prefix = InstallPrefix::from(self.path.to_owned());
482485
let manifestation = Manifestation::open(prefix, toolchain.target.clone())?;
483486

484-
match manifestation.load_manifest()? {
487+
manifestation.load_manifest()
488+
}
489+
490+
pub fn show_version(&self) -> Result<Option<String>> {
491+
match self.get_manifest()? {
485492
Some(manifest) => Ok(Some(manifest.get_rust_version()?.to_string())),
486493
None => Ok(None),
487494
}

0 commit comments

Comments
 (0)