22package flake
33
44import (
5- "maps "
5+ "cmp "
66 "net/url"
77 "path"
88 "slices"
@@ -167,8 +167,9 @@ func parseURLRef(ref string) (parsed Ref, fragment string, err error) {
167167 parsed .Path = refURL .Path
168168 }
169169
170- parsed .NARHash = refURL .Query ().Get ("narHash" )
171- parsed .LastModified , err = atoiOmitZero (refURL .Query ().Get ("lastModified" ))
170+ query := refURL .Query ()
171+ parsed .NARHash = query .Get ("narHash" )
172+ parsed .LastModified , err = atoiOmitZero (query .Get ("lastModified" ))
172173 if err != nil {
173174 return Ref {}, "" , redact .Errorf ("parse flake reference URL query parameter: lastModified=%s: %v" , redact .Safe (parsed .LastModified ), redact .Safe (err ))
174175 }
@@ -180,8 +181,8 @@ func parseURLRef(ref string) (parsed Ref, fragment string, err error) {
180181 }
181182 query := refURL .Query ()
182183 parsed .Dir = query .Get ("dir" )
183- parsed .NARHash = refURL . Query () .Get ("narHash" )
184- parsed .LastModified , err = atoiOmitZero (refURL . Query () .Get ("lastModified" ))
184+ parsed .NARHash = query .Get ("narHash" )
185+ parsed .LastModified , err = atoiOmitZero (query .Get ("lastModified" ))
185186 if err != nil {
186187 return Ref {}, "" , redact .Errorf ("parse flake reference URL query parameter: lastModified=%s: %v" , redact .Safe (parsed .LastModified ), redact .Safe (err ))
187188 }
@@ -196,8 +197,8 @@ func parseURLRef(ref string) (parsed Ref, fragment string, err error) {
196197 parsed .Type = TypeTarball
197198 query := refURL .Query ()
198199 parsed .Dir = query .Get ("dir" )
199- parsed .NARHash = refURL . Query () .Get ("narHash" )
200- parsed .LastModified , err = atoiOmitZero (refURL . Query () .Get ("lastModified" ))
200+ parsed .NARHash = query .Get ("narHash" )
201+ parsed .LastModified , err = atoiOmitZero (query .Get ("lastModified" ))
201202 if err != nil {
202203 return Ref {}, "" , redact .Errorf ("parse flake reference URL query parameter: lastModified=%s: %v" , redact .Safe (parsed .LastModified ), redact .Safe (err ))
203204 }
@@ -213,8 +214,8 @@ func parseURLRef(ref string) (parsed Ref, fragment string, err error) {
213214 parsed .Type = TypeFile
214215 query := refURL .Query ()
215216 parsed .Dir = query .Get ("dir" )
216- parsed .NARHash = refURL . Query () .Get ("narHash" )
217- parsed .LastModified , err = atoiOmitZero (refURL . Query () .Get ("lastModified" ))
217+ parsed .NARHash = query .Get ("narHash" )
218+ parsed .LastModified , err = atoiOmitZero (query .Get ("lastModified" ))
218219 if err != nil {
219220 return Ref {}, "" , redact .Errorf ("parse flake reference URL query parameter: lastModified=%s: %v" , redact .Safe (parsed .LastModified ), redact .Safe (err ))
220221 }
@@ -228,16 +229,16 @@ func parseURLRef(ref string) (parsed Ref, fragment string, err error) {
228229 parsed .URL = refURL .String ()
229230 case "git" , "git+http" , "git+https" , "git+ssh" , "git+git" , "git+file" :
230231 parsed .Type = TypeGit
231- q := refURL .Query ()
232- parsed .Dir = q .Get ("dir" )
233- parsed .Ref = q .Get ("ref" )
234- parsed .Rev = q .Get ("rev" )
232+ query := refURL .Query ()
233+ parsed .Dir = query .Get ("dir" )
234+ parsed .Ref = query .Get ("ref" )
235+ parsed .Rev = query .Get ("rev" )
235236
236237 // ref and rev get stripped from the query parameters, but dir
237238 // stays.
238- q .Del ("ref" )
239- q .Del ("rev" )
240- refURL .RawQuery = q .Encode ()
239+ query .Del ("ref" )
240+ query .Del ("rev" )
241+ refURL .RawQuery = query .Encode ()
241242 if len (refURL .Scheme ) > 3 {
242243 refURL .Scheme = refURL .Scheme [4 :] // remove git+
243244 }
@@ -360,7 +361,7 @@ func (r Ref) String() string {
360361 // messed with the parsed URL.
361362 return ""
362363 }
363- url .RawQuery = buildQueryString (url .Query (),
364+ url .RawQuery = appendQueryString (url .Query (),
364365 "lastModified" , itoaOmitZero (r .LastModified ),
365366 "narHash" , r .NARHash ,
366367 )
@@ -386,7 +387,7 @@ func (r Ref) String() string {
386387 // messed with the parsed URL.
387388 return ""
388389 }
389- url .RawQuery = buildQueryString (url .Query (), "ref" , r .Ref , "rev" , r .Rev , "dir" , r .Dir )
390+ url .RawQuery = appendQueryString (url .Query (), "ref" , r .Ref , "rev" , r .Rev , "dir" , r .Dir )
390391 return url .String ()
391392 case TypeGitHub :
392393 if r .Owner == "" || r .Repo == "" {
@@ -395,7 +396,7 @@ func (r Ref) String() string {
395396 url := & url.URL {
396397 Scheme : "github" ,
397398 Opaque : buildEscapedPath (r .Owner , r .Repo , r .Rev , r .Ref ),
398- RawQuery : buildQueryString (nil ,
399+ RawQuery : appendQueryString (nil ,
399400 "host" , r .Host ,
400401 "dir" , r .Dir ,
401402 "lastModified" , itoaOmitZero (r .LastModified ),
@@ -410,7 +411,7 @@ func (r Ref) String() string {
410411 url := & url.URL {
411412 Scheme : "flake" ,
412413 Opaque : buildEscapedPath (r .ID , r .Ref , r .Rev ),
413- RawQuery : buildQueryString (nil ,
414+ RawQuery : appendQueryString (nil ,
414415 "dir" , r .Dir ,
415416 "lastModified" , itoaOmitZero (r .LastModified ),
416417 "narHash" , r .NARHash ,
@@ -434,7 +435,7 @@ func (r Ref) String() string {
434435 url .Opaque = "."
435436 }
436437
437- url .RawQuery = buildQueryString (nil ,
438+ url .RawQuery = appendQueryString (nil ,
438439 "lastModified" , itoaOmitZero (r .LastModified ),
439440 "narHash" , r .NARHash ,
440441 )
@@ -453,7 +454,7 @@ func (r Ref) String() string {
453454 // messed with the parsed URL.
454455 return ""
455456 }
456- url .RawQuery = buildQueryString (url .Query (),
457+ url .RawQuery = appendQueryString (url .Query (),
457458 "dir" , r .Dir ,
458459 "lastModified" , itoaOmitZero (r .LastModified ),
459460 "narHash" , r .NARHash ,
@@ -532,22 +533,27 @@ func buildEscapedPath(elem ...string) string {
532533 return u .JoinPath (elem ... ).String ()
533534}
534535
535- // buildQueryString builds a URL query string from a list of key-value string
536+ // appendQueryString builds a URL query string from a list of key-value string
536537// pairs, omitting any keys with empty values.
537- func buildQueryString ( initial url.Values , keyval ... string ) string {
538+ func appendQueryString ( query url.Values , keyval ... string ) string {
538539 if len (keyval )% 2 != 0 {
539- panic ("buildQueryString : odd number of key-value pairs" )
540+ panic ("appendQueryString : odd number of key-value pairs" )
540541 }
541542
542- q := make (url.Values , len (initial )+ len (keyval )/ 2 )
543- maps .Copy (q , initial )
543+ appended := make (url.Values , len (query )+ len (keyval )/ 2 )
544+ for k , vals := range query {
545+ v := cmp .Or (vals ... )
546+ if v != "" {
547+ appended .Set (k , v )
548+ }
549+ }
544550 for i := 0 ; i < len (keyval ); i += 2 {
545551 k , v := keyval [i ], keyval [i + 1 ]
546552 if v != "" {
547- q .Set (k , v )
553+ appended .Set (k , v )
548554 }
549555 }
550- return q .Encode ()
556+ return appended .Encode ()
551557}
552558
553559// itoaOmitZero returns an empty string if i == 0, otherwise it formats i as a
0 commit comments