summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--guix/channels.scm64
-rw-r--r--tests/channels.scm84
2 files changed, 126 insertions, 22 deletions
diff --git a/guix/channels.scm b/guix/channels.scm
index cd8a0131bd8..b9ce2aa0249 100644
--- a/guix/channels.scm
+++ b/guix/channels.scm
@@ -35,6 +35,7 @@
35 #:autoload (guix self) (whole-package make-config.scm) 35 #:autoload (guix self) (whole-package make-config.scm)
36 #:autoload (guix inferior) (gexp->derivation-in-inferior) ;FIXME: circular dep 36 #:autoload (guix inferior) (gexp->derivation-in-inferior) ;FIXME: circular dep
37 #:use-module (ice-9 match) 37 #:use-module (ice-9 match)
38 #:use-module (ice-9 vlist)
38 #:export (channel 39 #:export (channel
39 channel? 40 channel?
40 channel-name 41 channel-name
@@ -289,6 +290,34 @@ INSTANCE depends on."
289 #:commit (channel-instance-commit instance) 290 #:commit (channel-instance-commit instance)
290 #:dependencies dependencies)) 291 #:dependencies dependencies))
291 292
293(define (resolve-dependencies instances)
294 "Return a procedure that, given one of the elements of INSTANCES, returns
295list of instances it depends on."
296 (define channel-instance-name
297 (compose channel-name channel-instance-channel))
298
299 (define table ;map a name to an instance
300 (fold (lambda (instance table)
301 (vhash-consq (channel-instance-name instance)
302 instance table))
303 vlist-null
304 instances))
305
306 (define edges
307 (fold (lambda (instance edges)
308 (fold (lambda (channel edges)
309 (let ((name (channel-name channel)))
310 (match (vhash-assq name table)
311 ((_ . target)
312 (vhash-consq instance target edges)))))
313 edges
314 (channel-instance-dependencies instance)))
315 vlist-null
316 instances))
317
318 (lambda (instance)
319 (vhash-foldq* cons '() instance edges)))
320
292(define (channel-instance-derivations instances) 321(define (channel-instance-derivations instances)
293 "Return the list of derivations to build INSTANCES, in the same order as 322 "Return the list of derivations to build INSTANCES, in the same order as
294INSTANCES." 323INSTANCES."
@@ -310,27 +339,22 @@ INSTANCES."
310 (module-ref (resolve-interface '(gnu packages guile)) 339 (module-ref (resolve-interface '(gnu packages guile))
311 'guile-bytestructures))) 340 'guile-bytestructures)))
312 341
313 (mlet %store-monad ((core (build-channel-instance core-instance))) 342 (define edges
314 (mapm %store-monad 343 (resolve-dependencies instances))
315 (lambda (instance) 344
316 (if (eq? instance core-instance) 345 (define (instance->derivation instance)
317 (return core) 346 (mcached (if (eq? instance core-instance)
318 (match (channel-instance-dependencies instance) 347 (build-channel-instance instance)
319 (() 348 (mlet %store-monad ((core (instance->derivation core-instance))
349 (deps (mapm %store-monad instance->derivation
350 (edges instance))))
320 (build-channel-instance instance 351 (build-channel-instance instance
321 (cons core dependencies))) 352 (cons core
322 (channels 353 (append deps
323 (mlet %store-monad ((dependencies-derivation 354 dependencies)))))
324 (latest-channel-derivation 355 instance))
325 ;; %default-channels is used here to 356
326 ;; ensure that the core channel is 357 (mapm %store-monad instance->derivation instances))
327 ;; available for channels declared as
328 ;; dependencies.
329 (append channels %default-channels))))
330 (build-channel-instance instance
331 (cons dependencies-derivation
332 (cons core dependencies))))))))
333 instances)))
334 358
335(define (whole-package-for-legacy name modules) 359(define (whole-package-for-legacy name modules)
336 "Return a full-blown Guix package for MODULES, a derivation that builds Guix 360 "Return a full-blown Guix package for MODULES, a derivation that builds Guix
diff --git a/tests/channels.scm b/tests/channels.scm
index f3fc383ac31..7df1b8c5fe5 100644
--- a/tests/channels.scm
+++ b/tests/channels.scm
@@ -18,9 +18,15 @@
18 18
19(define-module (test-channels) 19(define-module (test-channels)
20 #:use-module (guix channels) 20 #:use-module (guix channels)
21 #:use-module (guix profiles)
21 #:use-module ((guix build syscalls) #:select (mkdtemp!)) 22 #:use-module ((guix build syscalls) #:select (mkdtemp!))
22 #:use-module (guix tests) 23 #:use-module (guix tests)
24 #:use-module (guix store)
25 #:use-module ((guix grafts) #:select (%graft?))
26 #:use-module (guix derivations)
27 #:use-module (guix gexp)
23 #:use-module (srfi srfi-1) 28 #:use-module (srfi srfi-1)
29 #:use-module (srfi srfi-26)
24 #:use-module (srfi srfi-64) 30 #:use-module (srfi srfi-64)
25 #:use-module (ice-9 match)) 31 #:use-module (ice-9 match))
26 32
@@ -34,8 +40,9 @@
34 (and spec 40 (and spec
35 (with-output-to-file (string-append instance-dir "/.guix-channel") 41 (with-output-to-file (string-append instance-dir "/.guix-channel")
36 (lambda _ (format #t "~a" spec)))) 42 (lambda _ (format #t "~a" spec))))
37 ((@@ (guix channels) channel-instance) 43 (checkout->channel-instance instance-dir
38 name commit instance-dir)) 44 #:commit commit
45 #:name name))
39 46
40(define instance--boring (make-instance)) 47(define instance--boring (make-instance))
41(define instance--no-deps 48(define instance--no-deps
@@ -136,4 +143,77 @@
136 'abc1234))) 143 'abc1234)))
137 instances)))))) 144 instances))))))
138 145
146(test-assert "channel-instances->manifest"
147 ;; Compute the manifest for a graph of instances and make sure we get a
148 ;; derivation graph that mirrors the instance graph. This test also ensures
149 ;; we don't try to access Git repositores at all at this stage.
150 (let* ((spec (lambda deps
151 `(channel (version 0)
152 (dependencies
153 ,@(map (lambda (dep)
154 `(channel
155 (name ,dep)
156 (url "http://example.org")))
157 deps)))))
158 (guix (make-instance #:name 'guix))
159 (instance0 (make-instance #:name 'a))
160 (instance1 (make-instance #:name 'b #:spec (spec 'a)))
161 (instance2 (make-instance #:name 'c #:spec (spec 'b)))
162 (instance3 (make-instance #:name 'd #:spec (spec 'c 'a))))
163 (%graft? #f) ;don't try to build stuff
164
165 ;; Create 'build-self.scm' so that GUIX is recognized as the 'guix' channel.
166 (let ((source (channel-instance-checkout guix)))
167 (mkdir (string-append source "/build-aux"))
168 (call-with-output-file (string-append source
169 "/build-aux/build-self.scm")
170 (lambda (port)
171 (write '(begin
172 (use-modules (guix) (gnu packages bootstrap))
173
174 (lambda _
175 (package->derivation %bootstrap-guile)))
176 port))))
177
178 (with-store store
179 (let ()
180 (define manifest
181 (run-with-store store
182 (channel-instances->manifest (list guix
183 instance0 instance1
184 instance2 instance3))))
185
186 (define entries
187 (manifest-entries manifest))
188
189 (define (depends? drv in out)
190 ;; Return true if DRV depends on all of IN and none of OUT.
191 (let ((lst (map derivation-input-path (derivation-inputs drv)))
192 (in (map derivation-file-name in))
193 (out (map derivation-file-name out)))
194 (and (every (cut member <> lst) in)
195 (not (any (cut member <> lst) out)))))
196
197 (define (lookup name)
198 (run-with-store store
199 (lower-object
200 (manifest-entry-item
201 (manifest-lookup manifest
202 (manifest-pattern (name name)))))))
203
204 (let ((drv-guix (lookup "guix"))
205 (drv0 (lookup "a"))
206 (drv1 (lookup "b"))
207 (drv2 (lookup "c"))
208 (drv3 (lookup "d")))
209 (and (depends? drv-guix '() (list drv0 drv1 drv2 drv3))
210 (depends? drv0
211 (list) (list drv1 drv2 drv3))
212 (depends? drv1
213 (list drv0) (list drv2 drv3))
214 (depends? drv2
215 (list drv1) (list drv0 drv3))
216 (depends? drv3
217 (list drv2 drv0) (list drv1))))))))
218
139(test-end "channels") 219(test-end "channels")