@@ -2,7 +2,8 @@ use crate::core::PackageId;
2
2
use crate :: sources:: registry:: CRATES_IO_HTTP_INDEX ;
3
3
use crate :: sources:: { DirectorySource , CRATES_IO_DOMAIN , CRATES_IO_INDEX , CRATES_IO_REGISTRY } ;
4
4
use crate :: sources:: { GitSource , PathSource , RegistrySource } ;
5
- use crate :: util:: { config, CanonicalUrl , CargoResult , Config , IntoUrl } ;
5
+ use crate :: util:: { config, CanonicalUrl , CargoResult , Config , IntoUrl , ToSemver } ;
6
+ use anyhow:: Context ;
6
7
use serde:: de;
7
8
use serde:: ser;
8
9
use std:: cmp:: { self , Ordering } ;
@@ -430,11 +431,6 @@ impl SourceId {
430
431
}
431
432
}
432
433
433
- /// Gets the value of the precise field.
434
- pub fn precise ( self ) -> Option < & ' static str > {
435
- self . inner . precise . as_deref ( )
436
- }
437
-
438
434
/// Gets the Git reference if this is a git source, otherwise `None`.
439
435
pub fn git_reference ( self ) -> Option < & ' static GitReference > {
440
436
match self . inner . kind {
@@ -443,6 +439,32 @@ impl SourceId {
443
439
}
444
440
}
445
441
442
+ /// Gets the value of the precise field.
443
+ pub fn precise ( self ) -> Option < & ' static str > {
444
+ self . inner . precise . as_deref ( )
445
+ }
446
+
447
+ /// Check if the precise data field stores information for this `name`
448
+ /// from a call to [with_precise_registry_version].
449
+ /// If so return the version currently in the lock file and the version to be updated to.
450
+ /// If specified, our own source will have a precise version listed of the form
451
+ // `<pkg>=<p_req>-><f_req>` where `<pkg>` is the name of a crate on
452
+ // this source, `<p_req>` is the version installed and `<f_req> is the
453
+ // version requested (argument to `--precise`).
454
+ pub fn precise_registry_version (
455
+ self ,
456
+ name : & str ,
457
+ ) -> Option < ( semver:: Version , semver:: Version ) > {
458
+ self . inner
459
+ . precise
460
+ . as_deref ( )
461
+ . filter ( |p| p. starts_with ( name) && p[ name. len ( ) ..] . starts_with ( '=' ) )
462
+ . map ( |p| {
463
+ let ( current, requested) = p[ name. len ( ) + 1 ..] . split_once ( "->" ) . unwrap ( ) ;
464
+ ( current. to_semver ( ) . unwrap ( ) , requested. to_semver ( ) . unwrap ( ) )
465
+ } )
466
+ }
467
+
446
468
/// Creates a new `SourceId` from this source with the given `precise`.
447
469
pub fn with_precise ( self , v : Option < String > ) -> SourceId {
448
470
SourceId :: wrap ( SourceIdInner {
@@ -451,6 +473,23 @@ impl SourceId {
451
473
} )
452
474
}
453
475
476
+ /// When updating a lock file on a version using `cargo update --precise`
477
+ /// the requested version is stored in the precise field.
478
+ /// On a registry dependency we also need to keep track of the package that
479
+ /// should be updated and even which of the versions should be updated.
480
+ /// All of this gets encoded in the precise field using this method.
481
+ /// The data can be read with [precise_registry_version]
482
+ pub fn with_precise_registry_version (
483
+ self ,
484
+ name : impl fmt:: Display ,
485
+ version : & semver:: Version ,
486
+ precise : & str ,
487
+ ) -> CargoResult < SourceId > {
488
+ semver:: Version :: parse ( precise)
489
+ . with_context ( || format ! ( "invalid version format for precise version `{precise}`" ) ) ?;
490
+ Ok ( self . with_precise ( Some ( format ! ( "{}={}->{}" , name, version, precise) ) ) )
491
+ }
492
+
454
493
/// Returns `true` if the remote registry is the standard <https://crates.io>.
455
494
pub fn is_crates_io ( self ) -> bool {
456
495
match self . inner . kind {
0 commit comments