diff options
| -rw-r--r-- | guix/channels.scm | 64 | ||||
| -rw-r--r-- | tests/channels.scm | 84 |
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 | ||
| 295 | list 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 |
| 294 | INSTANCES." | 323 | INSTANCES." |
| @@ -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") |
