@@ -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,33 @@ 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 [SourceId::with_precise_registry_version].
449
+ ///
450
+ /// If so return the version currently in the lock file and the version to be updated to.
451
+ /// If specified, our own source will have a precise version listed of the form
452
+ // `<pkg>=<p_req>-><f_req>` where `<pkg>` is the name of a crate on
453
+ // this source, `<p_req>` is the version installed and `<f_req>` is the
454
+ // version requested (argument to `--precise`).
455
+ pub fn precise_registry_version (
456
+ self ,
457
+ name : & str ,
458
+ ) -> Option < ( semver:: Version , semver:: Version ) > {
459
+ self . inner
460
+ . precise
461
+ . as_deref ( )
462
+ . and_then ( |p| p. strip_prefix ( name) ?. strip_prefix ( '=' ) )
463
+ . map ( |p| {
464
+ let ( current, requested) = p. split_once ( "->" ) . unwrap ( ) ;
465
+ ( current. to_semver ( ) . unwrap ( ) , requested. to_semver ( ) . unwrap ( ) )
466
+ } )
467
+ }
468
+
446
469
/// Creates a new `SourceId` from this source with the given `precise`.
447
470
pub fn with_precise ( self , v : Option < String > ) -> SourceId {
448
471
SourceId :: wrap ( SourceIdInner {
@@ -451,6 +474,23 @@ impl SourceId {
451
474
} )
452
475
}
453
476
477
+ /// When updating a lock file on a version using `cargo update --precise`
478
+ /// the requested version is stored in the precise field.
479
+ /// On a registry dependency we also need to keep track of the package that
480
+ /// should be updated and even which of the versions should be updated.
481
+ /// All of this gets encoded in the precise field using this method.
482
+ /// The data can be read with [SourceId::precise_registry_version]
483
+ pub fn with_precise_registry_version (
484
+ self ,
485
+ name : impl fmt:: Display ,
486
+ version : & semver:: Version ,
487
+ precise : & str ,
488
+ ) -> CargoResult < SourceId > {
489
+ semver:: Version :: parse ( precise)
490
+ . with_context ( || format ! ( "invalid version format for precise version `{precise}`" ) ) ?;
491
+ Ok ( self . with_precise ( Some ( format ! ( "{}={}->{}" , name, version, precise) ) ) )
492
+ }
493
+
454
494
/// Returns `true` if the remote registry is the standard <https://crates.io>.
455
495
pub fn is_crates_io ( self ) -> bool {
456
496
match self . inner . kind {
0 commit comments