Let’s say there is an overlay, which adds some extra packages and overrides some others. How can I compute the packages that were added or modified? Basically I want to know the difference set between the sets, i.e: nixpkgs_{overlays} \ nixpkgs.
I would like to use this function as entry point for Hydra: I’m only interested in the added/modified packages and I don’t want to rebuild all nixpkgs.
Presumably, filterAttrs
or filterAttrsRecursive
with a predicate searching if an attribute is contained in an attrset would be very slow/inefficient, because it had to evaluate all packages.
Comparing only the attrNames
for filtering removes overhead for computing the attr values, but is not granular enough in case a nested attribute is changed. For example, overlayPkgs
below contains the entire libsForQt5
and not only libsForQt5.pkg2
.
let
drv =
{ stdenv, name }:
stdenv.mkDerivation (finalAttrs: {
inherit name;
buildCommand = ''
mkdir -p $out
touch $out/${finalAttrs.name}
'';
});
overlays = [(self: super: with self; {
pkg1 = callPackage drv { name = "pkg1"; };
libsForQt5 = super.libsForQt5 // {
pkg2 = callPackage drv { name = "pkg2"; };
};
})];
nixpkgs' = (import <nixpkgs> { inherit overlays; }).pkgs;
# approach with attrNames:
inherit (nixpkgs'.lib) flatten filterAttrs;
inherit (builtins) map attrNames elem;
overlayPkgs = overlays: flatten (map (overlay: attrNames (overlay {} {})) overlays);
in {
# pkgs with overlays
pkgs' = nixpkgs';
# good: fast
# bad: contains the entire libsForQt5 instead of only libsForQt5.pkg2
overlay-pkgs = filterAttrs (n: v: elem n (overlayPkgs overlays)) nixpkgs';
}