diff options
author | Ludovic Courtès <ludo@gnu.org> | 2017-04-05 15:19:15 +0200 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2017-04-05 22:45:41 +0200 |
commit | f37f2b83fa95c1fe2bf01c4b8072cfc23d4c67ec (patch) | |
tree | bed6bac6a29ee4575fdbf34604bd380f0d5c2ff7 | |
parent | 79f912c7106131f4179c727583d33500271361cd (diff) |
packages: Add 'package-mapping' and base 'package-input-rewriting' on it.
* guix/packages.scm (package-mapping): New procedure.
(package-input-rewriting): Rewrite in terms of 'package-mapping'.
* tests/packages.scm ("package-mapping"): New test.
* doc/guix.texi (Defining Packages): Document it.
-rw-r--r-- | doc/guix.texi | 10 | ||||
-rw-r--r-- | guix/packages.scm | 56 | ||||
-rw-r--r-- | tests/packages.scm | 27 |
3 files changed, 74 insertions, 19 deletions
diff --git a/doc/guix.texi b/doc/guix.texi index aa779e38e2..b2498d039e 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -2946,6 +2946,16 @@ with @var{libressl}. Then we use it to define a @dfn{variant} of the This is exactly what the @option{--with-input} command-line option does (@pxref{Package Transformation Options, @option{--with-input}}). +A more generic procedure to rewrite a package dependency graph is +@code{package-mapping}: it supports arbitrary changes to nodes in the +graph. + +@deffn {Scheme Procedure} package-mapping @var{proc} [@var{cut?}] +Return a procedure that, given a package, applies @var{proc} to all the packages +depended on and returns the resulting package. The procedure stops recursion +when @var{cut?} returns true for a given package. +@end deffn + @menu * package Reference :: The package data type. * origin Reference:: The origin data type. diff --git a/guix/packages.scm b/guix/packages.scm index b68b3de6d2..44f2c32fb7 100644 --- a/guix/packages.scm +++ b/guix/packages.scm @@ -98,6 +98,7 @@ package-transitive-propagated-inputs package-transitive-native-search-paths package-transitive-supported-systems + package-mapping package-input-rewriting package-source-derivation package-derivation @@ -741,36 +742,53 @@ dependencies are known to build on SYSTEM." "Return the \"target inputs\" of BAG, recursively." (transitive-inputs (bag-target-inputs bag))) -(define* (package-input-rewriting replacements - #:optional (rewrite-name identity)) - "Return a procedure that, when passed a package, replaces its direct and -indirect dependencies (but not its implicit inputs) according to REPLACEMENTS. -REPLACEMENTS is a list of package pairs; the first element of each pair is the -package to replace, and the second one is the replacement. - -Optionally, REWRITE-NAME is a one-argument procedure that takes the name of a -package and returns its new name after rewrite." +(define* (package-mapping proc #:optional (cut? (const #f))) + "Return a procedure that, given a package, applies PROC to all the packages +depended on and returns the resulting package. The procedure stops recursion +when CUT? returns true for a given package." (define (rewrite input) (match input ((label (? package? package) outputs ...) - (match (assq-ref replacements package) - (#f (cons* label (replace package) outputs)) - (new (cons* label new outputs)))) + (let ((proc (if (cut? package) proc replace))) + (cons* label (proc package) outputs))) (_ input))) (define replace (mlambdaq (p) - ;; Return a variant of P with its inputs rewritten. - (package - (inherit p) - (name (rewrite-name (package-name p))) - (inputs (map rewrite (package-inputs p))) - (native-inputs (map rewrite (package-native-inputs p))) - (propagated-inputs (map rewrite (package-propagated-inputs p)))))) + ;; Return a variant of P with PROC applied to P and its explicit + ;; dependencies, recursively. Memoize the transformations. Failing to + ;; do that, we would build a huge object graph with lots of duplicates, + ;; which in turns prevents us from benefiting from memoization in + ;; 'package-derivation'. + (let ((p (proc p))) + (package + (inherit p) + (location (package-location p)) + (inputs (map rewrite (package-inputs p))) + (native-inputs (map rewrite (package-native-inputs p))) + (propagated-inputs (map rewrite (package-propagated-inputs p))))))) replace) +(define* (package-input-rewriting replacements + #:optional (rewrite-name identity)) + "Return a procedure that, when passed a package, replaces its direct and +indirect dependencies (but not its implicit inputs) according to REPLACEMENTS. +REPLACEMENTS is a list of package pairs; the first element of each pair is the +package to replace, and the second one is the replacement. + +Optionally, REWRITE-NAME is a one-argument procedure that takes the name of a +package and returns its new name after rewrite." + (define (rewrite p) + (match (assq-ref replacements p) + (#f (package + (inherit p) + (name (rewrite-name (package-name p))))) + (new new))) + + (package-mapping rewrite (cut assq <> replacements))) + ;;; ;;; Package derivations. diff --git a/tests/packages.scm b/tests/packages.scm index 51dc1ba2b0..930374dabf 100644 --- a/tests/packages.scm +++ b/tests/packages.scm @@ -886,6 +886,33 @@ (and (build-derivations %store (list drv)) (file-exists? (string-append out "/bin/make"))))))) +(test-equal "package-mapping" + 42 + (let* ((dep (dummy-package "chbouib" + (native-inputs `(("x" ,grep))))) + (p0 (dummy-package "example" + (inputs `(("foo" ,coreutils) + ("bar" ,grep) + ("baz" ,dep))))) + (transform (lambda (p) + (package (inherit p) (source 42)))) + (rewrite (package-mapping transform)) + (p1 (rewrite p0))) + (and (eq? p1 (rewrite p0)) + (eqv? 42 (package-source p1)) + (match (package-inputs p1) + ((("foo" dep1) ("bar" dep2) ("baz" dep3)) + (and (eq? dep1 (rewrite coreutils)) ;memoization + (eq? dep2 (rewrite grep)) + (eq? dep3 (rewrite dep)) + (eqv? 42 + (package-source dep1) (package-source dep2) + (package-source dep3)) + (match (package-native-inputs dep3) + ((("x" dep)) + (and (eq? dep (rewrite grep)) + (package-source dep)))))))))) + (test-assert "package-input-rewriting" (let* ((dep (dummy-package "chbouib" (native-inputs `(("x" ,grep))))) |