about summary refs log tree commit diff
path: root/tools
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@google.com>2019-08-11T19·10+0100
committerVincent Ambo <github@tazj.in>2019-08-13T23·02+0100
commit590ce994bb18b15c9b654c2aa426866750c3c494 (patch)
treeb72c1cb3cfc406051be951197a5194f3673b4fa1 /tools
parent92078527dbe8f853d984a4038e718c662c016741 (diff)
feat(group-layers): Add initial popcount scripts
This script generates an entry in a text file for each time a
derivation is referred to by another in nixpkgs.

For initial testing, this output can be turned into group-layers
compatible JSON with this *trivial* invocation:

cat output | awk '{ print "{\"" $2 "\":" $1 "}"}' | jq -s '. | add | with_entries(.key |= sub("/nix/store/[a-z0-9]+-";""))' > test-data.json
Diffstat (limited to 'tools')
-rwxr-xr-xtools/nixery/group-layers/popcount13
-rw-r--r--tools/nixery/group-layers/popcount.nix51
2 files changed, 64 insertions, 0 deletions
diff --git a/tools/nixery/group-layers/popcount b/tools/nixery/group-layers/popcount
new file mode 100755
index 0000000000..83baf3045d
--- /dev/null
+++ b/tools/nixery/group-layers/popcount
@@ -0,0 +1,13 @@
+#!/bin/bash
+set -ueo pipefail
+
+function graphsFor() {
+  local pkg="${1}"
+  local graphs=$(nix-build --timeout 2 --argstr target "${pkg}" popcount.nix || echo -n 'empty.json')
+  cat $graphs | jq -r -cM '.[] | .references[]'
+}
+
+for pkg in $(cat all-top-level.json | jq -r '.[]'); do
+  graphsFor "${pkg}" 2>/dev/null
+  echo "Printed refs for ${pkg}" >&2
+done
diff --git a/tools/nixery/group-layers/popcount.nix b/tools/nixery/group-layers/popcount.nix
new file mode 100644
index 0000000000..e21d736772
--- /dev/null
+++ b/tools/nixery/group-layers/popcount.nix
@@ -0,0 +1,51 @@
+{ pkgs ? import <nixpkgs> { config.allowUnfree = false; }
+, target }:
+
+let
+  inherit (pkgs) coreutils runCommand writeText;
+  inherit (builtins) replaceStrings readFile toFile fromJSON toJSON foldl' listToAttrs;
+
+  path = [ pkgs."${target}" ];
+
+  # graphJSON abuses feature in Nix that makes structured runtime
+  # closure information available to builders. This data is imported
+  # back via IFD to process it for layering data.
+  graphJSON =
+    path:
+    runCommand "build-graph" {
+      __structuredAttrs = true;
+      exportReferencesGraph.graph = path;
+      PATH = "${coreutils}/bin";
+      builder = toFile "builder" ''
+        . .attrs.sh
+        cat .attrs.json > ''${outputs[out]}
+      '';
+    } "";
+
+  buildClosures = paths: (fromJSON (readFile (graphJSON paths)));
+
+  buildGraph = paths: listToAttrs (map (c: {
+    name = c.path;
+    value = {
+    inherit (c) closureSize references;
+    };
+  }) (buildClosures paths));
+
+  # Nix does not allow attrbute set keys to refer to store paths, but
+  # we need them to for the purpose of the calculation. To work around
+  # it, the store path prefix is replaced with the string 'closure/'
+  # and later replaced again.
+  fromStorePath = replaceStrings [ "/nix/store" ] [ "closure/" ];
+  toStorePath = replaceStrings [ "closure/" ] [ "/nix/store/" ];
+
+  buildTree = paths:
+  let
+    graph = buildGraph paths;
+    top = listToAttrs (map (p: {
+      name = fromStorePath (toString p);
+      value = {};
+    }) paths);
+  in top;
+
+  outputJson = thing: writeText "the-thing.json" (builtins.toJSON thing);
+in outputJson (buildClosures path).graph