grafts: Make sure files are not created world-writable.
[jackhill/guix/guix.git] / guix / grafts.scm
CommitLineData
7adf9b84
LC
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2014, 2015, 2016 Ludovic Courtès <ludo@gnu.org>
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (guix grafts)
20 #:use-module (guix records)
21 #:use-module (guix derivations)
22 #:use-module ((guix utils) #:select (%current-system))
23 #:use-module (srfi srfi-1)
acb01e37 24 #:use-module (srfi srfi-9 gnu)
7adf9b84
LC
25 #:use-module (srfi srfi-26)
26 #:use-module (ice-9 match)
27 #:export (graft?
28 graft
29 graft-origin
30 graft-replacement
31 graft-origin-output
32 graft-replacement-output
33
34 graft-derivation
35
36 %graft?
37 set-grafting))
38
39(define-record-type* <graft> graft make-graft
40 graft?
41 (origin graft-origin) ;derivation | store item
42 (origin-output graft-origin-output ;string | #f
43 (default "out"))
44 (replacement graft-replacement) ;derivation | store item
45 (replacement-output graft-replacement-output ;string | #f
46 (default "out")))
47
acb01e37
LC
48(define (write-graft graft port)
49 "Write a concise representation of GRAFT to PORT."
50 (define (->string thing output)
51 (if (derivation? thing)
52 (derivation->output-path thing output)
53 thing))
54
55 (match graft
56 (($ <graft> origin origin-output replacement replacement-output)
57 (format port "#<graft ~a ==> ~a ~a>"
58 (->string origin origin-output)
59 (->string replacement replacement-output)
60 (number->string (object-address graft) 16)))))
61
62(set-record-type-printer! <graft> write-graft)
63
b0fef4d6
LC
64(define* (graft-derivation store drv grafts
65 #:key
66 (name (derivation-name drv))
67 (guile (%guile-for-build))
7adf9b84
LC
68 (system (%current-system)))
69 "Return a derivation called NAME, based on DRV but with all the GRAFTS
70applied."
71 ;; XXX: Someday rewrite using gexps.
72 (define mapping
73 ;; List of store item pairs.
74 (map (match-lambda
75 (($ <graft> source source-output target target-output)
76 (cons (if (derivation? source)
77 (derivation->output-path source source-output)
78 source)
79 (if (derivation? target)
80 (derivation->output-path target target-output)
81 target))))
82 grafts))
83
84 (define outputs
85 (match (derivation-outputs drv)
86 (((names . outputs) ...)
87 (map derivation-output-path outputs))))
88
89 (define output-names
90 (match (derivation-outputs drv)
91 (((names . outputs) ...)
92 names)))
93
94 (define build
95 `(begin
96 (use-modules (guix build graft)
97 (guix build utils)
98 (ice-9 match))
99
100 (let ((mapping ',mapping))
101 (for-each (lambda (input output)
102 (format #t "grafting '~a' -> '~a'...~%" input output)
103 (force-output)
104 (rewrite-directory input output
105 `((,input . ,output)
106 ,@mapping)))
107 ',outputs
108 (match %outputs
109 (((names . files) ...)
110 files))))))
111
112 (define add-label
113 (cut cons "x" <>))
114
115 (match grafts
116 ((($ <graft> sources source-outputs targets target-outputs) ...)
117 (let ((sources (zip sources source-outputs))
118 (targets (zip targets target-outputs)))
119 (build-expression->derivation store name build
120 #:system system
121 #:guile-for-build guile
122 #:modules '((guix build graft)
123 (guix build utils))
124 #:inputs `(,@(map (lambda (out)
125 `("x" ,drv ,out))
126 output-names)
127 ,@(append (map add-label sources)
128 (map add-label targets)))
129 #:outputs output-names
130 #:local-build? #t)))))
131
132\f
133;; The following might feel more at home in (guix packages) but since (guix
134;; gexp), which is a lower level, needs them, we put them here.
135
136(define %graft?
137 ;; Whether to honor package grafts by default.
138 (make-parameter #t))
139
140(define (set-grafting enable?)
141 "This monadic procedure enables grafting when ENABLE? is true, and disables
142it otherwise. It returns the previous setting."
143 (lambda (store)
144 (values (%graft? enable?) store)))
145
146;;; grafts.scm ends here