From 45adbd624f920d315259b102b923728d655a1efa Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Mon, 3 Feb 2014 23:12:54 +0100 Subject: monads: Add 'text-file*'. * guix/monads.scm (text-file*): New procedure. * tests/monads.scm ("text-file*"): New test. * doc/guix.texi (The Store Monad): Change example since the previous one would erroneously fail to retain a reference to Coreutils. Document 'text-file*'. --- tests/monads.scm | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/monads.scm b/tests/monads.scm index d3f78e1568..b51e705f01 100644 --- a/tests/monads.scm +++ b/tests/monads.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2013 Ludovic Courtès +;;; Copyright © 2013, 2014 Ludovic Courtès ;;; ;;; This file is part of GNU Guix. ;;; @@ -126,6 +126,30 @@ (readlink (string-append out "/guile-rocks")))))) #:guile-for-build (package-derivation %store %bootstrap-guile))) +(test-assert "text-file*" + (let ((references (store-lift references))) + (run-with-store %store + (mlet* %store-monad + ((drv (package->derivation %bootstrap-guile)) + (guile -> (derivation->output-path drv)) + (file (text-file "bar" "This is bar.")) + (text (text-file* "foo" + %bootstrap-guile "/bin/guile " + `(,%bootstrap-guile "out") "/bin/guile " + drv "/bin/guile " + file)) + (done (built-derivations (list text))) + (out -> (derivation->output-path text)) + (refs (references out))) + ;; Make sure we get the right references and the right content. + (return (and (lset= string=? refs (list guile file)) + (equal? (call-with-input-file out get-string-all) + (string-append guile "/bin/guile " + guile "/bin/guile " + guile "/bin/guile " + file))))) + #:guile-for-build (package-derivation %store %bootstrap-guile)))) + (test-assert "mapm" (every (lambda (monad run) (with-monad monad -- cgit v1.2.3 From 99fbddf9a623757e39d88bfb431f8f7d6f24b75b Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Mon, 10 Feb 2014 23:30:09 +0100 Subject: store: Change 'export-paths' to always export in topological order. * guix/store.scm (export-paths): Pass PATHS through 'topologically-sorted' before iterating. * tests/store.scm ("export/import paths, ensure topological order"): New test. --- guix/store.scm | 6 +++--- tests/store.scm | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/guix/store.scm b/guix/store.scm index eca0de7d97..b9b9d9e55a 100644 --- a/guix/store.scm +++ b/guix/store.scm @@ -732,10 +732,10 @@ is raised if the set of paths read from PORT is not signed (as per (= 1 (read-int s)))) (define* (export-paths server paths port #:key (sign? #t)) - "Export the store paths listed in PATHS to PORT, signing them if SIGN? -is true." + "Export the store paths listed in PATHS to PORT, in topological order, +signing them if SIGN? is true." (let ((s (nix-server-socket server))) - (let loop ((paths paths)) + (let loop ((paths (topologically-sorted server paths))) (match paths (() (write-int 0 port)) diff --git a/tests/store.scm b/tests/store.scm index a61d449fb4..7b0f3249d2 100644 --- a/tests/store.scm +++ b/tests/store.scm @@ -398,6 +398,25 @@ Deriver: ~a~%" get-string-all)) files))))))) +(test-assert "export/import paths, ensure topological order" + (let* ((file1 (add-text-to-store %store "foo" (random-text))) + (file2 (add-text-to-store %store "bar" (random-text) + (list file1))) + (files (list file1 file2)) + (dump1 (call-with-bytevector-output-port + (cute export-paths %store (list file1 file2) <>))) + (dump2 (call-with-bytevector-output-port + (cute export-paths %store (list file2 file1) <>)))) + (delete-paths %store files) + (and (every (negate file-exists?) files) + (bytevector=? dump1 dump2) + (let* ((source (open-bytevector-input-port dump1)) + (imported (import-paths %store source))) + (and (equal? imported (list file1 file2)) + (every file-exists? files) + (null? (references %store file1)) + (equal? (list file1) (references %store file2))))))) + (test-assert "import corrupt path" (let* ((text (random-text)) (file (add-text-to-store %store "text" text)) -- cgit v1.2.3 From a93e91ff484005e05491621664ab71f888ad2ba2 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 21 Feb 2014 17:37:55 +0100 Subject: nar: 'write-file' can write to non-file ports. * guix/nar.scm (write-contents): Use 'sendfile' only when P is a file port. * tests/nar.scm ("write-file supports non-file output ports"): New test. --- guix/nar.scm | 3 ++- tests/nar.scm | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/guix/nar.scm b/guix/nar.scm index 4bc2deb229..89a71302e0 100644 --- a/guix/nar.scm +++ b/guix/nar.scm @@ -112,7 +112,8 @@ (write-long-long size p) (call-with-binary-input-file file ;; Use `sendfile' when available (Guile 2.0.8+). - (if (compile-time-value (defined? 'sendfile)) + (if (and (compile-time-value (defined? 'sendfile)) + (file-port? p)) (cut sendfile p <> size 0) (cut dump <> p size))) (write-padding size p)) diff --git a/tests/nar.scm b/tests/nar.scm index 9f21f990c8..7ae8cf0aa7 100644 --- a/tests/nar.scm +++ b/tests/nar.scm @@ -183,6 +183,13 @@ (test-begin "nar") +(test-assert "write-file supports non-file output ports" + (let ((input (string-append (dirname (search-path %load-path "guix.scm")) + "/guix")) + (output (%make-void-port "w"))) + (write-file input output) + #t)) + (test-assert "write-file + restore-file" (let* ((input (string-append (dirname (search-path %load-path "guix.scm")) "/guix")) -- cgit v1.2.3 From 3140f2df423d1235c3766e3478a429ac89d882ed Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 21 Feb 2014 17:54:32 +0100 Subject: guix hash: Add '--recursive'. * guix/scripts/hash.scm (show-help): Add --recursive. (%options): Likewise. (guix-hash)[file-hash]: New procedure. Honor --recursive. Use it. * guix/nar.scm (write-file): Add missing field to the &nar-error condition raised upon unsupported file type; change its message to be more descriptive. * tests/guix-hash.sh: Add tests with -r. * doc/guix.texi (Invoking guix hash): Document --recursive. --- doc/guix.texi | 13 +++++++++++++ guix/nar.scm | 4 ++-- guix/scripts/hash.scm | 25 +++++++++++++++++++++---- tests/guix-hash.sh | 22 +++++++++++++++++++++- 4 files changed, 57 insertions(+), 7 deletions(-) (limited to 'tests') diff --git a/doc/guix.texi b/doc/guix.texi index 34f6810f34..ce011959ad 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -1958,6 +1958,19 @@ If the @option{--format} option is not specified, @command{guix hash} will output the hash in @code{nix-base32}. This representation is used in the definitions of packages. +@item --recursive +@itemx -r +Compute the hash on @var{file} recursively. + +In this case, the hash is computed on an archive containing @var{file}, +including its children if it is a directory. Some of @var{file}'s +meta-data is part of the archive; for instance, when @var{file} is a +regular file, the hash is different depending on whether @var{file} is +executable or not. Meta-data such as time stamps has no impact on the +hash (@pxref{Invoking guix archive}). +@c FIXME: Replace xref above with xref to an ``Archive'' section when +@c it exists. + @end table @node Invoking guix refresh diff --git a/guix/nar.scm b/guix/nar.scm index 89a71302e0..9ba6e4ce2c 100644 --- a/guix/nar.scm +++ b/guix/nar.scm @@ -195,8 +195,8 @@ sub-directories of FILE as needed." (write-string "target" p) (write-string (readlink f) p)) (else - (raise (condition (&message (message "ENOSYS")) - (&nar-error))))) + (raise (condition (&message (message "unsupported file type")) + (&nar-error (file f) (port port)))))) (write-string ")" p)))) (define (restore-file port file) diff --git a/guix/scripts/hash.scm b/guix/scripts/hash.scm index 4e66aa0f3e..ea8c2ada6b 100644 --- a/guix/scripts/hash.scm +++ b/guix/scripts/hash.scm @@ -20,12 +20,14 @@ (define-module (guix scripts hash) #:use-module (guix base32) #:use-module (guix hash) + #:use-module (guix nar) #:use-module (guix ui) #:use-module (guix utils) #:use-module (rnrs io ports) #:use-module (rnrs files) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-11) #:use-module (srfi srfi-26) #:use-module (srfi srfi-37) #:export (guix-hash)) @@ -43,10 +45,12 @@ (display (_ "Usage: guix hash [OPTION] FILE Return the cryptographic hash of FILE. -Supported formats: 'nix-base32' (default), 'base32', and 'base16' -('hex' and 'hexadecimal' can be used as well).\n")) +Supported formats: 'nix-base32' (default), 'base32', and 'base16' ('hex' +and 'hexadecimal' can be used as well).\n")) (format #t (_ " -f, --format=FMT write the hash in the given format")) + (format #t (_ " + -r, --recursive compute the hash on FILE recursively")) (newline) (display (_ " -h, --help display this help and exit")) @@ -73,6 +77,9 @@ Supported formats: 'nix-base32' (default), 'base32', and 'base16' (alist-cons 'format fmt-proc (alist-delete 'format result)))) + (option '(#\r "recursive") #f #f + (lambda (opt name arg result) + (alist-cons 'recursive? #t result))) (option '(#\h "help") #f #f (lambda args @@ -107,12 +114,22 @@ Supported formats: 'nix-base32' (default), 'base32', and 'base16' (reverse opts))) (fmt (assq-ref opts 'format))) + (define (file-hash file) + ;; Compute the hash of FILE. + ;; Catch and gracefully report possible '&nar-error' conditions. + (with-error-handling + (if (assoc-ref opts 'recursive?) + (let-values (((port get-hash) (open-sha256-port))) + (write-file file port) + (flush-output-port port) + (get-hash)) + (call-with-input-file file port-sha256)))) + (match args ((file) (catch 'system-error (lambda () - (format #t "~a~%" - (fmt (call-with-input-file file port-sha256)))) + (format #t "~a~%" (fmt (file-hash file)))) (lambda args (leave (_ "~a~%") (strerror (system-error-errno args)))))) diff --git a/tests/guix-hash.sh b/tests/guix-hash.sh index 53325ce1f4..23df01d417 100644 --- a/tests/guix-hash.sh +++ b/tests/guix-hash.sh @@ -1,5 +1,5 @@ # GNU Guix --- Functional package management for GNU -# Copyright © 2013 Ludovic Courtès +# Copyright © 2013, 2014 Ludovic Courtès # # This file is part of GNU Guix. # @@ -22,7 +22,27 @@ guix hash --version +tmpdir="guix-hash-$$" +trap 'rm -rf "$tmpdir"' EXIT + test `guix hash /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73 test `guix hash -f nix-base32 /dev/null` = 0mdqa9w1p6cmli6976v4wi0sw9r4p5prkj7lzfd1877wk11c9c73 test `guix hash -f hex /dev/null` = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 test `guix hash -f base32 /dev/null` = 4oymiquy7qobjgx36tejs35zeqt24qpemsnzgtfeswmrw6csxbkq + +mkdir "$tmpdir" +echo -n executable > "$tmpdir/exe" +chmod +x "$tmpdir/exe" +( cd "$tmpdir" ; ln -s exe symlink ) +mkdir "$tmpdir/subdir" + +test `guix hash -r "$tmpdir"` = 10k1lw41wyrjf9mxydi0is5nkpynlsvgslinics4ppir13g7d74p + +# Without '-r', this should fail. +if guix hash "$tmpdir" +then false; else true; fi + +# This should fail because /dev/null is a character device, which +# the archive format doesn't support. +if guix hash -r /dev/null +then false; else true; fi -- cgit v1.2.3 From 36bbbbd150f75c2a6dab2473643c3723e606e41d Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 21 Feb 2014 23:03:19 +0100 Subject: derivations: Add support for recursive fixed-output derivations. * guix/derivations.scm (): Add 'recursive?' field. Adjust 'make-derivation-output' callers. (%read-derivation) : When HASH-ALGO starts with 'r:', set the 'recursive?' field and drop 'r:' from the hash algo name. (write-derivation)[write-output]: Write the algo as 'r:HASH-ALGO' when the RECURSIVE? field is set. (derivation-hash) : Prepend "r:" when RECURSIVE? is set. (fixed-output-path): New procedure. (derivation): Add #:recursive? parameter. Use 'fixed-output-path' to compute the output file name of a fixed output derivation. (build-expression->derivation): Add #:recursive? parameter. Pass it to 'derivation'. * tests/derivations.scm ("fixed-output derivation, recursive", "build-expression->derivation produces recursive fixed-output", "build-expression->derivation uses recursive fixed-output"): New tests. * doc/guix.texi (Derivations): Document #:recursive? for 'derivation'. Add #:recursive? for 'build-expression->derivation'. --- doc/guix.texi | 9 ++++--- guix/derivations.scm | 71 ++++++++++++++++++++++++++++++++++++++------------- tests/derivations.scm | 70 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 127 insertions(+), 23 deletions(-) (limited to 'tests') diff --git a/doc/guix.texi b/doc/guix.texi index ce011959ad..b2733fbec9 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -1478,7 +1478,7 @@ a derivation is the @code{derivation} procedure: @deffn {Scheme Procedure} derivation @var{store} @var{name} @var{builder} @ @var{args} [#:outputs '("out")] [#:hash #f] [#:hash-algo #f] @ - [#:hash-mode #f] [#:inputs '()] [#:env-vars '()] @ + [#:recursive? #f] [#:hash-mode #f] [#:inputs '()] [#:env-vars '()] @ [#:system (%current-system)] [#:references-graphs #f] @ [#:local-build? #f] Build a derivation with the given arguments, and return the resulting @@ -1486,7 +1486,10 @@ Build a derivation with the given arguments, and return the resulting When @var{hash}, @var{hash-algo}, and @var{hash-mode} are given, a @dfn{fixed-output derivation} is created---i.e., one whose result is -known in advance, such as a file download. +known in advance, such as a file download. If, in addition, +@var{recursive?} is true, then that fixed output may be an executable +file or a directory and @var{hash} must be the hash of an archive +containing this output. When @var{references-graphs} is true, it must be a list of file name/store path pairs. In that case, the reference graph of each store @@ -1526,7 +1529,7 @@ the caller to directly pass a Guile expression as the build script: @var{name} @var{exp} @ [#:system (%current-system)] [#:inputs '()] @ [#:outputs '("out")] [#:hash #f] [#:hash-algo #f] @ - [#:env-vars '()] [#:modules '()] @ + [#:recursive? #f] [#:env-vars '()] [#:modules '()] @ [#:references-graphs #f] [#:local-build? #f] [#:guile-for-build #f] Return a derivation that executes Scheme expression @var{exp} as a builder for derivation @var{name}. @var{inputs} must be a list of diff --git a/guix/derivations.scm b/guix/derivations.scm index cc8e37c973..4f060a6aa2 100644 --- a/guix/derivations.scm +++ b/guix/derivations.scm @@ -47,6 +47,7 @@ derivation-output-path derivation-output-hash-algo derivation-output-hash + derivation-output-recursive? derivation-input? @@ -91,11 +92,12 @@ (file-name derivation-file-name)) ; the .drv file name (define-record-type - (make-derivation-output path hash-algo hash) + (make-derivation-output path hash-algo hash recursive?) derivation-output? (path derivation-output-path) ; store path (hash-algo derivation-output-hash-algo) ; symbol | #f - (hash derivation-output-hash)) ; bytevector | #f + (hash derivation-output-hash) ; bytevector | #f + (recursive? derivation-output-recursive?)) ; Boolean (define-record-type (make-derivation-input path sub-derivations) @@ -241,14 +243,19 @@ that second value is the empty list." (match output ((name path "" "") (alist-cons name - (make-derivation-output path #f #f) + (make-derivation-output path #f #f #f) result)) ((name path hash-algo hash) ;; fixed-output - (let ((algo (string->symbol hash-algo)) - (hash (base16-string->bytevector hash))) + (let* ((rec? (string-prefix? "r:" hash-algo)) + (algo (string->symbol + (if rec? + (string-drop hash-algo 2) + hash-algo))) + (hash (base16-string->bytevector hash))) (alist-cons name - (make-derivation-output path algo hash) + (make-derivation-output path algo + hash rec?) result))))) '() x)) @@ -368,9 +375,12 @@ that form." (define (write-output output port) (match output - ((name . ($ path hash-algo hash)) + ((name . ($ path hash-algo hash recursive?)) (write-tuple (list name path - (or (and=> hash-algo symbol->string) "") + (if hash-algo + (string-append (if recursive? "r:" "") + (symbol->string hash-algo)) + "") (or (and=> hash bytevector->base16-string) "")) write @@ -476,11 +486,14 @@ in SIZE bytes." "Return the hash of DRV, modulo its fixed-output inputs, as a bytevector." (match drv (($ ((_ . ($ path - (? symbol? hash-algo) (? bytevector? hash))))) + (? symbol? hash-algo) (? bytevector? hash) + (? boolean? recursive?))))) ;; A fixed-output derivation. (sha256 (string->utf8 - (string-append "fixed:out:" (symbol->string hash-algo) + (string-append "fixed:out:" + (if recursive? "r:" "") + (symbol->string hash-algo) ":" (bytevector->base16-string hash) ":" path)))) (($ outputs inputs sources @@ -527,17 +540,33 @@ the derivation called NAME with hash HASH." name (string-append name "-" output)))) +(define (fixed-output-path output hash-algo hash recursive? name) + "Return an output path for the fixed output OUTPUT defined by HASH of type +HASH-ALGO, of the derivation NAME. RECURSIVE? has the same meaning as for +'add-to-store'." + (if (and recursive? (eq? hash-algo 'sha256)) + (store-path "source" hash name) + (let ((tag (string-append "fixed:" output ":" + (if recursive? "r:" "") + (symbol->string hash-algo) ":" + (bytevector->base16-string hash) ":"))) + (store-path (string-append "output:" output) + (sha256 (string->utf8 tag)) + name)))) + (define* (derivation store name builder args #:key (system (%current-system)) (env-vars '()) (inputs '()) (outputs '("out")) - hash hash-algo hash-mode + hash hash-algo hash-mode recursive? references-graphs local-build?) "Build a derivation with the given arguments, and return the resulting object. When HASH, HASH-ALGO, and HASH-MODE are given, a fixed-output derivation is created---i.e., one whose result is known in -advance, such as a file download. +advance, such as a file download. If, in addition, RECURSIVE? is true, then +that fixed output may be an executable file or a directory and HASH must be +the hash of an archive containing this output. When REFERENCES-GRAPHS is true, it must be a list of file name/store path pairs. In that case, the reference graph of each store path is exported in @@ -555,12 +584,16 @@ derivations where the costs of data transfers would outweigh the benefits." (let* ((drv-hash (derivation-hash drv)) (outputs (map (match-lambda ((output-name . ($ - _ algo hash)) - (let ((path (output-path output-name - drv-hash name))) + _ algo hash rec?)) + (let ((path (if hash + (fixed-output-path output-name + algo hash + rec? name) + (output-path output-name + drv-hash name)))) (cons output-name (make-derivation-output path algo - hash))))) + hash rec?))))) outputs))) (make-derivation outputs inputs sources system builder args (map (match-lambda @@ -618,7 +651,8 @@ derivations where the costs of data transfers would outweigh the benefits." (let* ((outputs (map (lambda (name) ;; Return outputs with an empty path. (cons name - (make-derivation-output "" hash-algo hash))) + (make-derivation-output "" hash-algo + hash recursive?))) outputs)) (inputs (map (match-lambda (((? derivation? drv)) @@ -909,7 +943,7 @@ they can refer to each other." (system (%current-system)) (inputs '()) (outputs '("out")) - hash hash-algo + hash hash-algo recursive? (env-vars '()) (modules '()) guile-for-build @@ -1056,6 +1090,7 @@ LOCAL-BUILD?." env-vars) #:hash hash #:hash-algo hash-algo + #:recursive? recursive? #:outputs outputs #:references-graphs references-graphs #:local-build? local-build?))) diff --git a/tests/derivations.scm b/tests/derivations.scm index f7cedde505..f31b00b8a2 100644 --- a/tests/derivations.scm +++ b/tests/derivations.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013 Ludovic Courtès +;;; Copyright © 2012, 2013, 2014 Ludovic Courtès ;;; ;;; This file is part of GNU Guix. ;;; @@ -23,7 +23,8 @@ #:use-module (guix utils) #:use-module (guix hash) #:use-module (guix base32) - #:use-module ((guix packages) #:select (package-derivation)) + #:use-module ((guix packages) #:select (package-derivation base32)) + #:use-module ((guix build utils) #:select (executable-file?)) #:use-module ((gnu packages) #:select (search-bootstrap-binary)) #:use-module (gnu packages bootstrap) #:use-module ((gnu packages guile) #:select (guile-1.8)) @@ -190,6 +191,23 @@ (equal? (derivation->output-path drv1) (derivation->output-path drv2))))) +(test-assert "fixed-output derivation, recursive" + (let* ((builder (add-text-to-store %store "my-fixed-builder.sh" + "echo -n hello > $out" '())) + (hash (sha256 (string->utf8 "hello"))) + (drv (derivation %store "fixed-rec" + %bash `(,builder) + #:inputs `((,builder)) + #:hash (base32 "0sg9f58l1jj88w6pdrfdpj5x9b1zrwszk84j81zvby36q9whhhqa") + #:hash-algo 'sha256 + #:recursive? #t)) + (succeeded? (build-derivations %store (list drv)))) + (and succeeded? + (let ((p (derivation->output-path drv))) + (and (equal? (string->utf8 "hello") + (call-with-input-file p get-bytevector-all)) + (bytevector? (query-path-hash %store p))))))) + (test-assert "derivation with a fixed-output input" ;; A derivation D using a fixed-output derivation F doesn't has the same ;; output path when passed F or F', as long as F and F' have the same output @@ -637,6 +655,54 @@ Deriver: ~a~%" (derivation-file-name final1))) (build-derivations %store (list final1 final2))))) +(test-assert "build-expression->derivation produces recursive fixed-output" + (let* ((builder '(begin + (use-modules (srfi srfi-26)) + (mkdir %output) + (chdir %output) + (call-with-output-file "exe" + (cut display "executable" <>)) + (chmod "exe" #o777) + (symlink "exe" "symlink") + (mkdir "subdir"))) + (drv (build-expression->derivation %store "fixed-rec" builder + #:hash-algo 'sha256 + #:hash (base32 + "10k1lw41wyrjf9mxydi0is5nkpynlsvgslinics4ppir13g7d74p") + #:recursive? #t))) + (and (build-derivations %store (list drv)) + (let* ((dir (derivation->output-path drv)) + (exe (string-append dir "/exe")) + (link (string-append dir "/symlink")) + (subdir (string-append dir "/subdir"))) + (and (executable-file? exe) + (string=? "executable" + (call-with-input-file exe get-string-all)) + (string=? "exe" (readlink link)) + (file-is-directory? subdir)))))) + +(test-assert "build-expression->derivation uses recursive fixed-output" + (let* ((builder '(call-with-output-file %output + (lambda (port) + (display "hello" port)))) + (fixed (build-expression->derivation %store "small-fixed-rec" + builder + #:hash-algo 'sha256 + #:hash (base32 + "0sg9f58l1jj88w6pdrfdpj5x9b1zrwszk84j81zvby36q9whhhqa") + #:recursive? #t)) + (in (derivation->output-path fixed)) + (builder `(begin + (mkdir %output) + (chdir %output) + (symlink ,in "symlink"))) + (drv (build-expression->derivation %store "fixed-rec-user" + builder + #:inputs `(("fixed" ,fixed))))) + (and (build-derivations %store (list drv)) + (let ((out (derivation->output-path drv))) + (string=? (readlink (string-append out "/symlink")) in))))) + (test-assert "build-expression->derivation with #:references-graphs" (let* ((input (add-text-to-store %store "foo" "hello" (list %bash %mkdir))) -- cgit v1.2.3 From 96c7448f370227c9777a6acdac4ac65f1884fb43 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Fri, 21 Feb 2014 20:17:29 +0100 Subject: nar: Produce archives with files sorted in C collation order. * guix/nar.scm (write-file) : Pass 'string '("." "..")) - (scandir f)))) + (let* ((select? (negate (cut member <> '("." "..")))) + + ;; 'scandir' defaults to 'string-locale