improve overrides:

- make overrides referenceable
  - automatically detect override functions for attributes
This commit is contained in:
DavHau 2021-10-30 19:23:47 +07:00
parent d20f318b58
commit 120b2d0ee0
3 changed files with 91 additions and 29 deletions

View File

@ -87,7 +87,7 @@ let
};
};
in
built.package;
built.defaultPackage;
makePackage = name: version:
let

View File

@ -12,8 +12,8 @@
externalSources ?
lib.genAttrs
(lib.attrNames (builtins.readDir externalDir))
(inputName: "${externalDir}/${inputName}"),
(lib.attrNames (builtins.readDir externalDir))
(inputName: "${externalDir}/${inputName}"),
# required for non-flake mode
externalDir ?

View File

@ -6,21 +6,34 @@ let
b = builtins;
exampleOverrides = {
hello = [
{
description = "patch hello";
condition = pkg: if pkg.version > 3.0.0 then true else false;
overrideAttrs = old: {
patches = [];
throwErrorUnclearAttributeOverride = pname: overrideName: attrName:
throw ''
Error while applying override for ${pname}: '${overrideName}'
There are multiple override functions accepting an argument named '${attrName}'.
Please modify the override to clarify which override function should be used.
Instead of:
```
"${pname}" = {
"${overrideName}" = {
...
${attrName} = ...;
...
};
};
override = old: {
withPython = false;
```
Use:
```
"${pname}" = {
"${overrideName}" = {
...
overrideAttrs = oldAttrs: {
${attrName} = ...;
};
...
};
};
}
];
};
```
'';
applyOverridesToPackage = conditionalOverrides: pkg: pname:
if ! conditionalOverrides ? "${pname}" then
@ -31,16 +44,30 @@ let
# if condition is unset, it will be assumed true
evalCondition = condOverride: pkg:
if condOverride ? condition then
condOverride.condition pkg
if condOverride ? _condition then
condOverride._condition pkg
else
true;
# filter the overrides by the package name and conditions
overridesToApply =
(lib.filter
(condOverride: evalCondition condOverride pkg)
conditionalOverrides."${pname}");
let
overridesForPackage = conditionalOverrides."${pname}";
overridesListForPackage =
lib.mapAttrsToList
(_name: data: data // { inherit _name; })
overridesForPackage;
in
(lib.filter
(condOverride: evalCondition condOverride pkg)
overridesListForPackage);
# apply single attribute override
applySingleAttributeOverride = oldVal: functionOrValue:
if b.isFunction functionOrValue then
functionOrValue oldVal
else
functionOrValue;
# helper to apply one conditional override
# the condition is not evaluated anymore here
@ -48,8 +75,46 @@ let
let
overrideFuncs =
lib.mapAttrsToList
(funcName: func: { inherit funcName func; })
(lib.filterAttrs (n: v: lib.hasPrefix "override" n) condOverride);
(funcName: func: { inherit funcName func; })
(lib.filterAttrs (n: v: lib.hasPrefix "override" n) condOverride);
singleArgOverrideFuncs =
let
availableFunctions =
lib.mapAttrs
(funcName: func: lib.attrNames (lib.functionArgs func))
(lib.filterAttrs
(funcName: func: lib.hasPrefix "override" funcName)
pkg);
getOverrideFuncNameForAttrName = attrName:
let
applicableFuncs =
lib.attrNames
(lib.filterAttrs
(funcName: args: b.elem attrName args)
availableFunctions);
in
if b.length applicableFuncs == 0 then
"overrideAttrs"
else if b.length applicableFuncs >= 1 then
throwErrorUnclearAttributeOverride pname condOverride._name attrName
else
b.elemAt applicableFuncs 0;
attributeOverrides =
lib.filterAttrs
(n: v: ! lib.hasPrefix "override" n && ! lib.hasPrefix "_" n)
condOverride;
in
lib.mapAttrsToList
(attrName: funcOrValue: {
funcName = getOverrideFuncNameForAttrName attrName;
func = oldAttrs: { "${attrName}" = funcOrValue; };
})
attributeOverrides;
in
b.foldl'
(pkg: overrideFunc:
@ -59,14 +124,11 @@ let
updateAttrsFuncs = overrideFunc.func old;
in
lib.mapAttrs
(attrName: maybeFunction:
if b.isFunction maybeFunction then
maybeFunction old."${attrName}"
else
maybeFunction)
(attrName: functionOrValue:
applySingleAttributeOverride old."${attrName}" functionOrValue)
updateAttrsFuncs))
pkg
overrideFuncs;
(overrideFuncs ++ singleArgOverrideFuncs);
in
# apply the overrides to the given pkg
(lib.foldl