summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoe Hermaszewski <git@monoid.al>2020-11-11 10:36:19 +0800
committerPeter Simons <simons@cryp.to>2020-11-13 21:37:57 +0100
commitc3b35f21f78a3d23aaf40b70fe8865598ddc6729 (patch)
treecb243bc900a386be28cb73dd437f8f7aaa44cc97
parentbacdeffd804c1da6700d2ab424cf2b74ca7e5355 (diff)
downloadnixpkgs-c3b35f21f78a3d23aaf40b70fe8865598ddc6729.tar
nixpkgs-c3b35f21f78a3d23aaf40b70fe8865598ddc6729.tar.gz
nixpkgs-c3b35f21f78a3d23aaf40b70fe8865598ddc6729.tar.bz2
nixpkgs-c3b35f21f78a3d23aaf40b70fe8865598ddc6729.tar.lz
nixpkgs-c3b35f21f78a3d23aaf40b70fe8865598ddc6729.tar.xz
nixpkgs-c3b35f21f78a3d23aaf40b70fe8865598ddc6729.tar.zst
nixpkgs-c3b35f21f78a3d23aaf40b70fe8865598ddc6729.zip
lib: Add composeManyExtensions
-rw-r--r--lib/default.nix4
-rw-r--r--lib/fixed-points.nix11
-rw-r--r--lib/tests/misc.nix20
3 files changed, 32 insertions, 3 deletions
diff --git a/lib/default.nix b/lib/default.nix
index d2239d26ead..e3c1ed71346 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -5,7 +5,7 @@
  */
 let
 
-  inherit (import ./fixed-points.nix {}) makeExtensible;
+  inherit (import ./fixed-points.nix { inherit lib; }) makeExtensible;
 
   lib = makeExtensible (self: let
     callLibs = file: import file { lib = self; };
@@ -69,7 +69,7 @@ let
       importJSON importTOML warn info showWarnings nixpkgsVersion version mod compare
       splitByAndCompare functionArgs setFunctionArgs isFunction toHexString toBaseDigits;
     inherit (self.fixedPoints) fix fix' converge extends composeExtensions
-      makeExtensible makeExtensibleWithCustomName;
+      composeManyExtensions makeExtensible makeExtensibleWithCustomName;
     inherit (self.attrsets) attrByPath hasAttrByPath setAttrByPath
       getAttrFromPath attrVals attrValues getAttrs catAttrs filterAttrs
       filterAttrsRecursive foldAttrs collect nameValuePair mapAttrs
diff --git a/lib/fixed-points.nix b/lib/fixed-points.nix
index 968930526a6..f998bc74e1d 100644
--- a/lib/fixed-points.nix
+++ b/lib/fixed-points.nix
@@ -1,4 +1,4 @@
-{ ... }:
+{ lib, ... }:
 rec {
   # Compute the fixed point of the given function `f`, which is usually an
   # attribute set that expects its final, non-recursive representation as an
@@ -77,6 +77,15 @@ rec {
           super' = super // fApplied;
       in fApplied // g self super';
 
+  # Compose several extending functions of the type expected by 'extends' into
+  # one where changes made in preceding functions are made available to
+  # subsequent ones.
+  #
+  # composeManyExtensions : [packageSet -> packageSet -> packageSet] -> packageSet -> packageSet -> packageSet
+  #                          ^final        ^prev         ^overrides     ^final        ^prev         ^overrides
+  composeManyExtensions =
+    lib.foldr (x: y: composeExtensions x y) (self: super: {});
+
   # Create an overridable, recursive attribute set. For example:
   #
   #     nix-repl> obj = makeExtensible (self: { })
diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix
index 6175f15819a..35a5801c724 100644
--- a/lib/tests/misc.nix
+++ b/lib/tests/misc.nix
@@ -87,6 +87,26 @@ runTests {
     expected = true;
   };
 
+  testComposeManyExtensions0 = {
+    expr = let obj = makeExtensible (self: { foo = true; });
+               emptyComposition = composeManyExtensions [];
+               composed = obj.extend emptyComposition;
+           in composed.foo;
+    expected = true;
+  };
+
+  testComposeManyExtensions =
+    let f = self: super: { bar = false; baz = true; };
+        g = self: super: { bar = super.baz or false; };
+        h = self: super: { qux = super.bar or false; };
+        obj = makeExtensible (self: { foo = self.qux; });
+    in {
+    expr = let composition = composeManyExtensions [f g h];
+               composed = obj.extend composition;
+           in composed.foo;
+    expected = (obj.extend (composeExtensions f (composeExtensions g h))).foo;
+  };
+
   testBitAnd = {
     expr = (bitAnd 3 10);
     expected = 2;