@@ -10,7 +10,8 @@ use crate::core::PackageId;
1010use crate :: util:: edit_distance;
1111use crate :: util:: errors:: CargoResult ;
1212use crate :: util:: interning:: InternedString ;
13- use crate :: util:: { validate_package_name, IntoUrl , ToSemver } ;
13+ use crate :: util:: PartialVersion ;
14+ use crate :: util:: { validate_package_name, IntoUrl } ;
1415
1516/// Some or all of the data required to identify a package:
1617///
@@ -24,7 +25,7 @@ use crate::util::{validate_package_name, IntoUrl, ToSemver};
2425#[ derive( Clone , PartialEq , Eq , Debug , Hash , Ord , PartialOrd ) ]
2526pub struct PackageIdSpec {
2627 name : InternedString ,
27- version : Option < Version > ,
28+ version : Option < PartialVersion > ,
2829 url : Option < Url > ,
2930}
3031
@@ -70,7 +71,7 @@ impl PackageIdSpec {
7071 let mut parts = spec. splitn ( 2 , [ ':' , '@' ] ) ;
7172 let name = parts. next ( ) . unwrap ( ) ;
7273 let version = match parts. next ( ) {
73- Some ( version) => Some ( version. to_semver ( ) ?) ,
74+ Some ( version) => Some ( version. parse :: < PartialVersion > ( ) ?) ,
7475 None => None ,
7576 } ;
7677 validate_package_name ( name, "pkgid" , "" ) ?;
@@ -94,12 +95,12 @@ impl PackageIdSpec {
9495 spec. query ( i)
9596 }
9697
97- /// Convert a `PackageId` to a `PackageIdSpec`, which will have both the `Version ` and `Url`
98+ /// Convert a `PackageId` to a `PackageIdSpec`, which will have both the `PartialVersion ` and `Url`
9899 /// fields filled in.
99100 pub fn from_package_id ( package_id : PackageId ) -> PackageIdSpec {
100101 PackageIdSpec {
101102 name : package_id. name ( ) ,
102- version : Some ( package_id. version ( ) . clone ( ) ) ,
103+ version : Some ( package_id. version ( ) . clone ( ) . into ( ) ) ,
103104 url : Some ( package_id. source_id ( ) . url ( ) . clone ( ) ) ,
104105 }
105106 }
@@ -125,14 +126,14 @@ impl PackageIdSpec {
125126 match frag {
126127 Some ( fragment) => match fragment. split_once ( [ ':' , '@' ] ) {
127128 Some ( ( name, part) ) => {
128- let version = part. to_semver ( ) ?;
129+ let version = part. parse :: < PartialVersion > ( ) ?;
129130 ( InternedString :: new ( name) , Some ( version) )
130131 }
131132 None => {
132133 if fragment. chars ( ) . next ( ) . unwrap ( ) . is_alphabetic ( ) {
133134 ( InternedString :: new ( & fragment) , None )
134135 } else {
135- let version = fragment. to_semver ( ) ?;
136+ let version = fragment. parse :: < PartialVersion > ( ) ?;
136137 ( InternedString :: new ( path_name) , Some ( version) )
137138 }
138139 }
@@ -151,7 +152,12 @@ impl PackageIdSpec {
151152 self . name
152153 }
153154
154- pub fn version ( & self ) -> Option < & Version > {
155+ /// Full `semver::Version`, if present
156+ pub fn version ( & self ) -> Option < Version > {
157+ self . version . as_ref ( ) . and_then ( |v| v. version ( ) )
158+ }
159+
160+ pub fn partial_version ( & self ) -> Option < & PartialVersion > {
155161 self . version . as_ref ( )
156162 }
157163
@@ -170,7 +176,8 @@ impl PackageIdSpec {
170176 }
171177
172178 if let Some ( ref v) = self . version {
173- if v != package_id. version ( ) {
179+ let req = v. exact_req ( ) ;
180+ if !req. matches ( package_id. version ( ) ) {
174181 return false ;
175182 }
176183 }
@@ -322,7 +329,6 @@ mod tests {
322329 use super :: PackageIdSpec ;
323330 use crate :: core:: { PackageId , SourceId } ;
324331 use crate :: util:: interning:: InternedString ;
325- use crate :: util:: ToSemver ;
326332 use url:: Url ;
327333
328334 #[ test]
@@ -347,16 +353,25 @@ mod tests {
347353 "https://crates.io/foo#1.2.3" ,
348354 PackageIdSpec {
349355 name : InternedString :: new ( "foo" ) ,
350- version : Some ( "1.2.3" . to_semver ( ) . unwrap ( ) ) ,
356+ version : Some ( "1.2.3" . parse ( ) . unwrap ( ) ) ,
351357 url : Some ( Url :: parse ( "https://crates.io/foo" ) . unwrap ( ) ) ,
352358 } ,
353359 "https://crates.io/foo#1.2.3" ,
354360 ) ;
361+ ok (
362+ "https://crates.io/foo#1.2" ,
363+ PackageIdSpec {
364+ name : InternedString :: new ( "foo" ) ,
365+ version : Some ( "1.2" . parse ( ) . unwrap ( ) ) ,
366+ url : Some ( Url :: parse ( "https://crates.io/foo" ) . unwrap ( ) ) ,
367+ } ,
368+ "https://crates.io/foo#1.2" ,
369+ ) ;
355370 ok (
356371 "https://crates.io/foo#bar:1.2.3" ,
357372 PackageIdSpec {
358373 name : InternedString :: new ( "bar" ) ,
359- version : Some ( "1.2.3" . to_semver ( ) . unwrap ( ) ) ,
374+ version : Some ( "1.2.3" . parse ( ) . unwrap ( ) ) ,
360375 url : Some ( Url :: parse ( "https://crates.io/foo" ) . unwrap ( ) ) ,
361376 } ,
362377 "https://crates.io/foo#bar@1.2.3" ,
@@ -365,11 +380,20 @@ mod tests {
365380 "https://crates.io/foo#bar@1.2.3" ,
366381 PackageIdSpec {
367382 name : InternedString :: new ( "bar" ) ,
368- version : Some ( "1.2.3" . to_semver ( ) . unwrap ( ) ) ,
383+ version : Some ( "1.2.3" . parse ( ) . unwrap ( ) ) ,
369384 url : Some ( Url :: parse ( "https://crates.io/foo" ) . unwrap ( ) ) ,
370385 } ,
371386 "https://crates.io/foo#bar@1.2.3" ,
372387 ) ;
388+ ok (
389+ "https://crates.io/foo#bar@1.2" ,
390+ PackageIdSpec {
391+ name : InternedString :: new ( "bar" ) ,
392+ version : Some ( "1.2" . parse ( ) . unwrap ( ) ) ,
393+ url : Some ( Url :: parse ( "https://crates.io/foo" ) . unwrap ( ) ) ,
394+ } ,
395+ "https://crates.io/foo#bar@1.2" ,
396+ ) ;
373397 ok (
374398 "foo" ,
375399 PackageIdSpec {
@@ -383,7 +407,7 @@ mod tests {
383407 "foo:1.2.3" ,
384408 PackageIdSpec {
385409 name : InternedString :: new ( "foo" ) ,
386- version : Some ( "1.2.3" . to_semver ( ) . unwrap ( ) ) ,
410+ version : Some ( "1.2.3" . parse ( ) . unwrap ( ) ) ,
387411 url : None ,
388412 } ,
389413 "foo@1.2.3" ,
@@ -392,21 +416,29 @@ mod tests {
392416 "foo@1.2.3" ,
393417 PackageIdSpec {
394418 name : InternedString :: new ( "foo" ) ,
395- version : Some ( "1.2.3" . to_semver ( ) . unwrap ( ) ) ,
419+ version : Some ( "1.2.3" . parse ( ) . unwrap ( ) ) ,
396420 url : None ,
397421 } ,
398422 "foo@1.2.3" ,
399423 ) ;
424+ ok (
425+ "foo@1.2" ,
426+ PackageIdSpec {
427+ name : InternedString :: new ( "foo" ) ,
428+ version : Some ( "1.2" . parse ( ) . unwrap ( ) ) ,
429+ url : None ,
430+ } ,
431+ "foo@1.2" ,
432+ ) ;
400433 }
401434
402435 #[ test]
403436 fn bad_parsing ( ) {
404437 assert ! ( PackageIdSpec :: parse( "baz:" ) . is_err( ) ) ;
405438 assert ! ( PackageIdSpec :: parse( "baz:*" ) . is_err( ) ) ;
406- assert ! ( PackageIdSpec :: parse( "baz:1.0" ) . is_err( ) ) ;
407439 assert ! ( PackageIdSpec :: parse( "baz@" ) . is_err( ) ) ;
408440 assert ! ( PackageIdSpec :: parse( "baz@*" ) . is_err( ) ) ;
409- assert ! ( PackageIdSpec :: parse( "baz@1.0" ) . is_err( ) ) ;
441+ assert ! ( PackageIdSpec :: parse( "baz@^ 1.0" ) . is_err( ) ) ;
410442 assert ! ( PackageIdSpec :: parse( "https://baz:1.0" ) . is_err( ) ) ;
411443 assert ! ( PackageIdSpec :: parse( "https://#baz:1.0" ) . is_err( ) ) ;
412444 }
@@ -424,5 +456,6 @@ mod tests {
424456 assert ! ( !PackageIdSpec :: parse( "foo:1.2.2" ) . unwrap( ) . matches( foo) ) ;
425457 assert ! ( PackageIdSpec :: parse( "foo@1.2.3" ) . unwrap( ) . matches( foo) ) ;
426458 assert ! ( !PackageIdSpec :: parse( "foo@1.2.2" ) . unwrap( ) . matches( foo) ) ;
459+ assert ! ( PackageIdSpec :: parse( "foo@1.2" ) . unwrap( ) . matches( foo) ) ;
427460 }
428461}
0 commit comments