Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos/nixpkgs: add override/merging capabilities from the module system to the nixpkgs.config option #80582

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
75 changes: 50 additions & 25 deletions nixos/modules/misc/nixpkgs.nix
Expand Up @@ -14,32 +14,57 @@ let
then f x
else f;

mergeConfig = lhs_: rhs_:
let
lhs = optCall lhs_ { inherit pkgs; };
rhs = optCall rhs_ { inherit pkgs; };
in
recursiveUpdate lhs rhs //
optionalAttrs (lhs ? packageOverrides) {
packageOverrides = pkgs:
optCall lhs.packageOverrides pkgs //
optCall (attrByPath ["packageOverrides"] ({}) rhs) pkgs;
} //
optionalAttrs (lhs ? perlPackageOverrides) {
perlPackageOverrides = pkgs:
optCall lhs.perlPackageOverrides pkgs //
optCall (attrByPath ["perlPackageOverrides"] ({}) rhs) pkgs;
};

configType = mkOptionType {
mergableConfigType = mkOptionType {
name = "nixpkgs-config";
description = "nixpkgs config";
check = x:
let traceXIfNot = c:
if c x then true
else lib.traceSeqN 1 x false;
in traceXIfNot isConfig;
merge = args: fold (def: mergeConfig def.value) {};
check = isConfig;
merge = loc: defs:
let
# Ensure that each attribute from nixpkgs.config appears at the
# first iteration to make sure that nothing is lost.
allValues = fold recursiveUpdate {} defs;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm aware that this is a gross hack to make sure that any attr-names that are defined in any moduel taken into account is known to the merger. Are there any suggestions for a better workaround? :)


# Recurses through the `config` attr-set for nixpkgs and ensures that
# no conflicting definitions exist and that overrides are resolved properly.
mapFun = path: value:
if isAttrs value && !(value ? _type) then value
else let
# Evaluate mkIf/mkMerge with `lib.dischargeProperties` and append the
# value to the list of declarations. If a value is `null`, it means that
# it was not declared in one of the configs and can be ignored.
appendVal = all: value_: next:
let
# FIXME support `mkMerge [{ snens = mkIf cond val; }]`
discharged = dischargeProperties value_;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in the comment, mk{If,Merge,Before,...} aren't evaluated inside a mkMerge (mkMerge [ (mkIf cond { /* ... */ } ]) works fine though). IMHO this would make the code even more complex, but are there any suggestions how fix this? :)

# FIXME check if there's a case where `discharged` is `[]` and
# therefore breaks `head`.
value = let h = head discharged; in if isAttrs h
then foldl recursiveUpdate {} discharged
else h;
in all ++ (if value == null then [] else [{
inherit (next) file;
inherit value;
}]);

# Gather all declarations of a value in the `nixpkgs.config` attr-set.
allDeclarations = foldl
(all: next: appendVal all (optCall (attrByPath path null next) finalPkgs) next)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The optCall in the recursive mapAttrs replaces the merging behavior for {perlP,p}ackageOverrides. Please note that I'm now using finalPkgs rather than pkgs as this seems more appropriate to me (since finalPkgs also takes overlays into account). If this is a wrong decision, please let me know, we probably might want to use pkgs rather than finalPkgs here.

[]
defs;

# Evaluate all overrides (defined using mkOverride/mkForce/etc) and pick the
# value with the highes priority.
result = sortProperties (filterOverrides allDeclarations);

# Merge all declarations (if a list or an attr-set is given, those can be merged together),
# if a "unique" value is given, it's ensured that no conflicting definitions exist.
#
# FIXME This is missing support for separatedString!
merge = let h = (head result).value or null; in
if isList h || isAttrs h then mergeDefaultOption else mergeOneOption;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in the comment, separatedString doesn't work here. As recursiveUpdate did silent overrides, this never worked before, but are there any suggestions how to fix this as well? :)

in
merge (["nixpkgs" "config"] ++ (tail path)) result;
in mapAttrsRecursiveCond (x: !(x ? _type)) mapFun allValues;
};

overlayType = mkOptionType {
Expand Down Expand Up @@ -113,7 +138,7 @@ in
''
{ allowBroken = true; allowUnfree = true; }
'';
type = configType;
type = mergableConfigType;
description = ''
The configuration of the Nix Packages collection. (For
details, see the Nixpkgs documentation.) It allows you to set
Expand Down