@@ -120,30 +120,24 @@ impl TryFrom<&'_ PackageId> for Crate {
120
120
pkgid. repr
121
121
) ,
122
122
}
123
- } else if let Some ( ( kind_proto, host_path_query_anchor) ) = pkgid. repr . split_once ( "://" ) {
124
- let ( kind, proto) = if let Some ( ( kind, proto) ) = kind_proto. split_once ( '+' ) {
123
+ } else if pkgid. repr . contains ( "://" ) {
124
+ // Cargo Package Id Spec URL format
125
+ // <https://doc.rust-lang.org/cargo/reference/pkgid-spec.html>
126
+
127
+ let pkg_url = url:: Url :: parse ( & pkgid. repr ) ?;
128
+
129
+ let ( kind, proto) = if let Some ( ( kind, proto) ) = pkg_url. scheme ( ) . split_once ( '+' ) {
125
130
( Some ( kind) , proto)
126
131
} else {
127
- ( None , kind_proto )
132
+ ( None , pkg_url . scheme ( ) )
128
133
} ;
129
134
130
- let ( host_path_query, anchor) =
131
- if let Some ( ( host_path_query, anchor) ) = host_path_query_anchor. split_once ( '#' ) {
132
- ( host_path_query, Some ( anchor) )
133
- } else {
134
- ( host_path_query_anchor, None )
135
- } ;
135
+ let anchor = pkg_url. fragment ( ) ;
136
+ let query = pkg_url. query ( ) ;
136
137
137
- let ( host_path, query) =
138
- if let Some ( ( host_path, query) ) = host_path_query. split_once ( '?' ) {
139
- ( host_path, Some ( query) )
140
- } else {
141
- ( host_path_query, None )
142
- } ;
143
-
144
- match ( kind, proto, query) {
145
- ( Some ( "path" ) | None , "file" , None ) => Ok ( Crate :: Path ( host_path. to_string ( ) ) ) ,
146
- ( Some ( "registry" ) , _, None ) => {
138
+ match ( kind, proto) {
139
+ ( Some ( "path" ) | None , "file" ) => Ok ( Crate :: Path ( pkg_url. path ( ) . to_string ( ) ) ) ,
140
+ ( Some ( "registry" ) , _) => {
147
141
if let Some ( anchor) = anchor {
148
142
if let Some ( ( package_name, version) ) = anchor. split_once ( [ '@' , ':' ] ) {
149
143
Ok ( Crate :: Registry ( RegistryCrate {
@@ -175,7 +169,9 @@ impl TryFrom<&'_ PackageId> for Crate {
175
169
)
176
170
}
177
171
178
- let Some ( package_name) = host_path. split ( '/' ) . last ( ) else {
172
+ let Some ( package_name) =
173
+ pkg_url. path_segments ( ) . and_then ( |segments| segments. last ( ) )
174
+ else {
179
175
bail ! (
180
176
"malformed pkgid format: {}\n maybe the representation has changed?" ,
181
177
pkgid. repr
@@ -194,73 +190,68 @@ impl TryFrom<&'_ PackageId> for Crate {
194
190
)
195
191
}
196
192
}
197
- ( None , "http" | "https" , _) | ( Some ( "git" ) , _, _)
198
- if host_path. starts_with ( "github.com/" ) =>
199
- {
200
- let mut parts = host_path. split ( '/' ) . skip ( 1 ) ;
201
- let Some ( org) = parts. next ( ) else {
202
- bail ! (
193
+ ( Some ( "git" ) , _) | ( None , "ssh" | "git" | "http" | "https" ) => {
194
+ let sha = if let Some ( query) = query {
195
+ let Some ( ( query_kind, rev) ) = query. split_once ( '=' ) else {
196
+ bail ! (
197
+ "malformed pkgid format: {}\n maybe the representation has changed?" ,
198
+ pkgid. repr
199
+ )
200
+ } ;
201
+ match query_kind {
202
+ "branch" | "tag" | "rev" => Some ( rev. to_string ( ) ) ,
203
+ _ => {
204
+ bail ! (
203
205
"malformed pkgid format: {}\n maybe the representation has changed?" ,
204
206
pkgid. repr
205
207
)
208
+ }
209
+ }
210
+ } else {
211
+ None
206
212
} ;
207
213
208
- let name = if let Some ( ( package_name, _version) ) =
209
- anchor. and_then ( |anchor| anchor. split_once ( [ '@' , ':' ] ) )
210
- {
211
- package_name
212
- } else if let Some ( name) = parts. next ( ) {
213
- name
214
- } else {
215
- bail ! (
214
+ if pkg_url. domain ( ) == Some ( "github.com" ) {
215
+ let Some ( org) = pkg_url
216
+ . path_segments ( )
217
+ . and_then ( |mut segments| segments. next ( ) )
218
+ else {
219
+ bail ! (
216
220
"malformed pkgid format: {}\n maybe the representation has changed?" ,
217
221
pkgid. repr
218
222
)
219
- } ;
220
-
221
- Ok ( Crate :: GitHub ( GitHubRepo {
222
- org : org. to_string ( ) ,
223
- name : name. to_string ( ) ,
224
- sha : None ,
225
- } ) )
226
- }
223
+ } ;
227
224
228
- ( Some ( "git" ) , _, None ) | ( None , "ssh" | "git" | "http" | "https" , None ) => {
229
- let kind = if let Some ( kind) = kind {
230
- format ! { "{kind}+" }
231
- } else {
232
- String :: new ( )
233
- } ;
234
- Ok ( Crate :: Git ( GitRepo {
235
- url : format ! ( "{kind}{proto}://{host_path}" ) ,
236
- sha : None ,
237
- } ) )
238
- }
239
- ( Some ( "git" ) , _, Some ( query) )
240
- | ( None , "ssh" | "git" | "http" | "https" , Some ( query) ) => {
241
- let Some ( ( query_kind, rev) ) = query. split_once ( '=' ) else {
242
- bail ! (
225
+ let name = if let Some ( ( package_name, _version) ) =
226
+ anchor. and_then ( |anchor| anchor. split_once ( [ '@' , ':' ] ) )
227
+ {
228
+ package_name
229
+ } else if let Some ( name) = pkg_url
230
+ . path_segments ( )
231
+ . and_then ( |mut segments| segments. nth ( 1 ) )
232
+ {
233
+ name
234
+ } else {
235
+ bail ! (
243
236
"malformed pkgid format: {}\n maybe the representation has changed?" ,
244
237
pkgid. repr
245
238
)
246
- } ;
239
+ } ;
247
240
248
- let kind = if let Some ( kind) = kind {
249
- format ! { "{kind}+" }
241
+ Ok ( Crate :: GitHub ( GitHubRepo {
242
+ org : org. to_string ( ) ,
243
+ name : name. to_string ( ) ,
244
+ sha,
245
+ } ) )
250
246
} else {
251
- String :: new ( )
252
- } ;
253
- match query_kind {
254
- "branch" | "tag" | "rev" => Ok ( Crate :: Git ( GitRepo {
255
- url : format ! ( "{kind}{proto}://{host_path}" ) ,
256
- sha : Some ( rev. to_string ( ) ) ,
257
- } ) ) ,
258
- _ => {
259
- bail ! (
260
- "malformed pkgid format: {}\n maybe the representation has changed?" ,
261
- pkgid. repr
262
- )
263
- }
247
+ let mut repo_url = pkg_url. clone ( ) ;
248
+ repo_url. set_fragment ( None ) ;
249
+ repo_url. set_query ( None ) ;
250
+
251
+ Ok ( Crate :: Git ( GitRepo {
252
+ url : repo_url. to_string ( ) ,
253
+ sha,
254
+ } ) )
264
255
}
265
256
}
266
257
_ => bail ! (
@@ -269,11 +260,15 @@ impl TryFrom<&'_ PackageId> for Crate {
269
260
) ,
270
261
}
271
262
} else if let Some ( ( package_name, version) ) = pkgid. repr . split_once ( [ '@' , ':' ] ) {
263
+ // Cargo Package Id Spec
264
+ // name ("@"|":") semver
272
265
Ok ( Crate :: Registry ( RegistryCrate {
273
266
name : package_name. to_string ( ) ,
274
267
version : version. to_string ( ) ,
275
268
} ) )
276
269
} else {
270
+ // Cargo Package Id Spec
271
+ // name only
277
272
Ok ( Crate :: Registry ( RegistryCrate {
278
273
name : pkgid. repr . clone ( ) ,
279
274
version : "unknown" . to_string ( ) ,
@@ -434,20 +429,28 @@ mod tests {
434
429
name: "cargo-platform" . to_string( ) ,
435
430
sha: None
436
431
} ) ,
437
-
438
- "ssh://git@github.com/ rust-lang/regex.git#regex@1.4.3" => Crate :: Git ( GitRepo {
439
- url : "ssh://git@github.com/rust-lang/ regex.git " . to_string( ) ,
432
+ "ssh://git@github.com/rust-lang/regex.git#regex@1.4.3" => Crate :: GitHub ( GitHubRepo {
433
+ org : " rust-lang" . to_string ( ) ,
434
+ name : "regex" . to_string( ) ,
440
435
sha: None
441
436
} ) ,
442
- "git+ssh://git@github.com/rust-lang/regex.git#regex@1.4.3" => Crate :: Git ( GitRepo {
443
- url: "git+ssh://git@github.com/rust-lang/regex.git" . to_string( ) ,
437
+ "git+ssh://git@github.com/rust-lang/regex.git#regex@1.4.3" => Crate :: GitHub ( GitHubRepo {
438
+ org: "rust-lang" . to_string( ) ,
439
+ name: "regex" . to_string( ) ,
444
440
sha: None
445
441
} ) ,
446
- "git+ssh://git@github.com/rust-lang/regex.git?branch=dev#regex@1.4.3" => Crate :: Git ( GitRepo {
447
- url: "git+ssh://git@github.com/rust-lang/regex.git" . to_string( ) ,
442
+ "git+ssh://git@github.com/rust-lang/regex.git?branch=dev#regex@1.4.3" => Crate :: GitHub ( GitHubRepo {
443
+ org: "rust-lang" . to_string( ) ,
444
+ name: "regex" . to_string( ) ,
448
445
sha: Some ( "dev" . to_string( ) )
449
446
} ) ,
450
447
448
+ "git+https://gitlab.com/dummy_org/dummy?rev=9823f01cf4948a41279f6a3febcf793130cab4f6" => Crate :: Git ( GitRepo {
449
+ url: "git+https://gitlab.com/dummy_org/dummy"
450
+ . to_string( ) ,
451
+ sha: Some ( "9823f01cf4948a41279f6a3febcf793130cab4f6" . to_string( ) )
452
+ } ) ,
453
+
451
454
"file:///path/to/my/project/foo" => Crate :: Path ( "/path/to/my/project/foo" . to_string( ) ) ,
452
455
"file:///path/to/my/project/foo#1.1.8" => Crate :: Path ( "/path/to/my/project/foo" . to_string( ) ) ,
453
456
"path+file:///path/to/my/project/foo#1.1.8" => Crate :: Path ( "/path/to/my/project/foo" . to_string( ) ) ,
0 commit comments