[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
04/04: profiles: Correctly deal with etc/ being a relative symlink.
From: |
Ludovic Courtès |
Subject: |
04/04: profiles: Correctly deal with etc/ being a relative symlink. |
Date: |
Mon, 10 Sep 2018 18:15:04 -0400 (EDT) |
civodul pushed a commit to branch master
in repository guix.
commit 2225d56a14a2d8d29374a14eefe90b3cffa79804
Author: Ludovic Courtès <address@hidden>
Date: Mon Sep 10 23:37:48 2018 +0200
profiles: Correctly deal with etc/ being a relative symlink.
Fixes <https://bugs.gnu.org/32686>.
Reported by Oleg Pykhalov <address@hidden>.
* guix/build/profiles.scm (ensure-writable-directory): Add #:symlink.
[absolute?]: New procedure.
[unsymlink]: Use it to determine how to resolve readlink's result.
(build-profile): Pass SYMLINK to 'ensure-writable-directory'.
* tests/profiles.scm ("profile-derivation when etc/ is a relative symlink"):
New test.
---
guix/build/profiles.scm | 15 ++++++++++++---
tests/profiles.scm | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/guix/build/profiles.scm b/guix/build/profiles.scm
index df785c8..0c23cd3 100644
--- a/guix/build/profiles.scm
+++ b/guix/build/profiles.scm
@@ -94,12 +94,20 @@ definitions for all the SEARCH-PATHS."
(for-each (write-environment-variable-definition port)
(map (abstract-profile output) variables))))))
-(define (ensure-writable-directory directory)
+(define* (ensure-writable-directory directory
+ #:key (symlink symlink))
"Ensure DIRECTORY exists and is writable. If DIRECTORY is currently a
symlink (to a read-only directory in the store), then delete the symlink and
instead make DIRECTORY a \"real\" directory containing symlinks."
+ (define (absolute? file)
+ (string-prefix? "/" file))
+
(define (unsymlink link)
- (let* ((target (readlink link))
+ (let* ((target (match (readlink link)
+ ((? absolute? target)
+ target)
+ ((? string? relative)
+ (string-append (dirname link) "/" relative))))
;; TARGET might itself be a symlink, so append "/" to make sure
;; 'scandir' enters it.
(files (scandir (string-append target "/")
@@ -149,7 +157,8 @@ SEARCH-PATHS."
;; Make sure we can write to 'OUTPUT/etc'. 'union-build' above could have
;; made 'etc' a symlink to a read-only sub-directory in the store so we need
;; to work around that.
- (ensure-writable-directory (string-append output "/etc"))
+ (ensure-writable-directory (string-append output "/etc")
+ #:symlink symlink)
;; Write 'OUTPUT/etc/profile'.
(build-etc/profile output search-paths))
diff --git a/tests/profiles.scm b/tests/profiles.scm
index 3a59a0c..9f366a0 100644
--- a/tests/profiles.scm
+++ b/tests/profiles.scm
@@ -20,6 +20,7 @@
(define-module (test-profiles)
#:use-module (guix tests)
#:use-module (guix profiles)
+ #:use-module (guix gexp)
#:use-module (guix store)
#:use-module (guix monads)
#:use-module (guix grafts)
@@ -543,6 +544,41 @@
get-string-all)
"foo!"))))))
+(test-assertm "profile-derivation when etc/ is a relative symlink"
+ ;; See <https://bugs.gnu.org/32686>.
+ (mlet* %store-monad
+ ((etc (gexp->derivation
+ "etc"
+ #~(begin
+ (mkdir #$output)
+ (call-with-output-file (string-append #$output "/foo")
+ (lambda (port)
+ (display "Heya!" port))))))
+ (thing -> (dummy-package "dummy"
+ (build-system trivial-build-system)
+ (inputs
+ `(("etc" ,etc)))
+ (arguments
+ `(#:guile ,%bootstrap-guile
+ #:builder
+ (let ((out (assoc-ref %outputs "out"))
+ (etc (assoc-ref %build-inputs "etc")))
+ (mkdir out)
+ (symlink etc (string-append out "/etc"))
+ #t)))))
+ (entry -> (package->manifest-entry thing))
+ (drv (profile-derivation (manifest (list entry))
+ #:relative-symlinks? #t
+ #:hooks '()
+ #:locales? #f))
+ (profile -> (derivation->output-path drv)))
+ (mbegin %store-monad
+ (built-derivations (list drv))
+ (return (string=? (call-with-input-file
+ (string-append profile "/etc/foo")
+ get-string-all)
+ "Heya!")))))
+
(test-equalm "union vs. dangling symlink" ;<https://bugs.gnu.org/26949>
"does-not-exist"
(mlet* %store-monad