diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2018-12-28 18:40:06 +0100 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2018-12-28 18:40:06 +0100 |
| commit | 79b0f72a9ef21a66f3c3cd65b3609f238f9e5c23 (patch) | |
| tree | 78f134c911155aa0890d39dd28712403fc7a5de9 | |
| parent | 5fdb66f17629c0f08b5976020f185f9285f59a18 (diff) | |
DRAFT substitute: Add IPFS support.wip-ipfs-substitutes
Missing:
- documentation
- command-line options
- progress report when downloading over IPFS
- fallback when we fail to fetch from IPFS
* guix/scripts/substitute.scm (<narinfo>)[ipfs]: New field.
(read-narinfo): Read "IPFS".
(process-substitution/http): New procedure, with code formerly in
'process-substitution'.
(process-substitution): Check for IPFS and call 'ipfs:restore-file-tree'
when IPFS is true.
| -rwxr-xr-x | guix/scripts/substitute.scm | 106 |
1 files changed, 61 insertions, 45 deletions
diff --git a/guix/scripts/substitute.scm b/guix/scripts/substitute.scm index 53b17772410..8be15e4f135 100755 --- a/guix/scripts/substitute.scm +++ b/guix/scripts/substitute.scm | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #:use-module (guix progress) | 42 | #:use-module (guix progress) |
| 43 | #:use-module ((guix build syscalls) | 43 | #:use-module ((guix build syscalls) |
| 44 | #:select (set-thread-name)) | 44 | #:select (set-thread-name)) |
| 45 | #:use-module ((guix ipfs) #:prefix ipfs:) | ||
| 45 | #:use-module (ice-9 rdelim) | 46 | #:use-module (ice-9 rdelim) |
| 46 | #:use-module (ice-9 regex) | 47 | #:use-module (ice-9 regex) |
| 47 | #:use-module (ice-9 match) | 48 | #:use-module (ice-9 match) |
| @@ -281,7 +282,7 @@ failure, return #f and #f." | |||
| 281 | 282 | ||
| 282 | (define-record-type <narinfo> | 283 | (define-record-type <narinfo> |
| 283 | (%make-narinfo path uri uri-base compression file-hash file-size nar-hash nar-size | 284 | (%make-narinfo path uri uri-base compression file-hash file-size nar-hash nar-size |
| 284 | references deriver system signature contents) | 285 | references deriver system ipfs signature contents) |
| 285 | narinfo? | 286 | narinfo? |
| 286 | (path narinfo-path) | 287 | (path narinfo-path) |
| 287 | (uri narinfo-uri) | 288 | (uri narinfo-uri) |
| @@ -294,6 +295,7 @@ failure, return #f and #f." | |||
| 294 | (references narinfo-references) | 295 | (references narinfo-references) |
| 295 | (deriver narinfo-deriver) | 296 | (deriver narinfo-deriver) |
| 296 | (system narinfo-system) | 297 | (system narinfo-system) |
| 298 | (ipfs narinfo-ipfs) | ||
| 297 | (signature narinfo-signature) ; canonical sexp | 299 | (signature narinfo-signature) ; canonical sexp |
| 298 | ;; The original contents of a narinfo file. This field is needed because we | 300 | ;; The original contents of a narinfo file. This field is needed because we |
| 299 | ;; want to preserve the exact textual representation for verification purposes. | 301 | ;; want to preserve the exact textual representation for verification purposes. |
| @@ -335,7 +337,7 @@ s-expression: ~s~%") | |||
| 335 | "Return a narinfo constructor for narinfos originating from CACHE-URL. STR | 337 | "Return a narinfo constructor for narinfos originating from CACHE-URL. STR |
| 336 | must contain the original contents of a narinfo file." | 338 | must contain the original contents of a narinfo file." |
| 337 | (lambda (path url compression file-hash file-size nar-hash nar-size | 339 | (lambda (path url compression file-hash file-size nar-hash nar-size |
| 338 | references deriver system signature) | 340 | references deriver system ipfs signature) |
| 339 | "Return a new <narinfo> object." | 341 | "Return a new <narinfo> object." |
| 340 | (%make-narinfo path | 342 | (%make-narinfo path |
| 341 | ;; Handle the case where URL is a relative URL. | 343 | ;; Handle the case where URL is a relative URL. |
| @@ -352,6 +354,7 @@ must contain the original contents of a narinfo file." | |||
| 352 | ((or #f "") #f) | 354 | ((or #f "") #f) |
| 353 | (_ deriver)) | 355 | (_ deriver)) |
| 354 | system | 356 | system |
| 357 | ipfs | ||
| 355 | (false-if-exception | 358 | (false-if-exception |
| 356 | (and=> signature narinfo-signature->canonical-sexp)) | 359 | (and=> signature narinfo-signature->canonical-sexp)) |
| 357 | str))) | 360 | str))) |
| @@ -386,7 +389,7 @@ No authentication and authorization checks are performed here!" | |||
| 386 | (narinfo-maker str url) | 389 | (narinfo-maker str url) |
| 387 | '("StorePath" "URL" "Compression" | 390 | '("StorePath" "URL" "Compression" |
| 388 | "FileHash" "FileSize" "NarHash" "NarSize" | 391 | "FileHash" "FileSize" "NarHash" "NarSize" |
| 389 | "References" "Deriver" "System" | 392 | "References" "Deriver" "System" "IPFS" |
| 390 | "Signature")))) | 393 | "Signature")))) |
| 391 | 394 | ||
| 392 | (define (narinfo-sha256 narinfo) | 395 | (define (narinfo-sha256 narinfo) |
| @@ -947,13 +950,58 @@ authorized substitutes." | |||
| 947 | (wtf | 950 | (wtf |
| 948 | (error "unknown `--query' command" wtf)))) | 951 | (error "unknown `--query' command" wtf)))) |
| 949 | 952 | ||
| 953 | (define* (process-substitution/http narinfo destination uri | ||
| 954 | #:key print-build-trace?) | ||
| 955 | (unless print-build-trace? | ||
| 956 | (format (current-error-port) | ||
| 957 | (G_ "Downloading ~a...~%") (uri->string uri))) | ||
| 958 | |||
| 959 | (let*-values (((raw download-size) | ||
| 960 | ;; Note that Hydra currently generates Nars on the fly | ||
| 961 | ;; and doesn't specify a Content-Length, so | ||
| 962 | ;; DOWNLOAD-SIZE is #f in practice. | ||
| 963 | (fetch uri #:buffered? #f #:timeout? #f)) | ||
| 964 | ((progress) | ||
| 965 | (let* ((comp (narinfo-compression narinfo)) | ||
| 966 | (dl-size (or download-size | ||
| 967 | (and (equal? comp "none") | ||
| 968 | (narinfo-size narinfo)))) | ||
| 969 | (reporter (if print-build-trace? | ||
| 970 | (progress-reporter/trace | ||
| 971 | destination | ||
| 972 | (uri->string uri) dl-size | ||
| 973 | (current-error-port)) | ||
| 974 | (progress-reporter/file | ||
| 975 | (uri->string uri) dl-size | ||
| 976 | (current-error-port) | ||
| 977 | #:abbreviation nar-uri-abbreviation)))) | ||
| 978 | (progress-report-port reporter raw))) | ||
| 979 | ((input pids) | ||
| 980 | ;; NOTE: This 'progress' port of current process will be | ||
| 981 | ;; closed here, while the child process doing the | ||
| 982 | ;; reporting will close it upon exit. | ||
| 983 | (decompressed-port (and=> (narinfo-compression narinfo) | ||
| 984 | string->symbol) | ||
| 985 | progress))) | ||
| 986 | ;; Unpack the Nar at INPUT into DESTINATION. | ||
| 987 | (restore-file input destination) | ||
| 988 | (close-port input) | ||
| 989 | |||
| 990 | ;; Wait for the reporter to finish. | ||
| 991 | (every (compose zero? cdr waitpid) pids) | ||
| 992 | |||
| 993 | ;; Skip a line after what 'progress-reporter/file' printed, and another | ||
| 994 | ;; one to visually separate substitutions. | ||
| 995 | (display "\n\n" (current-error-port)))) | ||
| 996 | |||
| 950 | (define* (process-substitution store-item destination | 997 | (define* (process-substitution store-item destination |
| 951 | #:key cache-urls acl print-build-trace?) | 998 | #:key cache-urls acl print-build-trace?) |
| 952 | "Substitute STORE-ITEM (a store file name) from CACHE-URLS, and write it to | 999 | "Substitute STORE-ITEM (a store file name) from CACHE-URLS, and write it to |
| 953 | DESTINATION as a nar file. Verify the substitute against ACL." | 1000 | DESTINATION as a nar file. Verify the substitute against ACL." |
| 954 | (let* ((narinfo (lookup-narinfo cache-urls store-item | 1001 | (let* ((narinfo (lookup-narinfo cache-urls store-item |
| 955 | (cut valid-narinfo? <> acl))) | 1002 | (cut valid-narinfo? <> acl))) |
| 956 | (uri (and=> narinfo narinfo-uri))) | 1003 | (uri (and=> narinfo narinfo-uri)) |
| 1004 | (ipfs (and=> narinfo narinfo-ipfs))) | ||
| 957 | (unless uri | 1005 | (unless uri |
| 958 | (leave (G_ "no valid substitute for '~a'~%") | 1006 | (leave (G_ "no valid substitute for '~a'~%") |
| 959 | store-item)) | 1007 | store-item)) |
| @@ -961,47 +1009,15 @@ DESTINATION as a nar file. Verify the substitute against ACL." | |||
| 961 | ;; Tell the daemon what the expected hash of the Nar itself is. | 1009 | ;; Tell the daemon what the expected hash of the Nar itself is. |
| 962 | (format #t "~a~%" (narinfo-hash narinfo)) | 1010 | (format #t "~a~%" (narinfo-hash narinfo)) |
| 963 | 1011 | ||
| 964 | (unless print-build-trace? | 1012 | (if ipfs |
| 965 | (format (current-error-port) | 1013 | (begin |
| 966 | (G_ "Downloading ~a...~%") (uri->string uri))) | 1014 | (unless print-build-trace? |
| 967 | 1015 | (format (current-error-port) | |
| 968 | (let*-values (((raw download-size) | 1016 | (G_ "Downloading from IPFS ~s...~%") ipfs)) |
| 969 | ;; Note that Hydra currently generates Nars on the fly | 1017 | (ipfs:restore-file-tree ipfs destination)) |
| 970 | ;; and doesn't specify a Content-Length, so | 1018 | (process-substitution/http narinfo destination uri |
| 971 | ;; DOWNLOAD-SIZE is #f in practice. | 1019 | #:print-build-trace? |
| 972 | (fetch uri #:buffered? #f #:timeout? #f)) | 1020 | print-build-trace?)))) |
| 973 | ((progress) | ||
| 974 | (let* ((comp (narinfo-compression narinfo)) | ||
| 975 | (dl-size (or download-size | ||
| 976 | (and (equal? comp "none") | ||
| 977 | (narinfo-size narinfo)))) | ||
| 978 | (reporter (if print-build-trace? | ||
| 979 | (progress-reporter/trace | ||
| 980 | destination | ||
| 981 | (uri->string uri) dl-size | ||
| 982 | (current-error-port)) | ||
| 983 | (progress-reporter/file | ||
| 984 | (uri->string uri) dl-size | ||
| 985 | (current-error-port) | ||
| 986 | #:abbreviation nar-uri-abbreviation)))) | ||
| 987 | (progress-report-port reporter raw))) | ||
| 988 | ((input pids) | ||
| 989 | ;; NOTE: This 'progress' port of current process will be | ||
| 990 | ;; closed here, while the child process doing the | ||
| 991 | ;; reporting will close it upon exit. | ||
| 992 | (decompressed-port (and=> (narinfo-compression narinfo) | ||
| 993 | string->symbol) | ||
| 994 | progress))) | ||
| 995 | ;; Unpack the Nar at INPUT into DESTINATION. | ||
| 996 | (restore-file input destination) | ||
| 997 | (close-port input) | ||
| 998 | |||
| 999 | ;; Wait for the reporter to finish. | ||
| 1000 | (every (compose zero? cdr waitpid) pids) | ||
| 1001 | |||
| 1002 | ;; Skip a line after what 'progress-reporter/file' printed, and another | ||
| 1003 | ;; one to visually separate substitutions. | ||
| 1004 | (display "\n\n" (current-error-port))))) | ||
| 1005 | 1021 | ||
| 1006 | 1022 | ||
| 1007 | ;;; | 1023 | ;;; |
