lib.toExtension: init

Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
This commit is contained in:
Yueh-Shun Li 2024-07-04 20:37:01 +00:00
parent 6749b1c4bc
commit 11c20cd390
3 changed files with 83 additions and 1 deletions

View file

@ -79,7 +79,8 @@ let
fromHexString toHexString toBaseDigits inPureEvalMode isBool isInt pathExists fromHexString toHexString toBaseDigits inPureEvalMode isBool isInt pathExists
genericClosure readFile; genericClosure readFile;
inherit (self.fixedPoints) fix fix' converge extends composeExtensions inherit (self.fixedPoints) fix fix' converge extends composeExtensions
composeManyExtensions makeExtensible makeExtensibleWithCustomName; composeManyExtensions makeExtensible makeExtensibleWithCustomName
toExtension;
inherit (self.attrsets) attrByPath hasAttrByPath setAttrByPath inherit (self.attrsets) attrByPath hasAttrByPath setAttrByPath
getAttrFromPath attrVals attrNames attrValues getAttrs catAttrs filterAttrs getAttrFromPath attrVals attrNames attrValues getAttrs catAttrs filterAttrs
filterAttrsRecursive foldlAttrs foldAttrs collect nameValuePair mapAttrs filterAttrsRecursive foldlAttrs foldAttrs collect nameValuePair mapAttrs

View file

@ -438,4 +438,68 @@ rec {
${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs); ${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs);
} }
); );
/**
Convert to an extending function (overlay).
`toExtension` is the `toFunction` for extending functions (a.k.a. extensions or overlays).
It converts a non-function or a single-argument function to an extending function,
while returning a double-argument function as-is.
That is, it takes one of `x`, `prev: x`, or `final: prev: x`,
and returns `final: prev: x`, where `x` is not a function.
This function is extracted from the implementation of
the fixed-point arguments support of `stdenv.mkDerivation`.
It bridges the gap between `<pkg>.overrideAttrs`
before and after the overlay-style support,
as well as `config.packageOverrides` and `config.overlays` in `pkgs`.
# Inputs
`f`
: The function or non-function to convert to an extending function.
# Type
```
toExtension ::: (a | a -> a | a -> a -> a) -> a -> a -> a
a = AttrSet & !Function
```
# Examples
:::{.example}
## `lib.fixedPoints.toExtension` usage example
```nix
fix (final: { a = 0; c = final.a; })
=> { a = 0; c = 0; };
fix (extends (toExtension { a = 1; b = 2; }) (final: { a = 0; c = final.a; }))
=> { a = 1; b = 2; c = 1; };
fix (extends (toExtension (prev: { a = 1; b = prev.a; })) (final: { a = 0; c = final.a; }))
=> { a = 1; b = 0; c = 1; };
fix (extends (toExtension (final: prev: { a = 1; b = prev.a; c = final.a + 1 })) (final: { a = 0; c = final.a; }))
=> { a = 1; b = 0; c = 2; };
```
:::
*/
toExtension =
f:
if lib.isFunction f then
final: prev:
let
fPrev = f prev;
in
if lib.isFunction fPrev then
# f is (final: prev: { ... })
f final prev
else
# f is (prev: { ... })
fPrev
else
# f is { ... }
final: prev: f;
} }

View file

@ -45,6 +45,7 @@ let
const const
escapeXML escapeXML
evalModules evalModules
extends
filter filter
fix fix
fold fold
@ -102,6 +103,7 @@ let
take take
testAllTrue testAllTrue
toBaseDigits toBaseDigits
toExtension
toHexString toHexString
fromHexString fromHexString
toInt toInt
@ -1239,6 +1241,21 @@ runTests {
expected = {a = "a";}; expected = {a = "a";};
}; };
testToExtension = {
expr = [
(fix (final: { a = 0; c = final.a; }))
(fix (extends (toExtension { a = 1; b = 2; }) (final: { a = 0; c = final.a; })))
(fix (extends (toExtension (prev: { a = 1; b = prev.a; })) (final: { a = 0; c = final.a; })))
(fix (extends (toExtension (final: prev: { a = 1; b = prev.a; c = final.a + 1; })) (final: { a = 0; c = final.a; })))
];
expected = [
{ a = 0; c = 0; }
{ a = 1; b = 2; c = 1; }
{ a = 1; b = 0; c = 1; }
{ a = 1; b = 0; c = 2; }
];
};
# GENERATORS # GENERATORS
# these tests assume attributes are converted to lists # these tests assume attributes are converted to lists
# in alphabetical order # in alphabetical order