diff --git a/guix/build/union.scm b/guix/build/union.scm index 6640b56523..a2ea72e1f5 100644 --- a/guix/build/union.scm +++ b/guix/build/union.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2012, 2013, 2014, 2016 Ludovic Courtès ;;; Copyright © 2014 Mark H Weaver +;;; Copyright © 2017 Huang Ying ;;; ;;; This file is part of GNU Guix. ;;; @@ -73,9 +74,12 @@ identical, #f otherwise." (loop))))))))))))) (define* (union-build output inputs - #:key (log-port (current-error-port))) - "Build in the OUTPUT directory a symlink tree that is the union of all -the INPUTS." + #:key (log-port (current-error-port)) + (create-all-directories? #f)) + "Build in the OUTPUT directory a symlink tree that is the union of all the +INPUTS. As a special case, if CREATE-ALL-DIRECTORIES?, creates the +subdirectories in the output directory to make sure the caller can modify them +later." (define (symlink* input output) (format log-port "`~a' ~~> `~a'~%" input output) @@ -104,8 +108,11 @@ the INPUTS." (define (union output inputs) (match inputs ((input) - ;; There's only one input, so just make a link. - (symlink* input output)) + ;; There's only one input, so just make a link unless + ;; create-all-directories?. + (if (and create-all-directories? (file-is-directory? input)) + (union-of-directories output inputs) + (symlink* input output))) (_ (call-with-values (lambda () (partition file-is-directory? inputs)) (match-lambda* diff --git a/tests/union.scm b/tests/union.scm index cccf397181..b63edc757b 100644 --- a/tests/union.scm +++ b/tests/union.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès +;;; Copyright © 2012, 2013, 2014, 2015, 2017 Ludovic Courtès ;;; ;;; This file is part of GNU Guix. ;;; @@ -124,4 +124,24 @@ ;; new 'bin' sub-directory in the profile. (eq? 'directory (stat:type (lstat "bin")))))))) +(test-assert "union-build #:create-all-directories? #t" + (let* ((build `(begin + (use-modules (guix build union)) + (union-build (assoc-ref %outputs "out") + (map cdr %build-inputs) + #:create-all-directories? #t))) + (input (package-derivation %store %bootstrap-guile)) + (drv (build-expression->derivation %store "union-test-all-dirs" + build + #:modules '((guix build union)) + #:inputs `(("g" ,input))))) + (and (build-derivations %store (list drv)) + (with-directory-excursion (derivation->output-path drv) + ;; Even though there's only one input to the union, + ;; #:create-all-directories? #t must have created bin/ rather than + ;; making it a symlink to Guile's bin/. + (and (file-exists? "bin/guile") + (file-is-directory? "bin") + (eq? 'symlink (stat:type (lstat "bin/guile")))))))) + (test-end)