@@ -8,6 +8,8 @@ pub enum OptVersionReq {
88 Req ( VersionReq ) ,
99 /// The exact locked version and the original version requirement.
1010 Locked ( Version , VersionReq ) ,
11+ /// The exact requested version and the original version requirement.
12+ UpdatePrecise ( Version , VersionReq ) ,
1113}
1214
1315pub trait VersionExt {
@@ -53,7 +55,7 @@ impl OptVersionReq {
5355 pub fn is_exact ( & self ) -> bool {
5456 match self {
5557 OptVersionReq :: Any => false ,
56- OptVersionReq :: Req ( req) => {
58+ OptVersionReq :: Req ( req) | OptVersionReq :: UpdatePrecise ( _ , req ) => {
5759 req. comparators . len ( ) == 1 && {
5860 let cmp = & req. comparators [ 0 ] ;
5961 cmp. op == Op :: Exact && cmp. minor . is_some ( ) && cmp. patch . is_some ( )
@@ -69,8 +71,24 @@ impl OptVersionReq {
6971 let version = version. clone ( ) ;
7072 * self = match self {
7173 Any => Locked ( version, VersionReq :: STAR ) ,
72- Req ( req) => Locked ( version, req. clone ( ) ) ,
73- Locked ( _, req) => Locked ( version, req. clone ( ) ) ,
74+ Req ( req) | Locked ( _, req) | UpdatePrecise ( _, req) => Locked ( version, req. clone ( ) ) ,
75+ } ;
76+ }
77+
78+ pub fn update_precise ( & mut self , version : & Version ) {
79+ assert ! (
80+ self . matches( version) ,
81+ "cannot update_precise {} to {}" ,
82+ self ,
83+ version
84+ ) ;
85+ use OptVersionReq :: * ;
86+ let version = version. clone ( ) ;
87+ * self = match self {
88+ Any => UpdatePrecise ( version, VersionReq :: STAR ) ,
89+ Req ( req) | Locked ( _, req) | UpdatePrecise ( _, req) => {
90+ UpdatePrecise ( version, req. clone ( ) )
91+ }
7492 } ;
7593 }
7694
@@ -100,6 +118,23 @@ impl OptVersionReq {
100118 // we should not silently use `1.0.0+foo` even though they have the same version.
101119 v == version
102120 }
121+ OptVersionReq :: UpdatePrecise ( v, _) => {
122+ // This is used for the `--precise` field of cargo update.
123+ //
124+ // Unfortunately crates.io allowed versions to differ only
125+ // by build metadata. This shouldn't be allowed, but since
126+ // it is, this will honor it if requested.
127+ //
128+ // In that context we treat a requirement that does not have
129+ // build metadata as allowing any metadata. But, if a requirement
130+ // has build metadata, then we only allow it to match the exact
131+ // metadata.
132+ v. major == version. major
133+ && v. minor == version. minor
134+ && v. patch == version. patch
135+ && v. pre == version. pre
136+ && ( v. build == version. build || v. build . is_empty ( ) )
137+ }
103138 }
104139 }
105140}
@@ -108,8 +143,9 @@ impl Display for OptVersionReq {
108143 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
109144 match self {
110145 OptVersionReq :: Any => f. write_str ( "*" ) ,
111- OptVersionReq :: Req ( req) => Display :: fmt ( req, f) ,
112- OptVersionReq :: Locked ( _, req) => Display :: fmt ( req, f) ,
146+ OptVersionReq :: Req ( req)
147+ | OptVersionReq :: Locked ( _, req)
148+ | OptVersionReq :: UpdatePrecise ( _, req) => Display :: fmt ( req, f) ,
113149 }
114150 }
115151}
0 commit comments