@@ -109,9 +109,13 @@ impl TomlLockfileSourceId {
109109 EncodableSourceIdError ( EncodableSourceIdErrorKind :: InvalidSource ( source. clone ( ) ) . into ( ) )
110110 } ) ?;
111111
112- let url = Url :: parse ( url) . map_err ( |msg| EncodableSourceIdErrorKind :: InvalidUrl {
113- url : url. to_string ( ) ,
114- msg : msg. to_string ( ) ,
112+ // Sparse URLs store the kind prefix (sparse+) in the URL. Therefore, for sparse kinds, we
113+ // want to use the raw `source` instead of the splitted `url`.
114+ let url = Url :: parse ( if kind == "sparse" { & source } else { url } ) . map_err ( |msg| {
115+ EncodableSourceIdErrorKind :: InvalidUrl {
116+ url : url. to_string ( ) ,
117+ msg : msg. to_string ( ) ,
118+ }
115119 } ) ?;
116120
117121 let kind = match kind {
@@ -317,3 +321,83 @@ fn dump_lockfile_schema() {
317321 let dump = serde_json:: to_string_pretty ( & schema) . unwrap ( ) ;
318322 snapbox:: assert_data_eq!( dump, snapbox:: file!( "../lockfile.schema.json" ) . raw( ) ) ;
319323}
324+
325+ #[ cfg( test) ]
326+ mod tests {
327+ use crate :: core:: { GitReference , SourceKind } ;
328+ use crate :: lockfile:: { EncodableSourceIdErrorKind , TomlLockfileSourceId } ;
329+
330+ #[ track_caller]
331+ fn ok ( source_str : & str , source_kind : SourceKind , url : & str ) {
332+ let source_str = source_str. to_owned ( ) ;
333+ let source_id = TomlLockfileSourceId :: new ( source_str) . unwrap ( ) ;
334+ assert_eq ! ( source_id. kind, source_kind) ;
335+ assert_eq ! ( source_id. url( ) . to_string( ) , url) ;
336+ }
337+
338+ macro_rules! err {
339+ ( $src: expr, $expected: pat) => {
340+ let kind = TomlLockfileSourceId :: new( $src. to_owned( ) ) . unwrap_err( ) . 0 ;
341+ assert!(
342+ matches!( kind, $expected) ,
343+ "`{}` parse error mismatch, got {kind:?}" ,
344+ $src,
345+ ) ;
346+ } ;
347+ }
348+
349+ #[ test]
350+ fn good_sources ( ) {
351+ ok (
352+ "sparse+https://my-crates.io" ,
353+ SourceKind :: SparseRegistry ,
354+ "sparse+https://my-crates.io" ,
355+ ) ;
356+ ok (
357+ "registry+https://github.com/rust-lang/crates.io-index" ,
358+ SourceKind :: Registry ,
359+ "https://github.com/rust-lang/crates.io-index" ,
360+ ) ;
361+ ok (
362+ "git+https://github.com/rust-lang/cargo" ,
363+ SourceKind :: Git ( GitReference :: DefaultBranch ) ,
364+ "https://github.com/rust-lang/cargo" ,
365+ ) ;
366+ ok (
367+ "git+https://github.com/rust-lang/cargo?branch=dev" ,
368+ SourceKind :: Git ( GitReference :: Branch ( "dev" . to_owned ( ) ) ) ,
369+ "https://github.com/rust-lang/cargo?branch=dev" ,
370+ ) ;
371+ ok (
372+ "git+https://github.com/rust-lang/cargo?tag=v1.0" ,
373+ SourceKind :: Git ( GitReference :: Tag ( "v1.0" . to_owned ( ) ) ) ,
374+ "https://github.com/rust-lang/cargo?tag=v1.0" ,
375+ ) ;
376+ ok (
377+ "git+https://github.com/rust-lang/cargo?rev=refs/pull/493/head" ,
378+ SourceKind :: Git ( GitReference :: Rev ( "refs/pull/493/head" . to_owned ( ) ) ) ,
379+ "https://github.com/rust-lang/cargo?rev=refs/pull/493/head" ,
380+ ) ;
381+ ok (
382+ "path+file:///path/to/root" ,
383+ SourceKind :: Path ,
384+ "file:///path/to/root" ,
385+ ) ;
386+ }
387+
388+ #[ test]
389+ fn bad_sources ( ) {
390+ err ! (
391+ "unknown+https://my-crates.io" ,
392+ EncodableSourceIdErrorKind :: UnsupportedSource ( ..)
393+ ) ;
394+ err ! (
395+ "registry+https//github.com/rust-lang/crates.io-index" ,
396+ EncodableSourceIdErrorKind :: InvalidUrl { .. }
397+ ) ;
398+ err ! (
399+ "https//github.com/rust-lang/crates.io-index" ,
400+ EncodableSourceIdErrorKind :: InvalidSource ( ..)
401+ ) ;
402+ }
403+ }
0 commit comments