@@ -196,13 +196,13 @@ impl EncodableResolve {
196196 let enc_id = EncodablePackageId {
197197 name : pkg. name . clone ( ) ,
198198 version : Some ( pkg. version . clone ( ) ) ,
199- source : pkg. source ,
199+ source : pkg. source . clone ( ) ,
200200 } ;
201201
202202 if !all_pkgs. insert ( enc_id. clone ( ) ) {
203203 anyhow:: bail!( "package `{}` is specified twice in the lockfile" , pkg. name) ;
204204 }
205- let id = match pkg. source . as_ref ( ) . or_else ( || path_deps. get ( & pkg. name ) ) {
205+ let id = match pkg. source . as_deref ( ) . or_else ( || path_deps. get ( & pkg. name ) ) {
206206 // We failed to find a local package in the workspace.
207207 // It must have been removed and should be ignored.
208208 None => {
@@ -366,7 +366,7 @@ impl EncodableResolve {
366366
367367 let mut unused_patches = Vec :: new ( ) ;
368368 for pkg in self . patch . unused {
369- let id = match pkg. source . as_ref ( ) . or_else ( || path_deps. get ( & pkg. name ) ) {
369+ let id = match pkg. source . as_deref ( ) . or_else ( || path_deps. get ( & pkg. name ) ) {
370370 Some ( & src) => PackageId :: new ( & pkg. name , & pkg. version , src) ?,
371371 None => continue ,
372372 } ;
@@ -488,17 +488,95 @@ impl Patch {
488488pub struct EncodableDependency {
489489 name : String ,
490490 version : String ,
491- source : Option < SourceId > ,
491+ source : Option < EncodableSourceId > ,
492492 checksum : Option < String > ,
493493 dependencies : Option < Vec < EncodablePackageId > > ,
494494 replace : Option < EncodablePackageId > ,
495495}
496496
497+ /// Pretty much equivalent to [`SourceId`] with a different serialization method.
498+ ///
499+ /// The serialization for `SourceId` doesn't do URL encode for parameters.
500+ /// In contrast, this type is aware of that whenever [`ResolveVersion`] allows
501+ /// us to do so (v4 or later).
502+ ///
503+ /// [`EncodableResolve`] turns into a `
504+ #[ derive( Deserialize , Debug , PartialOrd , Ord , Clone ) ]
505+ #[ serde( transparent) ]
506+ pub struct EncodableSourceId {
507+ inner : SourceId ,
508+ /// We don't care about the deserialization of this, as the `url` crate
509+ /// will always decode as the URL was encoded. Only when a [`Resolve`]
510+ /// turns into a [`EncodableResolve`] will it set the value accordingly
511+ /// via [`encodable_source_id`].
512+ #[ serde( skip) ]
513+ encoded : bool ,
514+ }
515+
516+ impl EncodableSourceId {
517+ /// Creates a `EncodableSourceId` that always encodes URL params.
518+ fn new ( inner : SourceId ) -> Self {
519+ Self {
520+ inner,
521+ encoded : true ,
522+ }
523+ }
524+
525+ /// Creates a `EncodableSourceId` that doesn't encode URL params. This is
526+ /// for backward compatibility for order lockfile version.
527+ fn without_url_encoded ( inner : SourceId ) -> Self {
528+ Self {
529+ inner,
530+ encoded : false ,
531+ }
532+ }
533+
534+ /// Encodes the inner [`SourceId`] as a URL.
535+ fn as_url ( & self ) -> impl fmt:: Display + ' _ {
536+ if self . encoded {
537+ self . inner . as_encoded_url ( )
538+ } else {
539+ self . inner . as_url ( )
540+ }
541+ }
542+ }
543+
544+ impl std:: ops:: Deref for EncodableSourceId {
545+ type Target = SourceId ;
546+
547+ fn deref ( & self ) -> & Self :: Target {
548+ & self . inner
549+ }
550+ }
551+
552+ impl ser:: Serialize for EncodableSourceId {
553+ fn serialize < S > ( & self , s : S ) -> Result < S :: Ok , S :: Error >
554+ where
555+ S : ser:: Serializer ,
556+ {
557+ s. collect_str ( & self . as_url ( ) )
558+ }
559+ }
560+
561+ impl std:: hash:: Hash for EncodableSourceId {
562+ fn hash < H : std:: hash:: Hasher > ( & self , state : & mut H ) {
563+ self . inner . hash ( state)
564+ }
565+ }
566+
567+ impl std:: cmp:: PartialEq for EncodableSourceId {
568+ fn eq ( & self , other : & Self ) -> bool {
569+ self . inner == other. inner
570+ }
571+ }
572+
573+ impl std:: cmp:: Eq for EncodableSourceId { }
574+
497575#[ derive( Debug , PartialOrd , Ord , PartialEq , Eq , Hash , Clone ) ]
498576pub struct EncodablePackageId {
499577 name : String ,
500578 version : Option < String > ,
501- source : Option < SourceId > ,
579+ source : Option < EncodableSourceId > ,
502580}
503581
504582impl fmt:: Display for EncodablePackageId {
@@ -535,7 +613,8 @@ impl FromStr for EncodablePackageId {
535613 Ok ( EncodablePackageId {
536614 name : name. to_string ( ) ,
537615 version : version. map ( |v| v. to_string ( ) ) ,
538- source : source_id,
616+ // Default to url encoded.
617+ source : source_id. map ( EncodableSourceId :: new) ,
539618 } )
540619 }
541620}
@@ -603,7 +682,7 @@ impl ser::Serialize for Resolve {
603682 . map ( |id| EncodableDependency {
604683 name : id. name ( ) . to_string ( ) ,
605684 version : id. version ( ) . to_string ( ) ,
606- source : encode_source ( id. source_id ( ) ) ,
685+ source : encodable_source_id ( id. source_id ( ) , self . version ( ) ) ,
607686 dependencies : None ,
608687 replace : None ,
609688 checksum : if self . version ( ) >= ResolveVersion :: V2 {
@@ -676,7 +755,7 @@ fn encodable_resolve_node(
676755 EncodableDependency {
677756 name : id. name ( ) . to_string ( ) ,
678757 version : id. version ( ) . to_string ( ) ,
679- source : encode_source ( id. source_id ( ) ) ,
758+ source : encodable_source_id ( id. source_id ( ) , resolve . version ( ) ) ,
680759 dependencies : deps,
681760 replace,
682761 checksum : if resolve. version ( ) >= ResolveVersion :: V2 {
@@ -702,7 +781,7 @@ pub fn encodable_package_id(
702781 }
703782 }
704783 }
705- let mut source = encode_source ( id_to_encode) . map ( |s| s . with_precise ( None ) ) ;
784+ let mut source = encodable_source_id ( id_to_encode. with_precise ( None ) , resolve_version ) ;
706785 if let Some ( counts) = & state. counts {
707786 let version_counts = & counts[ & id. name ( ) ] ;
708787 if version_counts[ & id. version ( ) ] == 1 {
@@ -719,10 +798,13 @@ pub fn encodable_package_id(
719798 }
720799}
721800
722- fn encode_source ( id : SourceId ) -> Option < SourceId > {
801+ fn encodable_source_id ( id : SourceId , version : ResolveVersion ) -> Option < EncodableSourceId > {
723802 if id. is_path ( ) {
724803 None
725804 } else {
726- Some ( id)
805+ Some ( match version {
806+ ResolveVersion :: V4 => EncodableSourceId :: new ( id) ,
807+ _ => EncodableSourceId :: without_url_encoded ( id) ,
808+ } )
727809 }
728810}
0 commit comments