@ilkecan @tejing Thanks for your answers 
However, I haven’t converted to flakes yet. Also, if I understand it right, a dirty working directory is allowed per default and I had to explicitly pass --allow-dirty=false
(or similar) to make it fail. This is obviously not what I want because it is extra effort just to force me to do the right thing.
The self.rev
might be what I was looking for but as I said, I’m not on flakes yet.
I came up with a solution that works with or without flakes. It is on the on hand somewhat hacky, but on the other hand I find it quite elegant 
{ config, pkgs,... }:
let
nixos-rebuild-wrapper =
pkgs.writeShellScriptBin "nixos-rebuild" ''
orig_PWD="$PWD"
check=false
if [ $1 == '--force-plz-i-fcked-up' ]; then
shift
else
for arg in "$@"; do
# Allow only arguments starting with a minus (to support e.g. `--help`) and `dry-*` commands
if [[ ! "$arg" =~ ^- ]] && [[ ! "$arg" =~ ^dry- ]]; then
check=true
fi
done
fi
if [[ $check == true ]]; then
nixosConfig="$(echo $NIX_PATH | tr : $'\n' | awk '/^nixos-config=/ { st = index($0, "="); print substr($0, st+1) }')"
configDir="$(dirname "$nixosConfig")"
cd "$configDir"
if ! $(git rev-parse --is-inside-work-tree >/dev/null 2>&1); then
# Warn if config is not in a git repository
echo >&2 -ne "\n $(tput bold; tput setab 226; tput setaf 0) WARNING $(tput sgr0) "
echo >&2 -e "No git repository found in \"''${configDir}\".\n"
elif [ -n "$(git status --porcelain)" ]; then
# Fail when dirty
echo >&2 -ne "\n $(tput bold; tput setab 124; tput setaf 255) ERROR $(tput sgr0) "
echo >&2 -e "Uncommitted changes in \"''${configDir}\". Please commit them first.\n"
exit 1
fi
fi
cd "$orig_PWD"
${pkgs.nixos-rebuild}/bin/nixos-rebuild "$@"
'';
in {
# ...
environment.systemPackages = with pkgs; [
nixos-rebuild-wrapper
# ...
];
# ...
}
What I do here is to create a new derivation with a script that replaces and wraps the nixos-rebuild
executable, and add it to the system packages.
The script checks if the repository is dirty and if so, it exits with an error message. If the config is not inside a git repository, a warning will be displayed and the build continues (a loophole!).
To find the git repository, the script gets the location of the configuration.nix
from the $NIX_PATH
environment variable and assumes that it is located inside the repository (must not be in the top level folder).
To make sure nixos-rebuild --help
still works, I do the dirty check only if the script was called with any arguments that don’t start with a minus. Doing so, I make sure that the check only applies when using one of the build commands. I decided to also allow any dry-
commands.
I included a flag --force-plz-i-fcked-up
that has to be passed as first parameter. It enables me to build my system even when the working directory is dirty. Just in case. I might remove this flag if I find myself abusing it. I could still rename the .git
directory to disable the check. But the inhibition threshold to doing this is (at least for me) much higher.