@@ -564,6 +564,7 @@ pub fn update_from_dist<'a>(
564
564
profile : Option < Profile > ,
565
565
prefix : & InstallPrefix ,
566
566
force_update : bool ,
567
+ old_date : Option < & str > ,
567
568
) -> Result < Option < String > > {
568
569
let fresh_install = !prefix. path ( ) . exists ( ) ;
569
570
let hash_exists = update_hash. map ( Path :: exists) . unwrap_or ( false ) ;
@@ -582,6 +583,7 @@ pub fn update_from_dist<'a>(
582
583
profile,
583
584
prefix,
584
585
force_update,
586
+ old_date,
585
587
) ;
586
588
587
589
// Don't leave behind an empty / broken installation directory
@@ -600,11 +602,29 @@ fn update_from_dist_<'a>(
600
602
profile : Option < Profile > ,
601
603
prefix : & InstallPrefix ,
602
604
force_update : bool ,
605
+ old_date : Option < & str > ,
603
606
) -> Result < Option < String > > {
604
607
let mut toolchain = toolchain. clone ( ) ;
605
608
let mut fetched = String :: new ( ) ;
606
609
let mut first_err = None ;
607
610
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
+
608
628
loop {
609
629
match try_update_from_dist_ (
610
630
download,
@@ -644,23 +664,28 @@ fn update_from_dist_<'a>(
644
664
// the components that the user currently has installed. Let's try the previous
645
665
// nightlies in reverse chronological order until we find a nightly that does,
646
666
// 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 (
654
669
& NaiveDate :: parse_from_str (
655
670
toolchain. date . as_ref ( ) . unwrap_or ( & fetched) ,
656
671
"%Y-%m-%d" ,
657
672
)
658
673
. expect ( "Malformed manifest date" ) ,
659
674
)
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 ( ) ) ;
664
689
}
665
690
}
666
691
}
0 commit comments