summaryrefslogtreecommitdiffstats
path: root/lib
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 /lib
parentbacdeffd804c1da6700d2ab424cf2b74ca7e5355 (diff)
lib: Add composeManyExtensions
Diffstat (limited to 'lib')
-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 d2239d26eadf..e3c1ed713463 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 968930526a63..f998bc74e1db 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 6175f15819a7..35a5801c724f 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;