guix-commits
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]