@@ -3,7 +3,8 @@ use crate::sources::registry::CRATES_IO_HTTP_INDEX;
3
3
use crate :: sources:: source:: Source ;
4
4
use crate :: sources:: { DirectorySource , CRATES_IO_DOMAIN , CRATES_IO_INDEX , CRATES_IO_REGISTRY } ;
5
5
use crate :: sources:: { GitSource , PathSource , RegistrySource } ;
6
- use crate :: util:: { config, CanonicalUrl , CargoResult , Config , IntoUrl , ToSemver } ;
6
+ use crate :: util:: interning:: InternedString ;
7
+ use crate :: util:: { config, CanonicalUrl , CargoResult , Config , IntoUrl } ;
7
8
use anyhow:: Context ;
8
9
use serde:: de;
9
10
use serde:: ser;
@@ -50,14 +51,37 @@ struct SourceIdInner {
50
51
/// The source kind.
51
52
kind : SourceKind ,
52
53
/// For example, the exact Git revision of the specified branch for a Git Source.
53
- precise : Option < String > ,
54
+ precise : Option < Precise > ,
54
55
/// Name of the remote registry.
55
56
///
56
57
/// WARNING: this is not always set when the name is not known,
57
58
/// e.g. registry coming from `--index` or Cargo.lock
58
59
registry_key : Option < KeyOf > ,
59
60
}
60
61
62
+ #[ derive( Eq , PartialEq , Clone , Debug , Hash ) ]
63
+ enum Precise {
64
+ Locked ,
65
+ Updated {
66
+ name : InternedString ,
67
+ from : semver:: Version ,
68
+ to : semver:: Version ,
69
+ } ,
70
+ GitUrlFragment ( String ) ,
71
+ }
72
+
73
+ impl fmt:: Display for Precise {
74
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
75
+ match self {
76
+ Precise :: Locked => "locked" . fmt ( f) ,
77
+ Precise :: Updated { name, from, to } => {
78
+ write ! ( f, "{name}={from}->{to}" )
79
+ }
80
+ Precise :: GitUrlFragment ( s) => s. fmt ( f) ,
81
+ }
82
+ }
83
+ }
84
+
61
85
/// The possible kinds of code source.
62
86
/// Along with [`SourceIdInner`], this fully defines the source.
63
87
#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
@@ -178,17 +202,15 @@ impl SourceId {
178
202
let precise = url. fragment ( ) . map ( |s| s. to_owned ( ) ) ;
179
203
url. set_fragment ( None ) ;
180
204
url. set_query ( None ) ;
181
- Ok ( SourceId :: for_git ( & url, reference) ?. with_precise ( precise) )
205
+ Ok ( SourceId :: for_git ( & url, reference) ?. with_git_precise ( precise) )
182
206
}
183
207
"registry" => {
184
208
let url = url. into_url ( ) ?;
185
- Ok ( SourceId :: new ( SourceKind :: Registry , url, None ) ?
186
- . with_precise ( Some ( "locked" . to_string ( ) ) ) )
209
+ Ok ( SourceId :: new ( SourceKind :: Registry , url, None ) ?. with_locked_precise ( ) )
187
210
}
188
211
"sparse" => {
189
212
let url = string. into_url ( ) ?;
190
- Ok ( SourceId :: new ( SourceKind :: SparseRegistry , url, None ) ?
191
- . with_precise ( Some ( "locked" . to_string ( ) ) ) )
213
+ Ok ( SourceId :: new ( SourceKind :: SparseRegistry , url, None ) ?. with_locked_precise ( ) )
192
214
}
193
215
"path" => {
194
216
let url = url. into_url ( ) ?;
@@ -335,7 +357,7 @@ impl SourceId {
335
357
} else if self . has_precise ( ) {
336
358
// We remove `precise` here to retrieve an permissive version of
337
359
// `SourceIdInner`, which may contain the registry name.
338
- self . with_precise ( None ) . display_registry_name ( )
360
+ self . without_precise ( ) . display_registry_name ( )
339
361
} else {
340
362
url_display ( self . url ( ) )
341
363
}
@@ -444,19 +466,14 @@ impl SourceId {
444
466
}
445
467
}
446
468
447
- /// Gets the value of the precise field.
448
- pub fn precise ( self ) -> Option < & ' static str > {
449
- self . inner . precise . as_deref ( )
450
- }
451
-
452
469
/// Check if the precise data field has bean set
453
470
pub fn has_precise ( self ) -> bool {
454
471
self . inner . precise . is_some ( )
455
472
}
456
473
457
- /// Check if the precise data field has bean set to "Locked "
474
+ /// Check if the precise data field has bean set to "locked "
458
475
pub fn has_locked_precise ( self ) -> bool {
459
- self . inner . precise . as_deref ( ) == Some ( "locked" )
476
+ self . inner . precise == Some ( Precise :: Locked )
460
477
}
461
478
462
479
/// Check if two sources have the same precise data field
@@ -468,28 +485,54 @@ impl SourceId {
468
485
/// from a call to [SourceId::with_precise_registry_version].
469
486
///
470
487
/// If so return the version currently in the lock file and the version to be updated to.
471
- /// If specified, our own source will have a precise version listed of the form
472
- // `<pkg>=<p_req>-><f_req>` where `<pkg>` is the name of a crate on
473
- // this source, `<p_req>` is the version installed and `<f_req>` is the
474
- // version requested (argument to `--precise`).
475
488
pub fn precise_registry_version (
476
489
self ,
477
- name : & str ,
478
- ) -> Option < ( semver:: Version , semver:: Version ) > {
479
- self . inner
480
- . precise
481
- . as_deref ( )
482
- . and_then ( |p| p. strip_prefix ( name) ?. strip_prefix ( '=' ) )
483
- . map ( |p| {
484
- let ( current, requested) = p. split_once ( "->" ) . unwrap ( ) ;
485
- ( current. to_semver ( ) . unwrap ( ) , requested. to_semver ( ) . unwrap ( ) )
486
- } )
490
+ pkg : & str ,
491
+ ) -> Option < ( & semver:: Version , & semver:: Version ) > {
492
+ match & self . inner . precise {
493
+ Some ( Precise :: Updated { name, from, to } ) if name == pkg => Some ( ( from, to) ) ,
494
+ _ => None ,
495
+ }
496
+ }
497
+
498
+ pub fn precise_git_fragment ( self ) -> Option < & ' static str > {
499
+ match & self . inner . precise {
500
+ Some ( Precise :: GitUrlFragment ( s) ) => Some ( & s[ ..8 ] ) ,
501
+ _ => None ,
502
+ }
503
+ }
504
+
505
+ pub fn precise_git_oid ( self ) -> CargoResult < Option < git2:: Oid > > {
506
+ Ok ( match self . inner . precise . as_ref ( ) {
507
+ Some ( Precise :: GitUrlFragment ( s) ) => {
508
+ Some ( git2:: Oid :: from_str ( s) . with_context ( || {
509
+ format ! ( "precise value for git is not a git revision: {}" , s)
510
+ } ) ?)
511
+ }
512
+ _ => None ,
513
+ } )
487
514
}
488
515
489
516
/// Creates a new `SourceId` from this source with the given `precise`.
490
- pub fn with_precise ( self , v : Option < String > ) -> SourceId {
517
+ pub fn with_git_precise ( self , fragment : Option < String > ) -> SourceId {
518
+ SourceId :: wrap ( SourceIdInner {
519
+ precise : fragment. map ( |f| Precise :: GitUrlFragment ( f) ) ,
520
+ ..( * self . inner ) . clone ( )
521
+ } )
522
+ }
523
+
524
+ /// Creates a new `SourceId` from this source without a `precise`.
525
+ pub fn without_precise ( self ) -> SourceId {
491
526
SourceId :: wrap ( SourceIdInner {
492
- precise : v,
527
+ precise : None ,
528
+ ..( * self . inner ) . clone ( )
529
+ } )
530
+ }
531
+
532
+ /// Creates a new `SourceId` from this source without a `precise`.
533
+ pub fn with_locked_precise ( self ) -> SourceId {
534
+ SourceId :: wrap ( SourceIdInner {
535
+ precise : Some ( Precise :: Locked ) ,
493
536
..( * self . inner ) . clone ( )
494
537
} )
495
538
}
@@ -510,13 +553,21 @@ impl SourceId {
510
553
/// The data can be read with [SourceId::precise_registry_version]
511
554
pub fn with_precise_registry_version (
512
555
self ,
513
- name : impl fmt :: Display ,
514
- version : & semver:: Version ,
556
+ name : InternedString ,
557
+ version : semver:: Version ,
515
558
precise : & str ,
516
559
) -> CargoResult < SourceId > {
517
- semver:: Version :: parse ( precise)
560
+ let precise = semver:: Version :: parse ( precise)
518
561
. with_context ( || format ! ( "invalid version format for precise version `{precise}`" ) ) ?;
519
- Ok ( self . with_precise ( Some ( format ! ( "{}={}->{}" , name, version, precise) ) ) )
562
+
563
+ Ok ( SourceId :: wrap ( SourceIdInner {
564
+ precise : Some ( Precise :: Updated {
565
+ name,
566
+ from : version,
567
+ to : precise,
568
+ } ) ,
569
+ ..( * self . inner ) . clone ( )
570
+ } ) )
520
571
}
521
572
522
573
/// Returns `true` if the remote registry is the standard <https://crates.io>.
@@ -648,7 +699,8 @@ impl fmt::Display for SourceId {
648
699
write ! ( f, "?{}" , pretty) ?;
649
700
}
650
701
651
- if let Some ( ref s) = self . inner . precise {
702
+ if let Some ( s) = & self . inner . precise {
703
+ let s = s. to_string ( ) ;
652
704
let len = cmp:: min ( s. len ( ) , 8 ) ;
653
705
write ! ( f, "#{}" , & s[ ..len] ) ?;
654
706
}
0 commit comments