@@ -2,7 +2,8 @@ use crate::core::PackageId;
22use crate :: sources:: registry:: CRATES_IO_HTTP_INDEX ;
33use crate :: sources:: { DirectorySource , CRATES_IO_DOMAIN , CRATES_IO_INDEX , CRATES_IO_REGISTRY } ;
44use 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 ;
67use serde:: de;
78use serde:: ser;
89use std:: cmp:: { self , Ordering } ;
@@ -430,11 +431,6 @@ impl SourceId {
430431 }
431432 }
432433
433- /// Gets the value of the precise field.
434- pub fn precise ( self ) -> Option < & ' static str > {
435- self . inner . precise . as_deref ( )
436- }
437-
438434 /// Gets the Git reference if this is a git source, otherwise `None`.
439435 pub fn git_reference ( self ) -> Option < & ' static GitReference > {
440436 match self . inner . kind {
@@ -443,6 +439,32 @@ impl SourceId {
443439 }
444440 }
445441
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+
446468 /// Creates a new `SourceId` from this source with the given `precise`.
447469 pub fn with_precise ( self , v : Option < String > ) -> SourceId {
448470 SourceId :: wrap ( SourceIdInner {
@@ -451,6 +473,23 @@ impl SourceId {
451473 } )
452474 }
453475
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+
454493 /// Returns `true` if the remote registry is the standard <https://crates.io>.
455494 pub fn is_crates_io ( self ) -> bool {
456495 match self . inner . kind {
0 commit comments