summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2016-10-14 18:56:48 +0200
committerLudovic Courtès <ludo@gnu.org>2016-10-14 23:31:50 +0200
commitb013c33f6f060c14ca7d1f3cfcb5d8ce3ef1c53c (patch)
treef83963c52c49c32d4d8de8ac49c1b45e751548c5
parentd0025d01445ff271ececea20cfa6a2346593d1d6 (diff)
grafts: 'graft-derivation' does now introduce grafts that shadow other grafts.
Partly fixes <http://bugs.gnu.org/24418>. * guix/grafts.scm (cumulative-grafts)[graft-origin?]: New procedure. [dependency-grafts]: Use it in new 'if' around recursive call. * tests/grafts.scm ("graft-derivation, grafts are not shadowed"): New test.
-rw-r--r--guix/grafts.scm24
-rw-r--r--tests/grafts.scm62
2 files changed, 82 insertions, 4 deletions
diff --git a/guix/grafts.scm b/guix/grafts.scm
index 53e697688a5..3e7a81a4c7c 100644
--- a/guix/grafts.scm
+++ b/guix/grafts.scm
@@ -227,13 +227,29 @@ resulting list of grafts.
227 227
228This is a monadic procedure in %STATE-MONAD where the state is a vhash mapping 228This is a monadic procedure in %STATE-MONAD where the state is a vhash mapping
229derivations to the corresponding set of grafts." 229derivations to the corresponding set of grafts."
230 (define (graft-origin? drv graft)
231 ;; Return true if DRV corresponds to the origin of GRAFT.
232 (match graft
233 (($ <graft> (? derivation? origin) output)
234 (match (assoc-ref (derivation->output-paths drv) output)
235 ((? string? result)
236 (string=? result
237 (derivation->output-path origin output)))
238 (_
239 #f)))
240 (_
241 #f)))
242
230 (define (dependency-grafts item) 243 (define (dependency-grafts item)
231 (let-values (((drv output) (item->deriver store item))) 244 (let-values (((drv output) (item->deriver store item)))
232 (if drv 245 (if drv
233 (cumulative-grafts store drv grafts references 246 ;; If GRAFTS already contains a graft from DRV, do not override it.
234 #:outputs (list output) 247 (if (find (cut graft-origin? drv <>) grafts)
235 #:guile guile 248 (state-return grafts)
236 #:system system) 249 (cumulative-grafts store drv grafts references
250 #:outputs (list output)
251 #:guile guile
252 #:system system))
237 (state-return grafts)))) 253 (state-return grafts))))
238 254
239 (define (return/cache cache value) 255 (define (return/cache cache value)
diff --git a/tests/grafts.scm b/tests/grafts.scm
index f2ff839fd88..4eff06b4b3c 100644
--- a/tests/grafts.scm
+++ b/tests/grafts.scm
@@ -218,4 +218,66 @@
218 (let ((out (derivation->output-path grafted))) 218 (let ((out (derivation->output-path grafted)))
219 (file-is-directory? (string-append out "/" repl)))))) 219 (file-is-directory? (string-append out "/" repl))))))
220 220
221(test-assert "graft-derivation, grafts are not shadowed"
222 ;; We build a DAG as below, where dotted arrows represent replacements and
223 ;; solid arrows represent dependencies:
224 ;;
225 ;; P1 ·············> P1R
226 ;; |\__________________.
227 ;; v v
228 ;; P2 ·············> P2R
229 ;; |
230 ;; v
231 ;; P3
232 ;;
233 ;; We want to make sure that the two grafts we want to apply to P3 are
234 ;; honored and not shadowed by other computed grafts.
235 (let* ((p1 (build-expression->derivation
236 %store "p1"
237 '(mkdir (assoc-ref %outputs "out"))))
238 (p1r (build-expression->derivation
239 %store "P1"
240 '(let ((out (assoc-ref %outputs "out")))
241 (mkdir out)
242 (call-with-output-file (string-append out "/replacement")
243 (const #t)))))
244 (p2 (build-expression->derivation
245 %store "p2"
246 `(let ((out (assoc-ref %outputs "out")))
247 (mkdir out)
248 (chdir out)
249 (symlink (assoc-ref %build-inputs "p1") "p1"))
250 #:inputs `(("p1" ,p1))))
251 (p2r (build-expression->derivation
252 %store "P2"
253 `(let ((out (assoc-ref %outputs "out")))
254 (mkdir out)
255 (chdir out)
256 (symlink (assoc-ref %build-inputs "p1") "p1")
257 (call-with-output-file (string-append out "/replacement")
258 (const #t)))
259 #:inputs `(("p1" ,p1))))
260 (p3 (build-expression->derivation
261 %store "p3"
262 `(let ((out (assoc-ref %outputs "out")))
263 (mkdir out)
264 (chdir out)
265 (symlink (assoc-ref %build-inputs "p2") "p2"))
266 #:inputs `(("p2" ,p2))))
267 (p1g (graft
268 (origin p1)
269 (replacement p1r)))
270 (p2g (graft
271 (origin p2)
272 (replacement (graft-derivation %store p2r (list p1g)))))
273 (p3d (graft-derivation %store p3 (list p1g p2g))))
274 (and (build-derivations %store (list p3d))
275 (let ((out (derivation->output-path (pk p3d))))
276 ;; Make sure OUT refers to the replacement of P2, which in turn
277 ;; refers to the replacement of P1, as specified by P1G and P2G.
278 ;; It used to be the case that P2G would be shadowed by a simple
279 ;; P2->P2R graft, which is not what we want.
280 (and (file-exists? (string-append out "/p2/replacement"))
281 (file-exists? (string-append out "/p2/p1/replacement")))))))
282
221(test-end) 283(test-end)