summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2023-10-27 23:44:39 +0200
committerLudovic Courtès <ludo@gnu.org>2023-10-28 00:17:23 +0200
commit67effc1560fc175dfbcb58ef5b965b08b3942d6c (patch)
tree34b28ec16e7b968ab02dac4bb56a721273c4c126
parent2de30042674197fe451c220745186e36465d06e2 (diff)
grafts: Fix corner case involving multiple-output derivations.
Fixes a bug that would occur with references to two outputs of the same derivation, with one of them referring to the other one. For example, the references of libreoffice include both mariadb:dev and mariadb:lib; additionally, mariadb:dev refers to mariadb:lib. In this case, the glibc graft would not be applied on one of the mariadb paths, and both the grafted and ungrafted glibc would end up in the closure of libreoffice. Fixes <https://issues.guix.gnu.org/66662>. * guix/grafts.scm (non-self-references): Simplify and include references to outputs of DRV other than OUTPUTS. (reference-origins): Simplify and possibly return outputs of DRV itself. (cumulative-grafts)[graft-origin?]: Add OUTPUT parameter and honor it. [dependency-grafts]: Adjust accordingly. * tests/grafts.scm ("graft-derivation, multiple outputs need to be replaced"): New test. Change-Id: Iac2005024ab7049037537b3af55298696ec90e3c
-rw-r--r--guix/grafts.scm43
-rw-r--r--tests/grafts.scm50
2 files changed, 68 insertions, 25 deletions
diff --git a/guix/grafts.scm b/guix/grafts.scm
index f93da32981c..48f4c212f7a 100644
--- a/guix/grafts.scm
+++ b/guix/grafts.scm
@@ -1,5 +1,5 @@
1;;; GNU Guix --- Functional package management for GNU 1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2014-2022 Ludovic Courtès <ludo@gnu.org> 2;;; Copyright © 2014-2023 Ludovic Courtès <ludo@gnu.org>
3;;; 3;;;
4;;; This file is part of GNU Guix. 4;;; This file is part of GNU Guix.
5;;; 5;;;
@@ -176,11 +176,8 @@ references."
176 (append-map (cut references/cached store <>) items)))) 176 (append-map (cut references/cached store <>) items))))
177 (append-map (cut references/cached store <>) items))) 177 (append-map (cut references/cached store <>) items)))
178 178
179 (let ((refs (references* (map (cut derivation->output-path drv <>) 179 (let* ((self (map (cut derivation->output-path drv <>) outputs))
180 outputs))) 180 (refs (references* self)))
181 (self (match (derivation->output-paths drv)
182 (((names . items) ...)
183 items))))
184 (remove (cut member <> self) refs))) 181 (remove (cut member <> self) refs)))
185 182
186(define %graft-cache 183(define %graft-cache
@@ -207,7 +204,7 @@ references."
207 (return result))))))) 204 (return result)))))))
208 205
209(define (reference-origins drv items) 206(define (reference-origins drv items)
210 "Return the derivation/output pairs among the inputs of DRV, recursively, 207 "Return the derivation/output pairs among DRV and its inputs, recursively,
211that produce ITEMS. Elements of ITEMS not produced by a derivation (i.e., 208that produce ITEMS. Elements of ITEMS not produced by a derivation (i.e.,
212it's a content-addressed \"source\"), or not produced by a dependency of DRV, 209it's a content-addressed \"source\"), or not produced by a dependency of DRV,
213have no corresponding element in the resulting list." 210have no corresponding element in the resulting list."
@@ -238,13 +235,10 @@ have no corresponding element in the resulting list."
238 ((set-contains? visited drv) 235 ((set-contains? visited drv)
239 (loop rest items result visited)) 236 (loop rest items result visited))
240 (else 237 (else
241 (let* ((inputs 238 (let ((result items (lookup-derivers drv result items)))
242 (map derivation-input-derivation 239 (loop (append rest
243 (derivation-inputs drv))) 240 (map derivation-input-derivation
244 (result items 241 (derivation-inputs drv)))
245 (fold2 lookup-derivers
246 result items inputs)))
247 (loop (append rest inputs)
248 items result 242 items result
249 (set-insert drv visited))))))))) 243 (set-insert drv visited)))))))))
250 244
@@ -258,16 +252,17 @@ GRAFTS to the dependencies of DRV. Return the resulting list of grafts.
258 252
259This is a monadic procedure in %STATE-MONAD where the state is a vhash mapping 253This is a monadic procedure in %STATE-MONAD where the state is a vhash mapping
260derivations to the corresponding set of grafts." 254derivations to the corresponding set of grafts."
261 (define (graft-origin? drv graft) 255 (define (graft-origin? drv output graft)
262 ;; Return true if DRV corresponds to the origin of GRAFT. 256 ;; Return true if DRV and OUTPUT correspond to the origin of GRAFT.
263 (match graft 257 (match graft
264 (($ <graft> (? derivation? origin) output) 258 (($ <graft> (? derivation? origin) origin-output)
265 (match (assoc-ref (derivation->output-paths drv) output) 259 (and (string=? origin-output output)
266 ((? string? result) 260 (match (assoc-ref (derivation->output-paths drv) output)
267 (string=? result 261 ((? string? result)
268 (derivation->output-path origin output))) 262 (string=? result
269 (_ 263 (derivation->output-path origin output)))
270 #f))) 264 (_
265 #f))))
271 (_ 266 (_
272 #f))) 267 #f)))
273 268
@@ -278,7 +273,7 @@ derivations to the corresponding set of grafts."
278 ((drv . output) 273 ((drv . output)
279 ;; If GRAFTS already contains a graft from DRV, do not 274 ;; If GRAFTS already contains a graft from DRV, do not
280 ;; override it. 275 ;; override it.
281 (if (find (cut graft-origin? drv <>) grafts) 276 (if (find (cut graft-origin? drv output <>) grafts)
282 (state-return grafts) 277 (state-return grafts)
283 (cumulative-grafts store drv grafts 278 (cumulative-grafts store drv grafts
284 #:outputs (list output) 279 #:outputs (list output)
diff --git a/tests/grafts.scm b/tests/grafts.scm
index 63dbb138302..24c4d243598 100644
--- a/tests/grafts.scm
+++ b/tests/grafts.scm
@@ -1,5 +1,5 @@
1;;; GNU Guix --- Functional package management for GNU 1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2014-2019, 2022 Ludovic Courtès <ludo@gnu.org> 2;;; Copyright © 2014-2019, 2022-2023 Ludovic Courtès <ludo@gnu.org>
3;;; Copyright © 2021 Mark H Weaver <mhw@netris.org> 3;;; Copyright © 2021 Mark H Weaver <mhw@netris.org>
4;;; 4;;;
5;;; This file is part of GNU Guix. 5;;; This file is part of GNU Guix.
@@ -268,6 +268,54 @@
268 (readlink (string-append out "/two"))) 268 (readlink (string-append out "/two")))
269 (file-exists? (string-append out "/one/replacement"))))))) 269 (file-exists? (string-append out "/one/replacement")))))))
270 270
271(test-assert "graft-derivation, multiple outputs need to be replaced"
272 ;; Build a reference graph like this:
273 ;;
274 ;; ,- p2:out --.
275 ;; v v
276 ;; p1:one <---- p1:two
277 ;; |
278 ;; `-> p0
279 ;;
280 ;; Graft p0r in lieu of p0, and make sure all the paths from the grafted p2
281 ;; lead to p0r. See <https://issues.guix.gnu.org/66662>.
282 (let* ((p0 (build-expression->derivation
283 %store "p0" '(mkdir (assoc-ref %outputs "out"))))
284 (p0r (build-expression->derivation
285 %store "P0"
286 '(let ((out (assoc-ref %outputs "out")))
287 (mkdir out)
288 (call-with-output-file (string-append out "/replacement")
289 (const #t)))))
290 (p1 (build-expression->derivation
291 %store "p1"
292 `(let ((one (assoc-ref %outputs "one"))
293 (two (assoc-ref %outputs "two"))
294 (p0 (assoc-ref %build-inputs "p0")))
295 (mkdir one)
296 (mkdir two)
297 (symlink p0 (string-append one "/p0"))
298 (symlink one (string-append two "/link")))
299 #:inputs `(("p0" ,p0))
300 #:outputs '("one" "two")))
301 (p2 (build-expression->derivation
302 %store "p2"
303 `(let ((out (assoc-ref %outputs "out")))
304 (mkdir out) (chdir out)
305 (symlink (assoc-ref %build-inputs "p1:one") "one")
306 (symlink (assoc-ref %build-inputs "p1:two") "two"))
307 #:inputs `(("p1:one" ,p1 "one")
308 ("p1:two" ,p1 "two"))))
309 (p0g (list (graft
310 (origin p0)
311 (replacement p0r))))
312 (p2d (graft-derivation %store p2 p0g)))
313
314 (build-derivations %store (list p2d))
315 (let ((out (derivation->output-path (pk 'p2d p2d))))
316 (equal? (stat (string-append out "/one/p0/replacement"))
317 (stat (string-append out "/two/link/p0/replacement"))))))
318
271(test-assert "graft-derivation with #:outputs" 319(test-assert "graft-derivation with #:outputs"
272 ;; Call 'graft-derivation' with a narrowed set of outputs passed as 320 ;; Call 'graft-derivation' with a narrowed set of outputs passed as
273 ;; #:outputs. 321 ;; #:outputs.