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 aa779e38e2e..b2498d039ef 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 | |||
| 2946 | This is exactly what the @option{--with-input} command-line option does | 2946 | This is exactly what the @option{--with-input} command-line option does |
| 2947 | (@pxref{Package Transformation Options, @option{--with-input}}). | 2947 | (@pxref{Package Transformation Options, @option{--with-input}}). |
| 2948 | 2948 | ||
| 2949 | A more generic procedure to rewrite a package dependency graph is | ||
| 2950 | @code{package-mapping}: it supports arbitrary changes to nodes in the | ||
| 2951 | graph. | ||
| 2952 | |||
| 2953 | @deffn {Scheme Procedure} package-mapping @var{proc} [@var{cut?}] | ||
| 2954 | Return a procedure that, given a package, applies @var{proc} to all the packages | ||
| 2955 | depended on and returns the resulting package. The procedure stops recursion | ||
| 2956 | when @var{cut?} returns true for a given package. | ||
| 2957 | @end deffn | ||
| 2958 | |||
| 2949 | @menu | 2959 | @menu |
| 2950 | * package Reference :: The package data type. | 2960 | * package Reference :: The package data type. |
| 2951 | * origin Reference:: The origin data type. | 2961 | * origin Reference:: The origin data type. |
diff --git a/guix/packages.scm b/guix/packages.scm index b68b3de6d23..44f2c32fb7d 100644 --- a/guix/packages.scm +++ b/guix/packages.scm | |||
| @@ -98,6 +98,7 @@ | |||
| 98 | package-transitive-propagated-inputs | 98 | package-transitive-propagated-inputs |
| 99 | package-transitive-native-search-paths | 99 | package-transitive-native-search-paths |
| 100 | package-transitive-supported-systems | 100 | package-transitive-supported-systems |
| 101 | package-mapping | ||
| 101 | package-input-rewriting | 102 | package-input-rewriting |
| 102 | package-source-derivation | 103 | package-source-derivation |
| 103 | package-derivation | 104 | package-derivation |
| @@ -741,36 +742,53 @@ dependencies are known to build on SYSTEM." | |||
| 741 | "Return the \"target inputs\" of BAG, recursively." | 742 | "Return the \"target inputs\" of BAG, recursively." |
| 742 | (transitive-inputs (bag-target-inputs bag))) | 743 | (transitive-inputs (bag-target-inputs bag))) |
| 743 | 744 | ||
| 744 | (define* (package-input-rewriting replacements | 745 | (define* (package-mapping proc #:optional (cut? (const #f))) |
| 745 | #:optional (rewrite-name identity)) | 746 | "Return a procedure that, given a package, applies PROC to all the packages |
| 746 | "Return a procedure that, when passed a package, replaces its direct and | 747 | depended on and returns the resulting package. The procedure stops recursion |
| 747 | indirect dependencies (but not its implicit inputs) according to REPLACEMENTS. | 748 | when CUT? returns true for a given package." |
| 748 | REPLACEMENTS is a list of package pairs; the first element of each pair is the | ||
| 749 | package to replace, and the second one is the replacement. | ||
| 750 | |||
| 751 | Optionally, REWRITE-NAME is a one-argument procedure that takes the name of a | ||
| 752 | package and returns its new name after rewrite." | ||
| 753 | (define (rewrite input) | 749 | (define (rewrite input) |
| 754 | (match input | 750 | (match input |
| 755 | ((label (? package? package) outputs ...) | 751 | ((label (? package? package) outputs ...) |
| 756 | (match (assq-ref replacements package) | 752 | (let ((proc (if (cut? package) proc replace))) |
| 757 | (#f (cons* label (replace package) outputs)) | 753 | (cons* label (proc package) outputs))) |
| 758 | (new (cons* label new outputs)))) | ||
| 759 | (_ | 754 | (_ |
| 760 | input))) | 755 | input))) |
| 761 | 756 | ||
| 762 | (define replace | 757 | (define replace |
| 763 | (mlambdaq (p) | 758 | (mlambdaq (p) |
| 764 | ;; Return a variant of P with its inputs rewritten. | 759 | ;; Return a variant of P with PROC applied to P and its explicit |
| 765 | (package | 760 | ;; dependencies, recursively. Memoize the transformations. Failing to |
| 766 | (inherit p) | 761 | ;; do that, we would build a huge object graph with lots of duplicates, |
| 767 | (name (rewrite-name (package-name p))) | 762 | ;; which in turns prevents us from benefiting from memoization in |
| 768 | (inputs (map rewrite (package-inputs p))) | 763 | ;; 'package-derivation'. |
| 769 | (native-inputs (map rewrite (package-native-inputs p))) | 764 | (let ((p (proc p))) |
| 770 | (propagated-inputs (map rewrite (package-propagated-inputs p)))))) | 765 | (package |
| 766 | (inherit p) | ||
| 767 | (location (package-location p)) | ||
| 768 | (inputs (map rewrite (package-inputs p))) | ||
| 769 | (native-inputs (map rewrite (package-native-inputs p))) | ||
| 770 | (propagated-inputs (map rewrite (package-propagated-inputs p))))))) | ||
| 771 | 771 | ||
| 772 | replace) | 772 | replace) |
| 773 | 773 | ||
| 774 | (define* (package-input-rewriting replacements | ||
| 775 | #:optional (rewrite-name identity)) | ||
| 776 | "Return a procedure that, when passed a package, replaces its direct and | ||
| 777 | indirect dependencies (but not its implicit inputs) according to REPLACEMENTS. | ||
| 778 | REPLACEMENTS is a list of package pairs; the first element of each pair is the | ||
| 779 | package to replace, and the second one is the replacement. | ||
| 780 | |||
| 781 | Optionally, REWRITE-NAME is a one-argument procedure that takes the name of a | ||
| 782 | package and returns its new name after rewrite." | ||
| 783 | (define (rewrite p) | ||
| 784 | (match (assq-ref replacements p) | ||
| 785 | (#f (package | ||
| 786 | (inherit p) | ||
| 787 | (name (rewrite-name (package-name p))))) | ||
| 788 | (new new))) | ||
| 789 | |||
| 790 | (package-mapping rewrite (cut assq <> replacements))) | ||
| 791 | |||
| 774 | 792 | ||
| 775 | ;;; | 793 | ;;; |
| 776 | ;;; Package derivations. | 794 | ;;; Package derivations. |
diff --git a/tests/packages.scm b/tests/packages.scm index 51dc1ba2b0c..930374dabfa 100644 --- a/tests/packages.scm +++ b/tests/packages.scm | |||
| @@ -886,6 +886,33 @@ | |||
| 886 | (and (build-derivations %store (list drv)) | 886 | (and (build-derivations %store (list drv)) |
| 887 | (file-exists? (string-append out "/bin/make"))))))) | 887 | (file-exists? (string-append out "/bin/make"))))))) |
| 888 | 888 | ||
| 889 | (test-equal "package-mapping" | ||
| 890 | 42 | ||
| 891 | (let* ((dep (dummy-package "chbouib" | ||
| 892 | (native-inputs `(("x" ,grep))))) | ||
| 893 | (p0 (dummy-package "example" | ||
| 894 | (inputs `(("foo" ,coreutils) | ||
| 895 | ("bar" ,grep) | ||
| 896 | ("baz" ,dep))))) | ||
| 897 | (transform (lambda (p) | ||
| 898 | (package (inherit p) (source 42)))) | ||
| 899 | (rewrite (package-mapping transform)) | ||
| 900 | (p1 (rewrite p0))) | ||
| 901 | (and (eq? p1 (rewrite p0)) | ||
| 902 | (eqv? 42 (package-source p1)) | ||
| 903 | (match (package-inputs p1) | ||
| 904 | ((("foo" dep1) ("bar" dep2) ("baz" dep3)) | ||
| 905 | (and (eq? dep1 (rewrite coreutils)) ;memoization | ||
| 906 | (eq? dep2 (rewrite grep)) | ||
| 907 | (eq? dep3 (rewrite dep)) | ||
| 908 | (eqv? 42 | ||
| 909 | (package-source dep1) (package-source dep2) | ||
| 910 | (package-source dep3)) | ||
| 911 | (match (package-native-inputs dep3) | ||
| 912 | ((("x" dep)) | ||
| 913 | (and (eq? dep (rewrite grep)) | ||
| 914 | (package-source dep)))))))))) | ||
| 915 | |||
| 889 | (test-assert "package-input-rewriting" | 916 | (test-assert "package-input-rewriting" |
| 890 | (let* ((dep (dummy-package "chbouib" | 917 | (let* ((dep (dummy-package "chbouib" |
| 891 | (native-inputs `(("x" ,grep))))) | 918 | (native-inputs `(("x" ,grep))))) |
