68
68
69
69
use crate :: core:: dependency:: Dependency ;
70
70
use crate :: core:: { PackageId , SourceId , Summary } ;
71
- use crate :: sources:: registry:: { RegistryData , RegistryPackage } ;
71
+ use crate :: sources:: registry:: { RegistryData , RegistryPackage , INDEX_V_MAX } ;
72
72
use crate :: util:: interning:: InternedString ;
73
73
use crate :: util:: paths;
74
74
use crate :: util:: { internal, CargoResult , Config , Filesystem , ToSemver } ;
75
75
use anyhow:: bail;
76
76
use log:: { debug, info} ;
77
77
use semver:: { Version , VersionReq } ;
78
78
use std:: collections:: { HashMap , HashSet } ;
79
+ use std:: convert:: TryInto ;
79
80
use std:: fs;
80
81
use std:: path:: Path ;
81
82
use std:: str;
@@ -309,7 +310,7 @@ impl<'cfg> RegistryIndex<'cfg> {
309
310
// necessary.
310
311
let raw_data = & summaries. raw_data ;
311
312
let max_version = if namespaced_features || weak_dep_features {
312
- 2
313
+ INDEX_V_MAX
313
314
} else {
314
315
1
315
316
} ;
@@ -571,6 +572,14 @@ impl Summaries {
571
572
let summary = match IndexSummary :: parse ( config, line, source_id) {
572
573
Ok ( summary) => summary,
573
574
Err ( e) => {
575
+ // This should only happen when there is an index
576
+ // entry from a future version of cargo that this
577
+ // version doesn't understand. Hopefully, those future
578
+ // versions of cargo correctly set INDEX_V_MAX and
579
+ // CURRENT_CACHE_VERSION, otherwise this will skip
580
+ // entries in the cache preventing those newer
581
+ // versions from reading them (that is, until the
582
+ // cache is rebuilt).
574
583
log:: info!( "failed to parse {:?} registry package: {}" , relative, e) ;
575
584
continue ;
576
585
}
@@ -658,9 +667,9 @@ impl Summaries {
658
667
// Implementation of serializing/deserializing the cache of summaries on disk.
659
668
// Currently the format looks like:
660
669
//
661
- // +--------------+-------------+---+
662
- // | version byte | git sha rev | 0 |
663
- // +--------------+-------------+---+
670
+ // +--------------------+---------------------- +-------------+---+
671
+ // | cache version byte | index format version | git sha rev | 0 |
672
+ // +--------------------+---------------------- +-------------+---+
664
673
//
665
674
// followed by...
666
675
//
@@ -677,8 +686,14 @@ impl Summaries {
677
686
// versions of Cargo share the same cache they don't get too confused. The git
678
687
// sha lets us know when the file needs to be regenerated (it needs regeneration
679
688
// whenever the index itself updates).
689
+ //
690
+ // Cache versions:
691
+ // * `1`: The original version.
692
+ // * `2`: Added the "index format version" field so that if the index format
693
+ // changes, different versions of cargo won't get confused reading each
694
+ // other's caches.
680
695
681
- const CURRENT_CACHE_VERSION : u8 = 1 ;
696
+ const CURRENT_CACHE_VERSION : u8 = 2 ;
682
697
683
698
impl < ' a > SummariesCache < ' a > {
684
699
fn parse ( data : & ' a [ u8 ] , last_index_update : & str ) -> CargoResult < SummariesCache < ' a > > {
@@ -689,6 +704,19 @@ impl<'a> SummariesCache<'a> {
689
704
if * first_byte != CURRENT_CACHE_VERSION {
690
705
bail ! ( "looks like a different Cargo's cache, bailing out" ) ;
691
706
}
707
+ let index_v_bytes = rest
708
+ . get ( ..4 )
709
+ . ok_or_else ( || anyhow:: anyhow!( "cache expected 4 bytes for index version" ) ) ?;
710
+ let index_v = u32:: from_le_bytes ( index_v_bytes. try_into ( ) . unwrap ( ) ) ;
711
+ if index_v > INDEX_V_MAX {
712
+ bail ! (
713
+ "index format version {} is greater than the newest version I know ({})" ,
714
+ index_v,
715
+ INDEX_V_MAX
716
+ ) ;
717
+ }
718
+ let rest = & rest[ 4 ..] ;
719
+
692
720
let mut iter = split ( rest, 0 ) ;
693
721
if let Some ( update) = iter. next ( ) {
694
722
if update != last_index_update. as_bytes ( ) {
@@ -720,6 +748,7 @@ impl<'a> SummariesCache<'a> {
720
748
. sum ( ) ;
721
749
let mut contents = Vec :: with_capacity ( size) ;
722
750
contents. push ( CURRENT_CACHE_VERSION ) ;
751
+ contents. extend ( & u32:: to_le_bytes ( INDEX_V_MAX ) ) ;
723
752
contents. extend_from_slice ( index_version. as_bytes ( ) ) ;
724
753
contents. push ( 0 ) ;
725
754
for ( version, data) in self . versions . iter ( ) {
@@ -769,6 +798,12 @@ impl IndexSummary {
769
798
///
770
799
/// The `line` provided is expected to be valid JSON.
771
800
fn parse ( config : & Config , line : & [ u8 ] , source_id : SourceId ) -> CargoResult < IndexSummary > {
801
+ // ****CAUTION**** Please be extremely careful with returning errors
802
+ // from this function. Entries that error are not included in the
803
+ // index cache, and can cause cargo to get confused when switching
804
+ // between different versions that understand the index differently.
805
+ // Make sure to consider the INDEX_V_MAX and CURRENT_CACHE_VERSION
806
+ // values carefully when making changes here.
772
807
let RegistryPackage {
773
808
name,
774
809
vers,
0 commit comments