~ruther/guix-local

fbc2a52a32ddc664db8ebab420c2e17b1432c744 — Timothy Sample 5 years ago df0b723
download: Use Disarchive as a last resort.

This is a fixed version of 66b14dccdd0d83c875ce3a8d50ceab8b6f0a3ce2,
which was reverted in e74250c3c535b75dd2225a26df51febb7ed94654.

* guix/download.scm (%disarchive-mirrors): New variable.
(%disarchive-mirror-file): New variable.
(built-in-download): Add 'disarchive-mirrors' keyword argument and
pass its value along to the 'builtin:download' derivation.
(url-fetch): Pass '%disarchive-mirror-file' to 'built-in-download'.
* guix/scripts/perform-download.scm (perform-download): Read
Disarchive mirrors from the environment and pass them to
'url-fetch'.
* guix/build/download.scm (disarchive-fetch/any): New procedure.
(url-fetch): Add 'disarchive-mirrors' keyword argument, use it to
make a list of URIs, and use the new procedure to fetch the file if
all other methods fail.
* build-aux/build-self.scm (build-program)[select?]: Exclude '(guix
build download)'.
* guix/self.scm (compiled-guix)[*core-modules*]: Add 'guile-json' to
the list of extensions.
M build-aux/build-self.scm => build-aux/build-self.scm +1 -0
@@ 250,6 250,7 @@ interface (FFI) of Guile.")
    (match-lambda
      (('guix 'config) #f)
      (('guix 'channels) #f)
      (('guix 'build 'download) #f)             ;autoloaded by (guix download)
      (('guix _ ...)   #t)
      (('gnu _ ...)    #t)
      (_               #f)))

M guix/build/download.scm => guix/build/download.scm +73 -10
@@ 2,6 2,7 @@
;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
;;; Copyright © 2017 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2021 Timothy Sample <samplet@ngyro.com>
;;;
;;; This file is part of GNU Guix.
;;;


@@ 34,6 35,8 @@
  #:use-module (srfi srfi-19)
  #:use-module (srfi srfi-26)
  #:autoload   (ice-9 ftw) (scandir)
  #:autoload   (guix base16) (bytevector->base16-string)
  #:autoload   (guix swh) (swh-download-directory)
  #:use-module (ice-9 match)
  #:use-module (ice-9 format)
  #:export (open-socket-for-uri


@@ 626,10 629,53 @@ Return a list of URIs."
    (else
     (list uri))))

(define* (disarchive-fetch/any uris file
                               #:key (timeout 10) (verify-certificate? #t))
  "Fetch a Disarchive specification from any of URIS, assemble it,
and write the output to FILE."
  (define (fetch-specification uris)
    (any (lambda (uri)
           (false-if-exception*
            (let-values (((port size) (http-fetch uri
                                                  #:verify-certificate?
                                                  verify-certificate?
                                                  #:timeout timeout)))
              (let ((specification (read port)))
                (close-port port)
                specification))))
         uris))

  (define (resolve addresses output)
    (any (match-lambda
           (('swhid swhid)
            (match (string-split swhid #\:)
              (("swh" "1" "dir" id)
               (format #t "Downloading ~a from Software Heritage...~%" file)
               (false-if-exception*
                (swh-download-directory id output)))
              (_ #f)))
           (_ #f))
         addresses))

  (format #t "Trying to use Disarchive to assemble ~a...~%" file)
  (match (and=> (resolve-module '(disarchive) #:ensure #f)
                (lambda (disarchive)
                  (cons (module-ref disarchive '%disarchive-log-port)
                        (module-ref disarchive 'disarchive-assemble))))
    (#f
     (format #t "could not load Disarchive~%"))
    ((%disarchive-log-port . disarchive-assemble)
     (match (fetch-specification uris)
       (#f
        (format #t "could not find its Disarchive specification~%"))
       (spec (parameterize ((%disarchive-log-port (current-output-port)))
               (disarchive-assemble spec file #:resolver resolve)))))))

(define* (url-fetch url file
                    #:key
                    (timeout 10) (verify-certificate? #t)
                    (mirrors '()) (content-addressed-mirrors '())
                    (disarchive-mirrors '())
                    (hashes '())
                    print-build-trace?)
  "Fetch FILE from URL; URL may be either a single string, or a list of


@@ 693,6 739,18 @@ otherwise simply ignore them."
                              hashes))
                content-addressed-mirrors))

  (define disarchive-uris
    (append-map (match-lambda
                  ((? string? mirror)
                   (map (match-lambda
                          ((hash-algo . hash)
                           (string->uri
                            (string-append mirror
                                           (symbol->string hash-algo) "/"
                                           (bytevector->base16-string hash)))))
                        hashes)))
                disarchive-mirrors))

  ;; Make this unbuffered so 'progress-report/file' works as expected.  'line
  ;; means '\n', not '\r', so it's not appropriate here.
  (setvbuf (current-output-port) 'none)


@@ 705,15 763,20 @@ otherwise simply ignore them."
       (or (fetch uri file)
           (try tail)))
      (()
       (format (current-error-port) "failed to download ~s from ~s~%"
               file url)

       ;; Remove FILE in case we made an incomplete download, for example due
       ;; to ENOSPC.
       (catch 'system-error
         (lambda ()
           (delete-file file))
         (const #f))
       #f))))
       ;; If we are looking for a software archive, one last thing we
       ;; can try is to use Disarchive to assemble it.
       (or (disarchive-fetch/any disarchive-uris file
                                 #:verify-certificate? verify-certificate?
                                 #:timeout timeout)
           (begin
             (format (current-error-port) "failed to download ~s from ~s~%"
                     file url)
             ;; Remove FILE in case we made an incomplete download, for
             ;; example due to ENOSPC.
             (catch 'system-error
               (lambda ()
                 (delete-file file))
               (const #f))
             #f))))))

;;; download.scm ends here

M guix/download.scm => guix/download.scm +16 -3
@@ 406,12 406,19 @@
  (plain-file "content-addressed-mirrors"
              (object->string %content-addressed-mirrors)))

(define %disarchive-mirrors
  '("https://disarchive.ngyro.com/"))

(define %disarchive-mirror-file
  (plain-file "disarchive-mirrors" (object->string %disarchive-mirrors)))

(define built-in-builders*
  (store-lift built-in-builders))

(define* (built-in-download file-name url
                            #:key system hash-algo hash
                            mirrors content-addressed-mirrors
                            disarchive-mirrors
                            executable?
                            (guile 'unused))
  "Download FILE-NAME from URL using the built-in 'download' builder.  When


@@ 422,13 429,16 @@ explicitly depend on Guile, GnuTLS, etc.  Instead, the daemon performs the
download by itself using its own dependencies."
  (mlet %store-monad ((mirrors (lower-object mirrors))
                      (content-addressed-mirrors
                       (lower-object content-addressed-mirrors)))
                       (lower-object content-addressed-mirrors))
                      (disarchive-mirrors (lower-object disarchive-mirrors)))
    (raw-derivation file-name "builtin:download" '()
                    #:system system
                    #:hash-algo hash-algo
                    #:hash hash
                    #:recursive? executable?
                    #:sources (list mirrors content-addressed-mirrors)
                    #:sources (list mirrors
                                    content-addressed-mirrors
                                    disarchive-mirrors)

                    ;; Honor the user's proxy and locale settings.
                    #:leaked-env-vars '("http_proxy" "https_proxy"


@@ 439,6 449,7 @@ download by itself using its own dependencies."
                                 ("mirrors" . ,mirrors)
                                 ("content-addressed-mirrors"
                                  . ,content-addressed-mirrors)
                                 ("disarchive-mirrors" . ,disarchive-mirrors)
                                 ,@(if executable?
                                       '(("executable" . "1"))
                                       '()))


@@ 492,7 503,9 @@ name in the store."
                             #:executable? executable?
                             #:mirrors %mirror-file
                             #:content-addressed-mirrors
                             %content-addressed-mirror-file)))))
                             %content-addressed-mirror-file
                             #:disarchive-mirrors
                             %disarchive-mirror-file)))))

(define* (url-fetch/executable url hash-algo hash
                               #:optional name

M guix/scripts/perform-download.scm => guix/scripts/perform-download.scm +6 -1
@@ 54,7 54,8 @@ actual output is different from that when we're doing a 'bmCheck' or
                       (output* "out")
                       (executable "executable")
                       (mirrors "mirrors")
                       (content-addressed-mirrors "content-addressed-mirrors"))
                       (content-addressed-mirrors "content-addressed-mirrors")
                       (disarchive-mirrors "disarchive-mirrors"))
    (unless url
      (leave (G_ "~a: missing URL~%") (derivation-file-name drv)))



@@ 79,6 80,10 @@ actual output is different from that when we're doing a 'bmCheck' or
                             (lambda (port)
                               (eval (read port) %user-module)))
                           '())
                       #:disarchive-mirrors
                       (if disarchive-mirrors
                           (call-with-input-file disarchive-mirrors read)
                           '())
                       #:hashes `((,algo . ,hash))

                       ;; Since DRV's output hash is known, X.509 certificate

M guix/self.scm => guix/self.scm +2 -1
@@ 878,7 878,8 @@ itself."
                   ("guix/store/schema.sql"
                    ,(local-file "../guix/store/schema.sql")))

                 #:extensions (list guile-gcrypt)
                 #:extensions (list guile-gcrypt
                                    guile-json)   ;for (guix swh)
                 #:guile-for-build guile-for-build))

  (define *extra-modules*