@@ -115,20 +115,30 @@ impl PackageIdSpec {
115115 if let Some ( ( kind_str, scheme) ) = url. scheme ( ) . split_once ( '+' ) {
116116 match kind_str {
117117 "git" => {
118- let git_ref = GitReference :: DefaultBranch ;
118+ let git_ref = GitReference :: from_query ( url. query_pairs ( ) ) ;
119+ url. set_query ( None ) ;
119120 kind = Some ( SourceKind :: Git ( git_ref) ) ;
120121 url = strip_url_protocol ( & url) ;
121122 }
122123 "registry" => {
124+ if url. query ( ) . is_some ( ) {
125+ bail ! ( "cannot have a query string in a pkgid: {}" , url)
126+ }
123127 kind = Some ( SourceKind :: Registry ) ;
124128 url = strip_url_protocol ( & url) ;
125129 }
126130 "sparse" => {
131+ if url. query ( ) . is_some ( ) {
132+ bail ! ( "cannot have a query string in a pkgid: {}" , url)
133+ }
127134 kind = Some ( SourceKind :: SparseRegistry ) ;
128135 // Leave `sparse` as part of URL
129136 // url = strip_url_protocol(&url);
130137 }
131138 "path" => {
139+ if url. query ( ) . is_some ( ) {
140+ bail ! ( "cannot have a query string in a pkgid: {}" , url)
141+ }
132142 if scheme != "file" {
133143 anyhow:: bail!( "`path+{scheme}` is unsupported; `path+file` and `file` schemes are supported" ) ;
134144 }
@@ -137,10 +147,10 @@ impl PackageIdSpec {
137147 }
138148 kind => anyhow:: bail!( "unsupported source protocol: {kind}" ) ,
139149 }
140- }
141-
142- if url . query ( ) . is_some ( ) {
143- bail ! ( "cannot have a query string in a pkgid: {}" , url )
150+ } else {
151+ if url . query ( ) . is_some ( ) {
152+ bail ! ( "cannot have a query string in a pkgid: {}" , url )
153+ }
144154 }
145155
146156 let frag = url. fragment ( ) . map ( |s| s. to_owned ( ) ) ;
@@ -347,6 +357,11 @@ impl fmt::Display for PackageIdSpec {
347357 write ! ( f, "{protocol}+" ) ?;
348358 }
349359 write ! ( f, "{}" , url) ?;
360+ if let Some ( SourceKind :: Git ( git_ref) ) = self . kind . as_ref ( ) {
361+ if let Some ( pretty) = git_ref. pretty_ref ( true ) {
362+ write ! ( f, "?{}" , pretty) ?;
363+ }
364+ }
350365 if url. path_segments ( ) . unwrap ( ) . next_back ( ) . unwrap ( ) != & * self . name {
351366 printed_name = true ;
352367 write ! ( f, "#{}" , self . name) ?;
@@ -625,6 +640,16 @@ mod tests {
625640 } ,
626641 "git+ssh://[email protected] /rust-lang/regex.git#[email protected] " , 627642 ) ;
643+ ok (
644+ "git+ssh://[email protected] /rust-lang/regex.git?branch=dev#[email protected] " , 645+ PackageIdSpec {
646+ name : String :: from ( "regex" ) ,
647+ version : Some ( "1.4.3" . parse ( ) . unwrap ( ) ) ,
648+ url : Some ( Url :: parse ( "ssh://[email protected] /rust-lang/regex.git" ) . unwrap ( ) ) , 649+ kind : Some ( SourceKind :: Git ( GitReference :: Branch ( "dev" . to_owned ( ) ) ) ) ,
650+ } ,
651+ "git+ssh://[email protected] /rust-lang/regex.git?branch=dev#[email protected] " , 652+ ) ;
628653 ok (
629654 "file:///path/to/my/project/foo" ,
630655 PackageIdSpec {
@@ -670,6 +695,18 @@ mod tests {
670695 PackageIdSpec :: parse( "foobar+https://github.com/rust-lang/crates.io-index" ) . is_err( )
671696 ) ;
672697 assert ! ( PackageIdSpec :: parse( "path+https://github.com/rust-lang/crates.io-index" ) . is_err( ) ) ;
698+
699+ // Only `git+` can use `?`
700+ assert ! ( PackageIdSpec :: parse( "file:///path/to/my/project/foo?branch=dev" ) . is_err( ) ) ;
701+ assert ! ( PackageIdSpec :: parse( "path+file:///path/to/my/project/foo?branch=dev" ) . is_err( ) ) ;
702+ assert ! ( PackageIdSpec :: parse(
703+ "registry+https://github.com/rust-lang/cargo#0.52.0?branch=dev"
704+ )
705+ . is_err( ) ) ;
706+ assert ! ( PackageIdSpec :: parse(
707+ "sparse+https://github.com/rust-lang/cargo#0.52.0?branch=dev"
708+ )
709+ . is_err( ) ) ;
673710 }
674711
675712 #[ test]
0 commit comments