Diffing user packages across a `nix-rebuild`

Users of @LnL7’s overlay for declarative package management by editing an overlay and running a new command nix-rebuild might be interested in the tweak I just made, which provides a nice diff of the requested packages across the rebuild. I’ve seen scripts before for diffing an entire environment, but I only care about the changes to the packages I’ve requested, not to any dependencies, so that’s what my script does. I commented on the overlay gist as well, but here’s what my version of the overlay looks like:

self: super:

{
  userPackages = super.userPackages or {} // {
    # My packages
    inherit (self) hello;
    # add more packages here...

    # Default packages
    inherit (self)
      cacert
      nix; # don't enable nix on multi-user
    
    nix-rebuild = super.writeScriptBin "nix-rebuild" ''
      #!${super.stdenv.shell}
      set -e
      if ! command -v nix-env &>/dev/null; then
        echo "warning: nix-env was not found in PATH, add nix to userPackages" >&2
        PATH=${self.nix}/bin:$PATH
      fi
      IFS=- read -r _ oldGen _ <<<"$(readlink "$(readlink ~/.nix-profile)")"
      oldVersions=$(readlink ~/.nix-profile/package_versions || echo "/dev/null")
      nix-env -f '<nixpkgs>' -r -iA userPackages "$@"
      IFS=- read -r _ newGen _ <<<"$(readlink "$(readlink ~/.nix-profile)")"
      ${self.diffutils}/bin/diff --color -u --label "generation $oldGen" $oldVersions \
        --label "generation $newGen" ~/.nix-profile/package_versions \
        || true
    '';

    packageVersions =
      let
        versions = super.lib.attrsets.mapAttrsToList (_: pkg: pkg.name) self.userPackages;
        versionText = super.lib.strings.concatMapStrings (s: s+"\n") versions;
      in
      super.writeTextDir "package_versions" versionText;
  };
}

And this produces output (when something changes) that looks like

--- generation 68
+++ generation 69
@@ -33,6 +33,7 @@
 rlwrap-0.43
 ShellCheck-0.6.0
 taskwarrior-2.5.1
+tig-2.4.1
 tmux-2.9a
 unison-2.51.2
 vit-1.3
1 Like