@@ -115,20 +115,30 @@ impl PackageIdSpec {
115
115
if let Some ( ( kind_str, scheme) ) = url. scheme ( ) . split_once ( '+' ) {
116
116
match kind_str {
117
117
"git" => {
118
- let git_ref = GitReference :: DefaultBranch ;
118
+ let git_ref = GitReference :: from_query ( url. query_pairs ( ) ) ;
119
+ url. set_query ( None ) ;
119
120
kind = Some ( SourceKind :: Git ( git_ref) ) ;
120
121
url = strip_url_protocol ( & url) ;
121
122
}
122
123
"registry" => {
124
+ if url. query ( ) . is_some ( ) {
125
+ bail ! ( "cannot have a query string in a pkgid: {url}" )
126
+ }
123
127
kind = Some ( SourceKind :: Registry ) ;
124
128
url = strip_url_protocol ( & url) ;
125
129
}
126
130
"sparse" => {
131
+ if url. query ( ) . is_some ( ) {
132
+ bail ! ( "cannot have a query string in a pkgid: {url}" )
133
+ }
127
134
kind = Some ( SourceKind :: SparseRegistry ) ;
128
135
// Leave `sparse` as part of URL, see `SourceId::new`
129
136
// url = strip_url_protocol(&url);
130
137
}
131
138
"path" => {
139
+ if url. query ( ) . is_some ( ) {
140
+ bail ! ( "cannot have a query string in a pkgid: {url}" )
141
+ }
132
142
if scheme != "file" {
133
143
anyhow:: bail!( "`path+{scheme}` is unsupported; `path+file` and `file` schemes are supported" ) ;
134
144
}
@@ -137,10 +147,10 @@ impl PackageIdSpec {
137
147
}
138
148
kind => anyhow:: bail!( "unsupported source protocol: {kind}" ) ,
139
149
}
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
+ }
144
154
}
145
155
146
156
let frag = url. fragment ( ) . map ( |s| s. to_owned ( ) ) ;
@@ -347,6 +357,11 @@ impl fmt::Display for PackageIdSpec {
347
357
write ! ( f, "{protocol}+" ) ?;
348
358
}
349
359
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
+ }
350
365
if url. path_segments ( ) . unwrap ( ) . next_back ( ) . unwrap ( ) != & * self . name {
351
366
printed_name = true ;
352
367
write ! ( f, "#{}" , self . name) ?;
@@ -625,6 +640,16 @@ mod tests {
625
640
} ,
626
641
"git+ssh://[email protected] /rust-lang/regex.git#[email protected] " ,
627
642
) ;
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
+ ) ;
628
653
ok (
629
654
"file:///path/to/my/project/foo" ,
630
655
PackageIdSpec {
@@ -670,6 +695,18 @@ mod tests {
670
695
PackageIdSpec :: parse( "foobar+https://github.com/rust-lang/crates.io-index" ) . is_err( )
671
696
) ;
672
697
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( ) ) ;
673
710
}
674
711
675
712
#[ test]
0 commit comments