@@ -189,11 +189,64 @@ enum MaybeIndexSummary {
189
189
/// from a line from a raw index file, or a JSON blob from on-disk index cache.
190
190
///
191
191
/// In addition to a full [`Summary`], we have information on whether it is `yanked`.
192
- pub struct IndexSummary {
193
- pub summary : Summary ,
194
- pub yanked : bool ,
195
- /// Schema version, see [`IndexPackage::v`].
196
- v : u32 ,
192
+ #[ derive( Clone , Debug ) ]
193
+ pub enum IndexSummary {
194
+ /// Available for consideration
195
+ Candidate ( Summary ) ,
196
+ /// Yanked within its registry
197
+ Yanked ( Summary ) ,
198
+ /// Not available as we are offline and create is not downloaded yet
199
+ Offline ( Summary ) ,
200
+ /// From a newer schema version and is likely incomplete or inaccurate
201
+ Unsupported ( Summary , u32 ) ,
202
+ }
203
+
204
+ impl IndexSummary {
205
+ /// Extract the summary from any variant
206
+ pub fn as_summary ( & self ) -> & Summary {
207
+ match self {
208
+ IndexSummary :: Candidate ( sum)
209
+ | IndexSummary :: Yanked ( sum)
210
+ | IndexSummary :: Offline ( sum)
211
+ | IndexSummary :: Unsupported ( sum, _) => sum,
212
+ }
213
+ }
214
+
215
+ /// Extract the summary from any variant
216
+ pub fn into_summary ( self ) -> Summary {
217
+ match self {
218
+ IndexSummary :: Candidate ( sum)
219
+ | IndexSummary :: Yanked ( sum)
220
+ | IndexSummary :: Offline ( sum)
221
+ | IndexSummary :: Unsupported ( sum, _) => sum,
222
+ }
223
+ }
224
+
225
+ /// Extract the package id from any variant
226
+ pub fn package_id ( & self ) -> PackageId {
227
+ match self {
228
+ IndexSummary :: Candidate ( sum)
229
+ | IndexSummary :: Yanked ( sum)
230
+ | IndexSummary :: Offline ( sum)
231
+ | IndexSummary :: Unsupported ( sum, _) => sum. package_id ( ) ,
232
+ }
233
+ }
234
+
235
+ /// Returns `true` if the index summary is [`Yanked`].
236
+ ///
237
+ /// [`Yanked`]: IndexSummary::Yanked
238
+ #[ must_use]
239
+ pub fn is_yanked ( & self ) -> bool {
240
+ matches ! ( self , Self :: Yanked ( ..) )
241
+ }
242
+
243
+ /// Returns `true` if the index summary is [`Offline`].
244
+ ///
245
+ /// [`Offline`]: IndexSummary::Offline
246
+ #[ must_use]
247
+ pub fn is_offline ( & self ) -> bool {
248
+ matches ! ( self , Self :: Offline ( ..) )
249
+ }
197
250
}
198
251
199
252
/// A representation of the cache on disk that Cargo maintains of summaries.
@@ -385,13 +438,13 @@ impl<'cfg> RegistryIndex<'cfg> {
385
438
/// the index file, aka [`IndexSummary`].
386
439
pub fn hash ( & mut self , pkg : PackageId , load : & mut dyn RegistryData ) -> Poll < CargoResult < & str > > {
387
440
let req = OptVersionReq :: exact ( pkg. version ( ) ) ;
388
- let summary = self . summaries ( & pkg. name ( ) , & req, load) ?;
441
+ let summary = self . summaries ( pkg. name ( ) , & req, load) ?;
389
442
let summary = ready ! ( summary)
390
- . filter ( |s| s. summary . version ( ) == pkg. version ( ) )
443
+ . filter ( |s| s. package_id ( ) . version ( ) == pkg. version ( ) )
391
444
. next ( ) ;
392
445
Poll :: Ready ( Ok ( summary
393
446
. ok_or_else ( || internal ( format ! ( "no hash listed for {}" , pkg) ) ) ?
394
- . summary
447
+ . as_summary ( )
395
448
. checksum ( )
396
449
. ok_or_else ( || internal ( format ! ( "no hash listed for {}" , pkg) ) ) ?) )
397
450
}
@@ -407,9 +460,9 @@ impl<'cfg> RegistryIndex<'cfg> {
407
460
///
408
461
/// Internally there's quite a few layer of caching to amortize this cost
409
462
/// though since this method is called quite a lot on null builds in Cargo.
410
- pub fn summaries < ' a , ' b > (
463
+ fn summaries < ' a , ' b > (
411
464
& ' a mut self ,
412
- name : & str ,
465
+ name : InternedString ,
413
466
req : & ' b OptVersionReq ,
414
467
load : & mut dyn RegistryData ,
415
468
) -> Poll < CargoResult < impl Iterator < Item = & ' a IndexSummary > + ' b > >
@@ -421,7 +474,6 @@ impl<'cfg> RegistryIndex<'cfg> {
421
474
let source_id = self . source_id ;
422
475
423
476
// First up parse what summaries we have available.
424
- let name = InternedString :: new ( name) ;
425
477
let summaries = ready ! ( self . load_summaries( name, load) ?) ;
426
478
427
479
// Iterate over our summaries, extract all relevant ones which match our
@@ -435,26 +487,27 @@ impl<'cfg> RegistryIndex<'cfg> {
435
487
. versions
436
488
. iter_mut ( )
437
489
. filter_map ( move |( k, v) | if req. matches ( k) { Some ( v) } else { None } )
438
- . filter_map ( move |maybe| match maybe. parse ( raw_data, source_id) {
439
- Ok ( summary) => Some ( summary) ,
440
- Err ( e) => {
441
- info ! ( "failed to parse `{}` registry package: {}" , name, e) ;
442
- None
443
- }
444
- } )
445
- . filter ( move |is| {
446
- if is. v == 3 && bindeps {
447
- true
448
- } else if is. v > INDEX_V_MAX {
449
- debug ! (
450
- "unsupported schema version {} ({} {})" ,
451
- is. v,
452
- is. summary. name( ) ,
453
- is. summary. version( )
454
- ) ;
455
- false
456
- } else {
457
- true
490
+ . filter_map ( move |maybe| {
491
+ match maybe. parse ( raw_data, source_id, bindeps) {
492
+ Ok ( sum @ IndexSummary :: Candidate ( _) | sum @ IndexSummary :: Yanked ( _) ) => {
493
+ Some ( sum)
494
+ }
495
+ Ok ( IndexSummary :: Unsupported ( summary, v) ) => {
496
+ debug ! (
497
+ "unsupported schema version {} ({} {})" ,
498
+ v,
499
+ summary. name( ) ,
500
+ summary. version( )
501
+ ) ;
502
+ None
503
+ }
504
+ Ok ( IndexSummary :: Offline ( _) ) => {
505
+ unreachable ! ( "We do not check for off-line until later" )
506
+ }
507
+ Err ( e) => {
508
+ info ! ( "failed to parse `{}` registry package: {}" , name, e) ;
509
+ None
510
+ }
458
511
}
459
512
} ) ) )
460
513
}
@@ -518,7 +571,7 @@ impl<'cfg> RegistryIndex<'cfg> {
518
571
/// This is primarily used by [`Source::query`](super::Source).
519
572
pub fn query_inner (
520
573
& mut self ,
521
- name : & str ,
574
+ name : InternedString ,
522
575
req : & OptVersionReq ,
523
576
load : & mut dyn RegistryData ,
524
577
yanked_whitelist : & HashSet < PackageId > ,
@@ -535,14 +588,35 @@ impl<'cfg> RegistryIndex<'cfg> {
535
588
// then cargo will fail to download and an error message
536
589
// indicating that the required dependency is unavailable while
537
590
// offline will be displayed.
538
- if ready ! ( self . query_inner_with_online( name, req, load, yanked_whitelist, f, false ) ?)
539
- > 0
540
- {
591
+ let mut called = false ;
592
+ let callback = & mut |s : IndexSummary | {
593
+ if !s. is_offline ( ) {
594
+ called = true ;
595
+ f ( s. into_summary ( ) ) ;
596
+ }
597
+ } ;
598
+ ready ! ( self . query_inner_with_online(
599
+ name,
600
+ req,
601
+ load,
602
+ yanked_whitelist,
603
+ callback,
604
+ false
605
+ ) ?) ;
606
+ if called {
541
607
return Poll :: Ready ( Ok ( ( ) ) ) ;
542
608
}
543
609
}
544
- self . query_inner_with_online ( name, req, load, yanked_whitelist, f, true )
545
- . map_ok ( |_| ( ) )
610
+ self . query_inner_with_online (
611
+ name,
612
+ req,
613
+ load,
614
+ yanked_whitelist,
615
+ & mut |s| {
616
+ f ( s. into_summary ( ) ) ;
617
+ } ,
618
+ true ,
619
+ )
546
620
}
547
621
548
622
/// Inner implementation of [`Self::query_inner`]. Returns the number of
@@ -551,13 +625,13 @@ impl<'cfg> RegistryIndex<'cfg> {
551
625
/// The `online` controls whether Cargo can access the network when needed.
552
626
fn query_inner_with_online (
553
627
& mut self ,
554
- name : & str ,
628
+ name : InternedString ,
555
629
req : & OptVersionReq ,
556
630
load : & mut dyn RegistryData ,
557
631
yanked_whitelist : & HashSet < PackageId > ,
558
- f : & mut dyn FnMut ( Summary ) ,
632
+ f : & mut dyn FnMut ( IndexSummary ) ,
559
633
online : bool ,
560
- ) -> Poll < CargoResult < usize > > {
634
+ ) -> Poll < CargoResult < ( ) > > {
561
635
let source_id = self . source_id ;
562
636
563
637
let summaries = ready ! ( self . summaries( name, req, load) ) ?;
@@ -573,23 +647,28 @@ impl<'cfg> RegistryIndex<'cfg> {
573
647
// does not satisfy the requirements, then resolution will
574
648
// fail. Unfortunately, whether or not something is optional
575
649
// is not known here.
576
- . filter ( |s| ( online || load. is_crate_downloaded ( s. summary . package_id ( ) ) ) )
650
+ . map ( |s| {
651
+ if online || load. is_crate_downloaded ( s. package_id ( ) ) {
652
+ s. clone ( )
653
+ } else {
654
+ IndexSummary :: Offline ( s. as_summary ( ) . clone ( ) )
655
+ }
656
+ } )
577
657
// Next filter out all yanked packages. Some yanked packages may
578
658
// leak through if they're in a whitelist (aka if they were
579
659
// previously in `Cargo.lock`
580
- . filter ( |s| !s. yanked || yanked_whitelist. contains ( & s. summary . package_id ( ) ) )
581
- . map ( |s| s. summary . clone ( ) ) ;
660
+ . filter ( |s| !s. is_yanked ( ) || yanked_whitelist. contains ( & s. package_id ( ) ) ) ;
582
661
583
662
// Handle `cargo update --precise` here.
584
- let precise = source_id. precise_registry_version ( name) ;
663
+ let precise = source_id. precise_registry_version ( name. as_str ( ) ) ;
585
664
let summaries = summaries. filter ( |s| match & precise {
586
665
Some ( ( current, requested) ) => {
587
666
if req. matches ( current) {
588
667
// Unfortunately crates.io allows versions to differ only
589
668
// by build metadata. This shouldn't be allowed, but since
590
669
// it is, this will honor it if requested. However, if not
591
670
// specified, then ignore it.
592
- let s_vers = s. version ( ) ;
671
+ let s_vers = s. package_id ( ) . version ( ) ;
593
672
match ( s_vers. build . is_empty ( ) , requested. build . is_empty ( ) ) {
594
673
( true , true ) => s_vers == requested,
595
674
( true , false ) => false ,
@@ -609,12 +688,8 @@ impl<'cfg> RegistryIndex<'cfg> {
609
688
None => true ,
610
689
} ) ;
611
690
612
- let mut count = 0 ;
613
- for summary in summaries {
614
- f ( summary) ;
615
- count += 1 ;
616
- }
617
- Poll :: Ready ( Ok ( count) )
691
+ summaries. for_each ( f) ;
692
+ Poll :: Ready ( Ok ( ( ) ) )
618
693
}
619
694
620
695
/// Looks into the summaries to check if a package has been yanked.
@@ -624,9 +699,9 @@ impl<'cfg> RegistryIndex<'cfg> {
624
699
load : & mut dyn RegistryData ,
625
700
) -> Poll < CargoResult < bool > > {
626
701
let req = OptVersionReq :: exact ( pkg. version ( ) ) ;
627
- let found = ready ! ( self . summaries( & pkg. name( ) , & req, load) ) ?
628
- . filter ( |s| s. summary . version ( ) == pkg. version ( ) )
629
- . any ( |summary| summary . yanked ) ;
702
+ let found = ready ! ( self . summaries( pkg. name( ) , & req, load) ) ?
703
+ . filter ( |s| s. package_id ( ) . version ( ) == pkg. version ( ) )
704
+ . any ( |s| s . is_yanked ( ) ) ;
630
705
Poll :: Ready ( Ok ( found) )
631
706
}
632
707
}
@@ -682,6 +757,8 @@ impl Summaries {
682
757
683
758
let response = ready ! ( load. load( root, relative, index_version. as_deref( ) ) ?) ;
684
759
760
+ let bindeps = config. cli_unstable ( ) . bindeps ;
761
+
685
762
match response {
686
763
LoadResponse :: CacheValid => {
687
764
tracing:: debug!( "fast path for registry cache of {:?}" , relative) ;
@@ -712,7 +789,7 @@ impl Summaries {
712
789
// allow future cargo implementations to break the
713
790
// interpretation of each line here and older cargo will simply
714
791
// ignore the new lines.
715
- let summary = match IndexSummary :: parse ( line, source_id) {
792
+ let summary = match IndexSummary :: parse ( line, source_id, bindeps ) {
716
793
Ok ( summary) => summary,
717
794
Err ( e) => {
718
795
// This should only happen when there is an index
@@ -731,7 +808,7 @@ impl Summaries {
731
808
continue ;
732
809
}
733
810
} ;
734
- let version = summary. summary . package_id ( ) . version ( ) . clone ( ) ;
811
+ let version = summary. package_id ( ) . version ( ) . clone ( ) ;
735
812
cache. versions . push ( ( version. clone ( ) , line) ) ;
736
813
ret. versions . insert ( version, summary. into ( ) ) ;
737
814
}
@@ -865,12 +942,17 @@ impl MaybeIndexSummary {
865
942
/// Does nothing if this is already `Parsed`, and otherwise the `raw_data`
866
943
/// passed in is sliced with the bounds in `Unparsed` and then actually
867
944
/// parsed.
868
- fn parse ( & mut self , raw_data : & [ u8 ] , source_id : SourceId ) -> CargoResult < & IndexSummary > {
945
+ fn parse (
946
+ & mut self ,
947
+ raw_data : & [ u8 ] ,
948
+ source_id : SourceId ,
949
+ bindeps : bool ,
950
+ ) -> CargoResult < & IndexSummary > {
869
951
let ( start, end) = match self {
870
952
MaybeIndexSummary :: Unparsed { start, end } => ( * start, * end) ,
871
953
MaybeIndexSummary :: Parsed ( summary) => return Ok ( summary) ,
872
954
} ;
873
- let summary = IndexSummary :: parse ( & raw_data[ start..end] , source_id) ?;
955
+ let summary = IndexSummary :: parse ( & raw_data[ start..end] , source_id, bindeps ) ?;
874
956
* self = MaybeIndexSummary :: Parsed ( summary) ;
875
957
match self {
876
958
MaybeIndexSummary :: Unparsed { .. } => unreachable ! ( ) ,
@@ -891,7 +973,7 @@ impl IndexSummary {
891
973
///
892
974
/// The `line` provided is expected to be valid JSON. It is supposed to be
893
975
/// a [`IndexPackage`].
894
- fn parse ( line : & [ u8 ] , source_id : SourceId ) -> CargoResult < IndexSummary > {
976
+ fn parse ( line : & [ u8 ] , source_id : SourceId , bindeps : bool ) -> CargoResult < IndexSummary > {
895
977
// ****CAUTION**** Please be extremely careful with returning errors
896
978
// from this function. Entries that error are not included in the
897
979
// index cache, and can cause cargo to get confused when switching
@@ -924,11 +1006,20 @@ impl IndexSummary {
924
1006
}
925
1007
let mut summary = Summary :: new ( pkgid, deps, & features, links, rust_version) ?;
926
1008
summary. set_checksum ( cksum) ;
927
- Ok ( IndexSummary {
928
- summary,
929
- yanked : yanked. unwrap_or ( false ) ,
930
- v,
931
- } )
1009
+
1010
+ let v_max = if bindeps {
1011
+ INDEX_V_MAX + 1
1012
+ } else {
1013
+ INDEX_V_MAX
1014
+ } ;
1015
+
1016
+ if v_max < v {
1017
+ Ok ( IndexSummary :: Unsupported ( summary, v) )
1018
+ } else if yanked. unwrap_or ( false ) {
1019
+ Ok ( IndexSummary :: Yanked ( summary) )
1020
+ } else {
1021
+ Ok ( IndexSummary :: Candidate ( summary) )
1022
+ }
932
1023
}
933
1024
}
934
1025
0 commit comments