-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,10 @@ | |
|
||
, crossSystem ? null | ||
, platform ? null | ||
|
||
# This should be set to false when used by stdenv functions, which in the | ||
# end should not rely imports of this file. | ||
, useQuickfix ? true | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
nbp
Author
Owner
|
||
}: | ||
|
||
|
||
|
@@ -105,6 +109,135 @@ let | |
then self: super: config.packageOverrides super | ||
else self: super: {}; | ||
|
||
# Apply ABI compatible fixes, recompile every program with the | ||
# dependencies from the super set only and apply patches on the remaining | ||
# packages. This will recompile only programs which have changed in the | ||
# quickfix. | ||
abiCompatiblePatches = pkgs: | ||
if useQuickfix && builtins.pathExists ../../quickfix/pkgs/top-level/all-packages.nix then with lib; | ||
# assert builtins.trace "!!! Apply abiCompatiblePatches !!!" true; | ||
let | ||
# Evaluate the set of packages from the quickfix index, with the | ||
# list of fixed-point packages. These packages are unlikely to be | ||
# too different than the original list of packages, thus these | ||
# expressions should lead most of the time the same result as the | ||
# fixed point. | ||
quickfixPkgs = import ../../quickfix/pkgs/top-level/all-packages.nix; | ||
quickFixPkgsFun = deps: | ||
let | ||
pkgs_ = quickfixPkgs { | ||
self = deps; # Do no recurse here. | ||
This comment has been minimized.
Sorry, something went wrong.
Mathnerd314
|
||
pkgs = deps; | ||
defaultScope = deps // deps.xorg; # Do not recurse here. | ||
inherit system crossSystem platform bootStdenv noSysDirs | ||
gccWithCC gccWithProfiling config; | ||
}; | ||
in pkgs_.stdenvAdapters // pkgs_.trivial-builders // pkgs_; | ||
|
||
patchDependencies = drv: hashesMap: pkgs.runCommand "quickfix-${drv.name}" { nixStore = "${pkgs.nix}/bin/nix-store"; } '' | ||
$nixStore --dump ${drv} | sed 's|${baseNameOf drv}|'$(basename $out)'|g;${ | ||
concatStrings (mapAttrsToList (name: value: | ||
"'s|${baseNameOf name}|${baseNameOf value}|g';" | ||
) hashesMap) | ||
} | $nixStore --restore $out | ||
''; | ||
|
||
# For each package, we check if we have the same dependencies. | ||
quickFixAsPatches = name: pkgs: quickfix: whatif: | ||
This comment has been minimized.
Sorry, something went wrong. |
||
let | ||
# Note, we need to check the drv.outPath to add some strictness | ||
# to eliminate derivation which might assert when they are | ||
# evaluated. | ||
validDeps = name: drv: | ||
let res = builtins.tryEval (isDerivation drv && isString drv.outPath); in | ||
name != "_currentPackage" && res.success && res.value; | ||
This comment has been minimized.
Sorry, something went wrong.
Mathnerd314
|
||
|
||
differentDeps = x: | ||
# assert __trace "differentDeps: ${x.name}\n : : ${x.value} ?" true; | ||
x.name != x.value; | ||
|
||
# Based on the derivation, get the list of dependencies. | ||
# | ||
# :TODO: Optimize this function by only using runtime | ||
# dependencies of the original package set, and which are | ||
# computed ahead by the buildfamr. | ||
getDeps = drv: | ||
if drv ? originalArgs then filterAttrs validDeps drv.originalArgs | ||
else assert __trace "Security issue: Unable to locate dependencies of `${name}`." true; {}; | ||
|
||
# This assumes that the originalArgs list are ordered the same | ||
# way, as they are both infered from the same files. | ||
hashesAssocList = | ||
let qDeps = getDeps quickfix; wDeps = getDeps whatif; in | ||
let names = attrNames qDeps; in | ||
# assert __trace "qDeps: ${toString (attrNames qDeps)}\ntrace: wDeps: ${toString (attrNames wDeps)}" true; | ||
assert names == attrNames wDeps; | ||
filter differentDeps (map (name: { | ||
name = builtins.unsafeDiscardStringContext (toString qDeps.${name}); | ||
value = toString wDeps.${name}; | ||
}) names); | ||
|
||
# If the name of the quickfix does not have the same | ||
# length, use the old name instead. This might cause a | ||
# problem if people do not use --leq while updating. | ||
quickfixRenamed = | ||
if stringLength pkgs.name == stringLength quickfix.name | ||
then quickfix | ||
else | ||
overrideDerivation quickfix ({ | ||
name = pkgs.name; | ||
}); | ||
in | ||
if length hashesAssocList != 0 then | ||
# One of the dependency is different. | ||
#throw "Is about to patch ${name}, because of ${showVal (listToAttrs hashesAssocList)}." | ||
patchDependencies quickfixRenamed (listToAttrs hashesAssocList) | ||
else | ||
quickfixRenamed; | ||
|
||
# Recursively decent into all packages until we reach a derivation, | ||
# in which case we execute the "f" function, otherwise, if we cannot | ||
# decide, such as in case of functions, then we execute the | ||
# "default" function with both arguments. | ||
zipQuickFixAsPatches = path: pkgs: quickfix: whatif: | ||
zipAttrsWith (name: values: | ||
# Somebody added / removed a packaged in quickfix? | ||
let pkgsName = concatStringsSep "." (path ++[name]); in | ||
# assert builtins.trace "zipQuickFixAsPatches (name: ${pkgsName})" true; | ||
assert builtins.length values == 3; | ||
let p = head values; q = head (tail values); w = head (tail (tail values)); in | ||
if name == "pkgs" then q # We should not recurse in the top-level pkgs argument. | ||
else if isAttrs p then | ||
assert isAttrs q && isAttrs w; # Do not mutate the derivation | ||
if isDerivation p then | ||
assert isDerivation q && isDerivation w; | ||
addErrorContext "While evaluating package ${pkgsName}" (quickFixAsPatches pkgsName p q w) | ||
else | ||
zipQuickFixAsPatches (path ++ [name]) p q w | ||
else | ||
q | ||
) [pkgs quickfix whatif]; | ||
|
||
# Pipeline of modification involved to apply security patches: | ||
# | ||
# 1. We apply security patches on top of the current set of packages. | ||
# | ||
# 2. We check what package would be recompiled, if we were to | ||
# recompile instead of applying patches. | ||
# | ||
# 3. We only keep the set of packages where we only applied patches. | ||
# | ||
quickFix = quickFixPkgsFun pkgs; | ||
whatIf = quickFixPkgsFun abiSec; | ||
abiSec = zipQuickFixAsPatches ["pkgs"] pkgs quickFix whatIf; | ||
in | ||
abiSec | ||
else | ||
# If there is no quickfix to apply, then there is no need for extra | ||
# overhead, in which case we just the fix-point of packages. | ||
pkgs; | ||
|
||
|
||
# The package compositions. Yes, this isn't properly indented. | ||
pkgsFun = pkgs: | ||
let | ||
|
@@ -125,4 +258,4 @@ let | |
|
||
in lib.mapAttrs tweakAlias aliases // pkgsRet; | ||
|
||
in pkgs | ||
in abiCompatiblePatches pkgs |
I don't think this is necessary, you can just check if
bootStdenv == null
, like in configOverrides.But I do agree that
bootStdenv
should go away; filed NixOS#10874.