me
/
guix
Archived
1
0
Fork 0

lint: archival: Lookup content in Disarchive database.

* guix/lint.scm (lookup-disarchive-spec): New procedure.
(check-archival): When 'lookup-content' returns #f, call
'lookup-disarchive-spec'.  Call 'lookup-directory' on the result of
'lookup-directory'.
* guix/download.scm (%disarchive-mirrors): Make public.
* tests/lint.scm ("archival: missing content"): Set
'%disarchive-mirrors'.
("archival: content unavailable but disarchive available"): New test.
master
Ludovic Courtès 2021-05-15 12:19:03 +02:00
parent dac6c21623
commit bc4d81d267
No known key found for this signature in database
GPG Key ID: 090B11993D9AEBB5
3 changed files with 89 additions and 8 deletions

View File

@ -35,6 +35,7 @@
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (srfi srfi-26) #:use-module (srfi srfi-26)
#:export (%mirrors #:export (%mirrors
%disarchive-mirrors
(url-fetch* . url-fetch) (url-fetch* . url-fetch)
url-fetch/executable url-fetch/executable
url-fetch/tarbomb url-fetch/tarbomb

View File

@ -30,6 +30,7 @@
(define-module (guix lint) (define-module (guix lint)
#:use-module (guix store) #:use-module (guix store)
#:autoload (guix base16) (bytevector->base16-string)
#:use-module (guix base32) #:use-module (guix base32)
#:use-module (guix diagnostics) #:use-module (guix diagnostics)
#:use-module (guix download) #:use-module (guix download)
@ -1227,6 +1228,43 @@ upstream releases")
#:field 'source))))))) #:field 'source)))))))
(define (lookup-disarchive-spec hash)
"If Disarchive mirrors have a spec for HASH, return the list of SWH
directory identifiers the spec refers to. Otherwise return #f."
(define (extract-swh-id spec)
;; Return the list of SWH directory identifiers SPEC refers to, where SPEC
;; is a Disarchive sexp. Instead of attempting to parse it, traverse it
;; in a pretty unintelligent fashion.
(let loop ((sexp spec)
(ids '()))
(match sexp
((? string? str)
(let ((prefix "swh:1:dir:"))
(if (string-prefix? prefix str)
(cons (string-drop str (string-length prefix)) ids)
ids)))
((head tail ...)
(loop tail (loop head ids)))
(_ ids))))
(any (lambda (mirror)
(with-networking-fail-safe
(format #f (G_ "failed to access Disarchive database at ~a")
mirror)
#f
(guard (c ((http-get-error? c) #f))
(let* ((url (string-append mirror
(symbol->string
(content-hash-algorithm hash))
"/"
(bytevector->base16-string
(content-hash-value hash))))
(port (http-fetch (string->uri url) #:text? #t))
(spec (read port)))
(close-port port)
(extract-swh-id spec)))))
%disarchive-mirrors))
(define (check-archival package) (define (check-archival package)
"Check whether PACKAGE's source code is archived on Software Heritage. If "Check whether PACKAGE's source code is archived on Software Heritage. If
it's not, and if its source code is a VCS snapshot, then send a \"save\" it's not, and if its source code is a VCS snapshot, then send a \"save\"
@ -1302,10 +1340,26 @@ try again later")
(symbol->string (symbol->string
(content-hash-algorithm hash))) (content-hash-algorithm hash)))
(#f (#f
(list (make-warning package ;; If SWH doesn't have HASH as is, it may be because it's
(G_ "source not archived on Software \ ;; a hand-crafted tarball. In that case, check whether
Heritage") ;; the Disarchive database has an entry for that tarball.
#:field 'source))) (match (lookup-disarchive-spec hash)
(#f
(list (make-warning package
(G_ "source not archived on Software \
Heritage and missing from the Disarchive database")
#:field 'source)))
(directory-ids
(match (find (lambda (id)
(not (lookup-directory id)))
directory-ids)
(#f '())
(id
(list (make-warning package
(G_ "
Disarchive entry refers to non-existent SWH directory '~a'")
(list id)
#:field 'source)))))))
((? content?) ((? content?)
'()))) '())))
'())))) '()))))

View File

@ -1,7 +1,7 @@
;;; GNU Guix --- Functional package management for GNU ;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2012, 2013 Cyril Roelandt <tipecaml@gmail.com> ;;; Copyright © 2012, 2013 Cyril Roelandt <tipecaml@gmail.com>
;;; Copyright © 2014, 2015, 2016 Eric Bavier <bavier@member.fsf.org> ;;; Copyright © 2014, 2015, 2016 Eric Bavier <bavier@member.fsf.org>
;;; Copyright © 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2015, 2016 Mathieu Lirzin <mthl@gnu.org> ;;; Copyright © 2015, 2016 Mathieu Lirzin <mthl@gnu.org>
;;; Copyright © 2016 Hartmut Goebel <h.goebel@crazy-compilers.com> ;;; Copyright © 2016 Hartmut Goebel <h.goebel@crazy-compilers.com>
;;; Copyright © 2017 Alex Kost <alezost@gmail.com> ;;; Copyright © 2017 Alex Kost <alezost@gmail.com>
@ -1008,10 +1008,13 @@
(method url-fetch) (method url-fetch)
(uri "http://example.org/foo.tgz") (uri "http://example.org/foo.tgz")
(sha256 (make-bytevector 32)))) (sha256 (make-bytevector 32))))
(warnings (with-http-server '((404 "Not archived.")) (warnings (with-http-server '((404 "Not archived.")
(404 "Not in Disarchive database."))
(parameterize ((%swh-base-url (%local-url))) (parameterize ((%swh-base-url (%local-url)))
(check-archival (dummy-package "x" (mock ((guix download) %disarchive-mirrors
(source origin))))))) (list (%local-url)))
(check-archival (dummy-package "x"
(source origin))))))))
(warning-contains? "not archived" warnings))) (warning-contains? "not archived" warnings)))
(test-equal "archival: content available" (test-equal "archival: content available"
@ -1027,6 +1030,29 @@
(parameterize ((%swh-base-url (%local-url))) (parameterize ((%swh-base-url (%local-url)))
(check-archival (dummy-package "x" (source origin))))))) (check-archival (dummy-package "x" (source origin)))))))
(test-equal "archival: content unavailable but disarchive available"
'()
(let* ((origin (origin
(method url-fetch)
(uri "http://example.org/foo.tgz")
(sha256 (make-bytevector 32))))
(disarchive (object->string
'(disarchive (version 0)
...
"swh:1:dir:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")))
;; https://archive.softwareheritage.org/api/1/directory/
(directory "[ { \"checksums\": {},
\"dir_id\": \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",
\"type\": \"file\",
\"name\": \"README\"
\"length\": 42 } ]"))
(with-http-server `((404 "") ;lookup-content
(200 ,disarchive) ;Disarchive database lookup
(200 ,directory)) ;lookup-directory
(mock ((guix download) %disarchive-mirrors (list (%local-url)))
(parameterize ((%swh-base-url (%local-url)))
(check-archival (dummy-package "x" (source origin))))))))
(test-assert "archival: missing revision" (test-assert "archival: missing revision"
(let* ((origin (origin (let* ((origin (origin
(method git-fetch) (method git-fetch)