2024-06-01 11:00:53 +00:00
|
|
|
let
|
|
|
|
files = [
|
|
|
|
./attrs
|
|
|
|
./bools
|
|
|
|
./errors
|
|
|
|
./fp
|
|
|
|
./generators
|
|
|
|
./importers
|
2024-06-05 02:04:40 +00:00
|
|
|
./licenses
|
2024-06-01 11:00:53 +00:00
|
|
|
./lists
|
|
|
|
./math
|
|
|
|
./modules
|
|
|
|
./numbers
|
|
|
|
./options
|
|
|
|
./packages
|
|
|
|
./paths
|
|
|
|
./points
|
|
|
|
./strings
|
|
|
|
./types
|
|
|
|
./versions
|
|
|
|
];
|
|
|
|
|
|
|
|
libs = builtins.map (f: import f) files;
|
|
|
|
|
|
|
|
## Calculate the fixed point of a function. This will evaluate the function `f`
|
|
|
|
## until its result settles (or Nix's recursion limit is reached). This allows
|
|
|
|
## us to define recursive functions without worrying about the order of their
|
|
|
|
## definitions.
|
|
|
|
##
|
|
|
|
## @type (a -> a) -> a
|
|
|
|
fix = f: let
|
|
|
|
x = f x;
|
|
|
|
in
|
|
|
|
x;
|
|
|
|
|
|
|
|
## Merge two attribute sets recursively until a given predicate returns true.
|
|
|
|
## Any values that are _not_ attribute sets will be overridden with the value
|
|
|
|
## from `y` first if it exists and then `x` otherwise.
|
|
|
|
##
|
|
|
|
## @type Attrs a b c => (String -> Any -> Any -> Bool) -> a -> b -> c
|
|
|
|
mergeAttrsRecursiveUntil = predicate: x: y: let
|
|
|
|
process = path:
|
|
|
|
builtins.zipAttrsWith (
|
2024-06-03 09:57:13 +00:00
|
|
|
name: values: let
|
|
|
|
currentPath = path ++ [name];
|
2024-06-01 11:00:53 +00:00
|
|
|
isSingleValue = builtins.length values == 1;
|
|
|
|
isComplete =
|
|
|
|
predicate currentPath
|
|
|
|
(builtins.elemAt values 1)
|
|
|
|
(builtins.elemAt values 0);
|
|
|
|
in
|
|
|
|
if isSingleValue || isComplete
|
|
|
|
then builtins.elemAt values 0
|
|
|
|
else process currentPath values
|
|
|
|
);
|
|
|
|
in
|
|
|
|
process [] [x y];
|
|
|
|
|
|
|
|
## Merge two attribute sets recursively. Any values that are _not_ attribute sets
|
|
|
|
## will be overridden with the value from `y` first if it exists and then `x`
|
|
|
|
## otherwise.
|
|
|
|
##
|
|
|
|
## @type Attrs a b c => a -> b -> c
|
|
|
|
mergeAttrsRecursive =
|
|
|
|
mergeAttrsRecursiveUntil
|
|
|
|
(path: x: y:
|
|
|
|
!(builtins.isAttrs x && builtins.isAttrs y));
|
|
|
|
|
|
|
|
lib = fix (
|
|
|
|
self: let
|
|
|
|
merge = acc: create:
|
|
|
|
mergeAttrsRecursive acc (create self);
|
|
|
|
in
|
|
|
|
builtins.foldl' merge {} libs
|
|
|
|
);
|
|
|
|
in
|
|
|
|
lib
|