Subject: Re: bug#42504: guix refresh --update fails for Rust packages

From: Danny Milosavljevic <[email-masked]>
Date: Fri, 24 Jul 2020 11:23:30 +0200

'"z"' appears in guix/upstream.scm, 

(define* (package-update/url-fetch store package source
                                   #:key key-download)
  "Return the version, tarball, and SOURCE, to update PACKAGE to
SOURCE, an <upstream-source>."
  (match source
    (($ <upstream-source> _ version urls signature-urls)
     (let*-values (((archive-type)
                    (match (and=> (package-source package) origin-uri)
                      ((? string? uri)
                       (let ((type (file-extension (basename uri))))
                         ;; Sometimes we have URLs such as
                         ;; "https://github.com/…/tarball/v0.1", in which case
                         ;; we must not consider "1" as the extension.
                         (and (or (string-contains type "z")
                                  (string=? type "tar"))
                              type)))
                      (_
                       "gz")))
                   ((url signature-url)
                    ;; Try to find a URL that matches ARCHIVE-TYPE.
                    (find2 (lambda (url sig-url)
                             ;; Some URIs lack a file extension, like
                             ;; 'https://crates.io/???/0.1/download'.  In that
                             ;; case, pick the first URL.
                             (or (not archive-type)
                                 (string-suffix? archive-type url)))
                           urls
                           (or signature-urls (circular-list #f)))))
       ;; If none of URLS matches ARCHIVE-TYPE, then URL is #f; in that case,
       ;; pick up the first element of URLS.
       (let ((tarball (download-tarball store
                                        (or url (first urls))
                                        (and (pair? signature-urls)
                                             (or signature-url
                                                 (first signature-urls)))
                                        #:key-download key-download)))
         (values version tarball source))))))

And guix repl says:

scheme@(guix-user)> ,use (guix utils)
scheme@(guix-user)> (file-extension "https://crates.io/api/v1/crates/instant/0.1.2/download")
$1 = #f

But the case #f is not handled in the code above--which is why it doesn't work.

Could you test the following fix?

diff --git a/guix/upstream.scm b/guix/upstream.scm
index 70cbfb45e8..31bd6faea4 100644
--- a/guix/upstream.scm
+++ b/guix/upstream.scm
@@ -369,7 +369,7 @@ SOURCE, an <upstream-source>."
      (let*-values (((archive-type)
                     (match (and=> (package-source package) origin-uri)
                       ((? string? uri)
-                       (let ((type (file-extension (basename uri))))
+                       (let ((type (or (file-extension (basename uri)) "")))
                          ;; Sometimes we have URLs such as
                          ;; "https://github.com/…/tarball/v0.1", in which case
                          ;; we must not consider "1" as the extension.