Support bundling nixos configurations

This commit is contained in:
Tim Van Baak 2024-07-28 20:09:17 -07:00
parent aae8892a4a
commit 079d222614
2 changed files with 73 additions and 44 deletions

View File

@ -3,8 +3,11 @@ let
inherit (builtins) inherit (builtins)
genericClosure genericClosure
hasAttr hasAttr
head
length length
map map
match
tail
; ;
inherit (pkgs) runCommandLocal writeText; inherit (pkgs) runCommandLocal writeText;
inherit (pkgs.lib) inherit (pkgs.lib)
@ -19,18 +22,32 @@ let
; ;
in in
rec { rec {
drvOutputs = drv: if hasAttr "outputs" drv then map (out: drv.${out}) drv.outputs else [ drv ]; # Map a drv or list of drvs to a list of output drvs
drvOutputs = drv:
if isList drv then
concatMap drvOutputs drv
else if hasAttr "outputs" drv then
map (out: drv.${out}) drv.outputs
else [ drv ];
# Map a drv or list of drvs to the outputs of referenced derivations
drvDeps = drvDeps =
drv: drv:
mapAttrsToList ( if isList drv then
k: v: concatMap drvDeps drv
if isDerivation v then else
(drvOutputs v) mapAttrsToList (
else if isList v then k: v:
concatMap drvOutputs (filter isDerivation v) if isDerivation v then
else (drvOutputs v)
[ ] else if isList v then
) drv; concatMap drvOutputs (filter isDerivation v)
else
[ ]
) drv;
# Get the reference closure of a derivation or list of derivations
# This may miss dependencies that are only in-closure from string context
drvClosure = drvClosure =
let let
wrap = drv: { wrap = drv: {
@ -43,50 +60,58 @@ rec {
startSet = map wrap (drvOutputs drv); startSet = map wrap (drvOutputs drv);
operator = obj: map wrap (concatLists (drvDeps obj.drv.drvAttrs)); operator = obj: map wrap (concatLists (drvDeps obj.drv.drvAttrs));
}); });
maintainable = drv: hasAttr "meta" drv && hasAttr "maintainers" drv.meta; maintainable = drv: hasAttr "meta" drv && hasAttr "maintainers" drv.meta;
drvMaintainers = drv: if maintainable drv then drv.meta.maintainers else [ ]; drvMaintainers = drv: if maintainable drv then drv.meta.maintainers else [ ];
nobodyMaintains =
drv: hasAttr "meta" drv && hasAttr "maintainers" drv.meta && (length drv.meta.maintainers) == 0; # Construct a link to a derivation's source in github:NixOS/nixpkgs
drvSource = drv:
let
parts = match "/nix/store/[^/]+/(.*):([0-9]*)" drv.meta.position;
in
if hasAttr "meta" drv && hasAttr "position" drv.meta then
"https://github.com/NixOS/nixpkgs/blob/master/${head parts}#L${head (tail parts)}"
else
"";
mainInfo = drv: {
name = drv.name;
maintainers = map (main: toString main.github) (drvMaintainers drv);
source = drvSource drv;
};
stringJoin = objToString: objs: writeText "txt" (concatLines (map objToString objs)); stringJoin = objToString: objs: writeText "txt" (concatLines (map objToString objs));
closureInfo = drv: map mainInfo (filter maintainable (drvClosure drv));
allMaintainers = allMaintainers =
drv: drv:
let let
closure = drvClosure drv; info = closureInfo drv;
maintainers = concatMap drvMaintainers closure; infoToString = info: "${info.name} ${concatStringsSep "," info.maintainers}";
mainToString = m: "${m.name} (${m.email})";
in in
runCommandLocal "uniq-maintainers.txt" { } '' runCommandLocal "all-maintainers.txt" { } ''
<${stringJoin mainToString maintainers} sort | uniq -c > $out <${stringJoin infoToString info} sort -u | ${pkgs.unixtools.column}/bin/column -t > $out
''; '';
noMaintainers = noMaintainers =
drv: drv:
let let
closure = drvClosure drv; info = closureInfo drv;
unmaintained = filter nobodyMaintains closure; unmaintained = filter (info: (length info.maintainers) == 0) info;
drvToString = drv: "${drv.name} ${drv.meta.position}"; infoToString = info: "${info.name} ${info.source}";
in in
runCommandLocal "no-maintainers.txt" { } '' runCommandLocal "unmaintained.txt" { } ''
<${stringJoin drvToString unmaintained} sort -u \ <${stringJoin infoToString unmaintained} sort -u | ${pkgs.unixtools.column}/bin/column -t > $out
| sed 's/\/nix\/store\/[^/]*/https:\/\/github.com\/NixOS\/nixpkgs\/blob\/master/' \
| sed 's/.nix:\(.*\)$/.nix#L\1/' \
| ${pkgs.unixtools.column}/bin/column -t \
> $out
''; '';
listMaintainers = expandInput =
drv: input:
let if (input.class or null == "nixos") && (input._type or null == "configuration") then
closure = drvClosure drv; [
maintainableDrvs = filter maintainable closure; input.config.system.build.toplevel
maintainersToString = input.config.environment.systemPackages
maintainers: concatStringsSep "," (map (main: toString main.github) maintainers); ]
drvToString = drv: "${drv.name} ${maintainersToString (drvMaintainers drv)}"; else
in input;
runCommandLocal "maintainers.txt" { } ''
<${stringJoin drvToString maintainableDrvs} sort -u \
| ${pkgs.unixtools.column}/bin/column -t \
> $out
'';
} }

View File

@ -5,13 +5,17 @@
system = "x86_64-linux"; system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
lib = import ./default.nix { inherit pkgs; }; lib = import ./default.nix { inherit pkgs; };
inherit (lib)
allMaintainers
expandInput
noMaintainers
;
in in
{ {
bundlers."x86_64-linux" = rec { bundlers."x86_64-linux" = rec {
default = adopt; default = unmaintained;
maintainers = lib.allMaintainers; all = drv: allMaintainers (expandInput drv);
adopt = lib.noMaintainers; unmaintained = drv: noMaintainers (expandInput drv);
list = lib.listMaintainers;
}; };
formatter."x86_64-linux" = pkgs.nixfmt-rfc-style; formatter."x86_64-linux" = pkgs.nixfmt-rfc-style;