Skip to content

Commit

Permalink
nixos/top-level: improve replaceRuntimeDependencies
Browse files Browse the repository at this point in the history
Instead of iterating over all replacements and applying them one by one,
use the newly introduced replaceDependencies function to apply them all
at once for replaceRuntimeDependencies. The advantages are twofold in
case there are multiple replacements:
* Performance is significantly improved, because there is only one pass
  over the closure to be made.
* Correctness is improved, because replaceDependencies also replaces
  dependencies of the replacements themselves if applicable.

Fixes: NixOS#4336
  • Loading branch information
alois31 authored and bryango committed Feb 23, 2024
1 parent 44a2e03 commit 85f9129
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 17 deletions.
12 changes: 9 additions & 3 deletions nixos/modules/system/activation/top-level.nix
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,15 @@ let
else showWarnings config.warnings baseSystem;

# Replace runtime dependencies
system = foldr ({ oldDependency, newDependency }: drv:
pkgs.replaceDependency { inherit oldDependency newDependency drv; }
) baseSystemAssertWarn config.system.replaceRuntimeDependencies;
system = let replacements = config.system.replaceRuntimeDependencies; in
if replacements == [] then
# Avoid IFD if possible, by sidestepping replaceDependencies if no replacements are specified.
baseSystemAssertWarn
else
pkgs.replaceDependencies {
drv = baseSystemAssertWarn;
inherit replacements;
};

systemWithBuildDeps = system.overrideAttrs (o: {
systemBuildClosure = pkgs.closureInfo { rootPaths = [ system.drvPath ]; };
Expand Down
29 changes: 15 additions & 14 deletions pkgs/build-support/replace-dependencies.nix
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ let
inherit (builtins) unsafeDiscardStringContext appendContext;
inherit (lib)
trace substring stringLength concatStringsSep mapAttrsToList listToAttrs
attrValues mapAttrs filter hasAttr attrNames all;
attrValues mapAttrs filter hasAttr all;
inherit (lib.attrsets) mergeAttrsList;

toContextlessString = x: unsafeDiscardStringContext (toString x);
Expand Down Expand Up @@ -114,19 +114,20 @@ let
else
true) replacements;

rewriteMemo = mapAttrs (drv: references:
let
rewrittenReferences =
filter (dep: dep != drv && toString rewriteMemo.${dep} != dep)
references;
rewrites = listToAttrs (map (reference: {
name = reference;
value = rewriteMemo.${reference};
}) rewrittenReferences);
# Mind the order of how the three attrsets are merged here.
# The order of precedence needs to be "explicitly specified replacements" > "rewrite exclusion (cutoffPackages)" > "rewrite".
# So the attrset merge order is the opposite.
in rewriteHashes storePathOrKnownDerivationMemo.${drv} rewrites)
rewriteMemo =
# Mind the order of how the three attrsets are merged here.
# The order of precedence needs to be "explicitly specified replacements" > "rewrite exclusion (cutoffPackages)" > "rewrite".
# So the attrset merge order is the opposite.
mapAttrs (drv: references:
let
rewrittenReferences =
filter (dep: dep != drv && toString rewriteMemo.${dep} != dep)
references;
rewrites = listToAttrs (map (reference: {
name = reference;
value = rewriteMemo.${reference};
}) rewrittenReferences);
in rewriteHashes storePathOrKnownDerivationMemo.${drv} rewrites)
relevantReferences // listToAttrs (map (drv: {
name = toContextlessString drv;
value = storePathOrKnownDerivationMemo.${toContextlessString drv};
Expand Down

0 comments on commit 85f9129

Please sign in to comment.