all messages for Guix-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: ludo@gnu.org (Ludovic Courtès)
To: Guix-devel <guix-devel@gnu.org>
Subject: Re: Grafts
Date: Fri, 17 Oct 2014 23:42:18 +0200	[thread overview]
Message-ID: <87k33y1ih1.fsf@gnu.org> (raw)
In-Reply-To: <87a950igwi.fsf@gnu.org> ("Ludovic \=\?utf-8\?Q\?Court\=C3\=A8s\=22'\?\= \=\?utf-8\?Q\?s\?\= message of "Mon, 13 Oct 2014 09:10:37 +0200")

[-- Attachment #1: Type: text/plain, Size: 794 bytes --]

The current status of ‘wip-grafts’ is that it works, there’s no
performance issue, etc.

However, the ‘graft-derivation’ procedure is not recursive: it grafts
the derivation you give it, but doesn’t graft its dependencies.  Thus,
only direct references are grafted, which isn’t so great:

  $ guix gc -R $(guix build glib) | grep bash
  /gnu/store/8fmgslrivicy54azysmaab3z1srid773-bash-4.3.27  <--+--- the ungrafted bash
  /gnu/store/3yiqz9wmwx6b7hpbapg5q39sjx33kh0j-bash-4.3.27  <--’
  /gnu/store/yl1rp2b8i2qwgxja3d09xc24ffk9sjmr-bash-4.3.27  <------ the grafted bash

Changing ‘graft-derivation’ to work recursively and perform well is a
bit challenging.

I’m posting the naive patch I have here, in case someone can look at it
before me.

Ludo’.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 5631 bytes --]

	Modified   guix/derivations.scm
diff --git a/guix/derivations.scm b/guix/derivations.scm
index 17c83e9..632bf8e 100644
--- a/guix/derivations.scm
+++ b/guix/derivations.scm
@@ -1007,40 +1009,51 @@ applied."
                      target))))
          grafts))
 
-  (define outputs
-    (match (derivation-outputs drv)
-      (((names . outputs) ...)
-       (map derivation-output-path outputs))))
-
-  (define output-names
-    (match (derivation-outputs drv)
-      (((names . outputs) ...)
-       names)))
-
-  (define build
-    `(begin
-       (use-modules (guix build graft)
-                    (guix build utils)
-                    (ice-9 match))
-
-       (let ((mapping ',mapping))
-         (for-each (lambda (input output)
-                     (format #t "rewriting '~a' to '~a'...~%" input output)
-                     (rewrite-directory input output
-                                        `((,input . ,output)
-                                          ,@mapping)))
-                   ',outputs
-                   (match %outputs
-                     (((names . files) ...)
-                      files))))))
+  (define input-mapping
+    (match-lambda
+     (($ <derivation-input> path sub-drv)
+      (let ((orig (call-with-input-file path read-derivation)))
+        (cons orig
+              (graft-derivation store (derivation-name orig) orig grafts
+                                #:guile guile
+                                #:system system))))))
 
   (define add-label
     (cut cons "x" <>))
 
   (match grafts
     ((($ <graft> sources source-outputs targets target-outputs) ...)
-     (let ((sources (zip sources source-outputs))
-           (targets (zip targets target-outputs)))
+     (let* ((sources (zip sources source-outputs))
+            (targets (zip targets target-outputs))
+            (inputs  (map input-mapping (derivation-inputs drv)))
+            (drv     (pk 'm (map-derivation store drv inputs))))
+       (define outputs
+         (match (derivation-outputs drv)
+           (((names . outputs) ...)
+            (map derivation-output-path outputs))))
+
+       (define output-names
+         (match (derivation-outputs drv)
+           (((names . outputs) ...)
+            names)))
+
+       (define build
+         `(begin
+            (use-modules (guix build graft)
+                         (guix build utils)
+                         (ice-9 match))
+
+            (let ((mapping ',mapping))
+              (for-each (lambda (input output)
+                          (format #t "rewriting '~a' to '~a'...~%" input output)
+                          (rewrite-directory input output
+                                             `((,input . ,output)
+                                               ,@mapping)))
+                        ',outputs
+                        (match %outputs
+                          (((names . files) ...)
+                           files))))))
+
        (build-expression->derivation store name build
                                      #:system system
                                      #:guile-for-build guile
	Modified   tests/derivations.scm
diff --git a/tests/derivations.scm b/tests/derivations.scm
index a69114a..608a7f6 100644
--- a/tests/derivations.scm
+++ b/tests/derivations.scm
@@ -851,6 +851,42 @@ Deriver: ~a~%"
                 (string=? (readlink (string-append graft "/sh")) one)
                 (string=? (readlink (string-append graft "/self")) graft))))))
 
+(test-assert "graft-derivation, recursive"
+  (let* ((build `(begin
+                   (mkdir %output)
+                   (chdir %output)
+                   (call-with-output-file "text"
+                     (lambda (output)
+                       (format output "foo/~a/bar" ,%mkdir)))
+                   (symlink ,%bash "sh")))
+         (dep   (build-expression->derivation %store "dep" build
+                                              #:inputs `(("a" ,%bash)
+                                                         ("b" ,%mkdir))))
+         (orig  (build-expression->derivation %store "graft"
+                                              `(symlink
+                                                (assoc-ref %build-inputs "dep")
+                                                %output)
+                                              #:inputs `(("dep" ,dep))))
+         (one   (add-text-to-store %store "bash" "fake bash"))
+         (two   (build-expression->derivation %store "mkdir"
+                                              '(call-with-output-file %output
+                                                 (lambda (port)
+                                                   (display "fake mkdir" port)))))
+         (graft (graft-derivation %store "graft" orig
+                                  (list (graft
+                                          (origin %bash)
+                                          (replacement one))
+                                        (graft
+                                          (origin %mkdir)
+                                          (replacement two))))))
+    (and (build-derivations %store (list graft))
+         (let ((two   (derivation->output-path two))
+               (graft (derivation->output-path graft)))
+           (and (string=? (format #f "foo/~a/bar" two)
+                          (call-with-input-file (string-append graft "/text")
+                            get-string-all))
+                (string=? (readlink (string-append graft "/sh")) one))))))
+
 (test-equal "map-derivation"
   "hello"
   (let* ((joke (package-derivation %store guile-1.8))

  parent reply	other threads:[~2014-10-17 21:42 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-13  7:10 Grafts Ludovic Courtès
2014-10-15  2:15 ` Grafts Mark H Weaver
2014-10-15 17:02   ` Grafts Ludovic Courtès
2014-10-17 21:42 ` Ludovic Courtès [this message]
2014-11-02 20:27   ` Grafts Ludovic Courtès

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87k33y1ih1.fsf@gnu.org \
    --to=ludo@gnu.org \
    --cc=guix-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/guix.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.