diff --git a/guix/build/graft.scm b/guix/build/graft.scm index e9fce03181..b61982dd64 100644 --- a/guix/build/graft.scm +++ b/guix/build/graft.scm @@ -83,6 +83,28 @@ writing the result to OUTPUT." (put-u8 output (char->integer char)) result))))) +(define (rename-matching-files directory mapping) + "Apply MAPPING to the names of all the files in DIRECTORY, where MAPPING is +a list of store file name pairs." + (let* ((mapping (map (match-lambda + ((source . target) + (cons (basename source) (basename target)))) + mapping)) + (matches (find-files directory + (lambda (file stat) + (assoc-ref mapping (basename file))) + #:directories? #t))) + + ;; XXX: This is not quite correct: if MAPPING contains "foo", and + ;; DIRECTORY contains "bar/foo/foo", we first rename "bar/foo" and then + ;; "bar/foo/foo" no longer exists so we fail. Oh well, surely that's good + ;; enough! + (for-each (lambda (file) + (let ((target (assoc-ref mapping (basename file)))) + (rename-file file + (string-append (dirname file) "/" target)))) + matches))) + (define* (rewrite-directory directory output mapping #:optional (store (%store-directory))) "Copy DIRECTORY to OUTPUT, replacing strings according to MAPPING, a list of @@ -127,6 +149,7 @@ file name pairs." (n-par-for-each (parallel-job-count) rewrite-leaf (find-files directory (const #t) - #:directories? #t))) + #:directories? #t)) + (rename-matching-files output mapping)) ;;; graft.scm ends here diff --git a/tests/grafts.scm b/tests/grafts.scm index f8c9eced1d..8cd048552c 100644 --- a/tests/grafts.scm +++ b/tests/grafts.scm @@ -182,4 +182,21 @@ (and (string=? (readlink one) repl) (string=? (readlink two) one)))))) +(test-assert "graft-derivation, renaming" ; + (let* ((build `(begin + (use-modules (guix build utils)) + (mkdir-p (string-append (assoc-ref %outputs "out") "/" + (assoc-ref %build-inputs "in"))))) + (orig (build-expression->derivation %store "thing-to-graft" build + #:modules '((guix build utils)) + #:inputs `(("in" ,%bash)))) + (repl (add-text-to-store %store "bash" "fake bash")) + (grafted (graft-derivation %store orig + (list (graft + (origin %bash) + (replacement repl)))))) + (and (build-derivations %store (list grafted)) + (let ((out (derivation->output-path grafted))) + (file-is-directory? (string-append out "/" repl)))))) + (test-end)