@@ -135,6 +135,8 @@ pub enum IndexSummary {
135
135
Offline ( Summary ) ,
136
136
/// From a newer schema version and is likely incomplete or inaccurate
137
137
Unsupported ( Summary , u32 ) ,
138
+ /// An error was encountered despite being a supported schema version
139
+ Invalid ( Summary ) ,
138
140
}
139
141
140
142
impl IndexSummary {
@@ -144,7 +146,8 @@ impl IndexSummary {
144
146
IndexSummary :: Candidate ( sum)
145
147
| IndexSummary :: Yanked ( sum)
146
148
| IndexSummary :: Offline ( sum)
147
- | IndexSummary :: Unsupported ( sum, _) => sum,
149
+ | IndexSummary :: Unsupported ( sum, _)
150
+ | IndexSummary :: Invalid ( sum) => sum,
148
151
}
149
152
}
150
153
@@ -154,7 +157,8 @@ impl IndexSummary {
154
157
IndexSummary :: Candidate ( sum)
155
158
| IndexSummary :: Yanked ( sum)
156
159
| IndexSummary :: Offline ( sum)
157
- | IndexSummary :: Unsupported ( sum, _) => sum,
160
+ | IndexSummary :: Unsupported ( sum, _)
161
+ | IndexSummary :: Invalid ( sum) => sum,
158
162
}
159
163
}
160
164
@@ -164,17 +168,13 @@ impl IndexSummary {
164
168
IndexSummary :: Yanked ( s) => IndexSummary :: Yanked ( f ( s) ) ,
165
169
IndexSummary :: Offline ( s) => IndexSummary :: Offline ( f ( s) ) ,
166
170
IndexSummary :: Unsupported ( s, v) => IndexSummary :: Unsupported ( f ( s) , v. clone ( ) ) ,
171
+ IndexSummary :: Invalid ( s) => IndexSummary :: Invalid ( f ( s) ) ,
167
172
}
168
173
}
169
174
170
175
/// Extract the package id from any variant
171
176
pub fn package_id ( & self ) -> PackageId {
172
- match self {
173
- IndexSummary :: Candidate ( sum)
174
- | IndexSummary :: Yanked ( sum)
175
- | IndexSummary :: Offline ( sum)
176
- | IndexSummary :: Unsupported ( sum, _) => sum. package_id ( ) ,
177
- }
177
+ self . as_summary ( ) . package_id ( )
178
178
}
179
179
180
180
/// Returns `true` if the index summary is [`Yanked`].
@@ -259,8 +259,52 @@ pub struct IndexPackage<'a> {
259
259
pub v : Option < u32 > ,
260
260
}
261
261
262
- /// A dependency as encoded in the [`IndexPackage`] index JSON.
262
+ impl IndexPackage < ' _ > {
263
+ fn to_summary ( & self , source_id : SourceId ) -> CargoResult < Summary > {
264
+ // ****CAUTION**** Please be extremely careful with returning errors, see
265
+ // `IndexSummary::parse` for details
266
+ let pkgid = PackageId :: new ( self . name . into ( ) , self . vers . clone ( ) , source_id) ;
267
+ let deps = self
268
+ . deps
269
+ . iter ( )
270
+ . map ( |dep| dep. clone ( ) . into_dep ( source_id) )
271
+ . collect :: < CargoResult < Vec < _ > > > ( ) ?;
272
+ let mut features = self . features . clone ( ) ;
273
+ if let Some ( features2) = & self . features2 {
274
+ for ( name, values) in features2 {
275
+ features. entry ( * name) . or_default ( ) . extend ( values) ;
276
+ }
277
+ }
278
+ let mut summary = Summary :: new (
279
+ pkgid,
280
+ deps,
281
+ & features,
282
+ self . links ,
283
+ self . rust_version . clone ( ) ,
284
+ ) ?;
285
+ summary. set_checksum ( self . cksum . clone ( ) ) ;
286
+ Ok ( summary)
287
+ }
288
+ }
289
+
263
290
#[ derive( Deserialize , Serialize ) ]
291
+ struct IndexPackageMinimum {
292
+ name : InternedString ,
293
+ vers : Version ,
294
+ }
295
+
296
+ #[ derive( Deserialize , Serialize , Default ) ]
297
+ struct IndexPackageRustVersion {
298
+ rust_version : Option < RustVersion > ,
299
+ }
300
+
301
+ #[ derive( Deserialize , Serialize , Default ) ]
302
+ struct IndexPackageV {
303
+ v : Option < u32 > ,
304
+ }
305
+
306
+ /// A dependency as encoded in the [`IndexPackage`] index JSON.
307
+ #[ derive( Deserialize , Serialize , Clone ) ]
264
308
pub struct RegistryDependency < ' a > {
265
309
/// Name of the dependency. If the dependency is renamed, the original
266
310
/// would be stored in [`RegistryDependency::package`].
@@ -706,32 +750,45 @@ impl IndexSummary {
706
750
// between different versions that understand the index differently.
707
751
// Make sure to consider the INDEX_V_MAX and CURRENT_CACHE_VERSION
708
752
// values carefully when making changes here.
709
- let IndexPackage {
710
- name,
711
- vers,
712
- cksum,
713
- deps,
714
- mut features,
715
- features2,
716
- yanked,
717
- links,
718
- rust_version,
719
- v,
720
- } = serde_json:: from_slice ( line) ?;
721
- let v = v. unwrap_or ( 1 ) ;
722
- tracing:: trace!( "json parsed registry {}/{}" , name, vers) ;
723
- let pkgid = PackageId :: new ( name. into ( ) , vers. clone ( ) , source_id) ;
724
- let deps = deps
725
- . into_iter ( )
726
- . map ( |dep| dep. into_dep ( source_id) )
727
- . collect :: < CargoResult < Vec < _ > > > ( ) ?;
728
- if let Some ( features2) = features2 {
729
- for ( name, values) in features2 {
730
- features. entry ( name) . or_default ( ) . extend ( values) ;
753
+ let index_summary = ( || {
754
+ let index = serde_json:: from_slice :: < IndexPackage < ' _ > > ( line) ?;
755
+ let summary = index. to_summary ( source_id) ?;
756
+ Ok ( ( index, summary) )
757
+ } ) ( ) ;
758
+ let ( index, summary, valid) = match index_summary {
759
+ Ok ( ( index, summary) ) => ( index, summary, true ) ,
760
+ Err ( err) => {
761
+ let Ok ( IndexPackageMinimum { name, vers } ) =
762
+ serde_json:: from_slice :: < IndexPackageMinimum > ( line)
763
+ else {
764
+ // If we can't recover, prefer the original error
765
+ return Err ( err) ;
766
+ } ;
767
+ tracing:: info!(
768
+ "recoverying from failed parse of registry package {name}@{vers}: {err}"
769
+ ) ;
770
+ let IndexPackageRustVersion { rust_version } =
771
+ serde_json:: from_slice :: < IndexPackageRustVersion > ( line) . unwrap_or_default ( ) ;
772
+ let IndexPackageV { v } =
773
+ serde_json:: from_slice :: < IndexPackageV > ( line) . unwrap_or_default ( ) ;
774
+ let index = IndexPackage {
775
+ name,
776
+ vers,
777
+ rust_version,
778
+ v,
779
+ deps : Default :: default ( ) ,
780
+ features : Default :: default ( ) ,
781
+ features2 : Default :: default ( ) ,
782
+ cksum : Default :: default ( ) ,
783
+ yanked : Default :: default ( ) ,
784
+ links : Default :: default ( ) ,
785
+ } ;
786
+ let summary = index. to_summary ( source_id) ?;
787
+ ( index, summary, false )
731
788
}
732
- }
733
- let mut summary = Summary :: new ( pkgid , deps , & features , links , rust_version ) ? ;
734
- summary . set_checksum ( cksum ) ;
789
+ } ;
790
+ let v = index . v . unwrap_or ( 1 ) ;
791
+ tracing :: trace! ( "json parsed registry {}/{}" , index . name , index . vers ) ;
735
792
736
793
let v_max = if bindeps {
737
794
INDEX_V_MAX + 1
@@ -741,7 +798,9 @@ impl IndexSummary {
741
798
742
799
if v_max < v {
743
800
Ok ( IndexSummary :: Unsupported ( summary, v) )
744
- } else if yanked. unwrap_or ( false ) {
801
+ } else if !valid {
802
+ Ok ( IndexSummary :: Invalid ( summary) )
803
+ } else if index. yanked . unwrap_or ( false ) {
745
804
Ok ( IndexSummary :: Yanked ( summary) )
746
805
} else {
747
806
Ok ( IndexSummary :: Candidate ( summary) )
0 commit comments