From a82e98d775112155dfe72f78c977dee21472ddbb Mon Sep 17 00:00:00 2001 From: Sven van Heugten Date: Mon, 2 Mar 2026 19:55:44 +0100 Subject: [PATCH 1/9] Move git-check-assertions to bin/ --- git-check-assertions => bin/git-check-assertions | 0 default.nix | 6 +++--- test.bats | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename git-check-assertions => bin/git-check-assertions (100%) diff --git a/git-check-assertions b/bin/git-check-assertions similarity index 100% rename from git-check-assertions rename to bin/git-check-assertions diff --git a/default.nix b/default.nix index 4dde1cf..8653ca0 100644 --- a/default.nix +++ b/default.nix @@ -20,7 +20,7 @@ resholve.mkDerivation { src = fs.toSource { root = ./.; fileset = fs.unions [ - ./git-check-assertions + ./bin/git-check-assertions ./test.bats ]; }; @@ -37,7 +37,7 @@ resholve.mkDerivation { checkPhase = '' runHook preCheck - shellcheck git-check-assertions test.bats + shellcheck bin/git-check-assertions test.bats git init git config user.email test git config user.name test @@ -52,7 +52,7 @@ resholve.mkDerivation { installPhase = '' runHook preInstall mkdir -p $out/bin - cp $src/git-check-assertions $out/bin/git-check-assertions + cp $src/bin/git-check-assertions $out/bin/git-check-assertions runHook postInstall ''; diff --git a/test.bats b/test.bats index 48965fd..96bf6d5 100755 --- a/test.bats +++ b/test.bats @@ -2,7 +2,7 @@ setup() { DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )" - PATH="$DIR:$PATH" + PATH="$DIR/bin:$PATH" } @test "can run" { From 653a1b67bc29afdf622bf7dddecadbf464907c79 Mon Sep 17 00:00:00 2001 From: Sven van Heugten Date: Mon, 2 Mar 2026 19:57:44 +0100 Subject: [PATCH 2/9] Move test.bats to test/git-check-assertions.bats --- default.nix | 6 +++--- test.bats => test/git-check-assertions.bats | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename test.bats => test/git-check-assertions.bats (85%) diff --git a/default.nix b/default.nix index 8653ca0..ecb1f69 100644 --- a/default.nix +++ b/default.nix @@ -21,7 +21,7 @@ resholve.mkDerivation { root = ./.; fileset = fs.unions [ ./bin/git-check-assertions - ./test.bats + ./test/git-check-assertions.bats ]; }; @@ -37,13 +37,13 @@ resholve.mkDerivation { checkPhase = '' runHook preCheck - shellcheck bin/git-check-assertions test.bats + shellcheck bin/git-check-assertions test/git-check-assertions.bats git init git config user.email test git config user.name test git checkout -b main git commit --allow-empty -m "initial" - ./test.bats + ./test/git-check-assertions.bats runHook postCheck ''; diff --git a/test.bats b/test/git-check-assertions.bats similarity index 85% rename from test.bats rename to test/git-check-assertions.bats index 96bf6d5..8371aea 100755 --- a/test.bats +++ b/test/git-check-assertions.bats @@ -2,7 +2,7 @@ setup() { DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )" - PATH="$DIR/bin:$PATH" + PATH="$DIR/../bin:$PATH" } @test "can run" { From e48e27fb523189d1652d53a8a78c7a5e976ea6b9 Mon Sep 17 00:00:00 2001 From: Sven van Heugten Date: Mon, 2 Mar 2026 20:06:53 +0100 Subject: [PATCH 3/9] Add helper modules for bats According to these instructions: https://bats-core.readthedocs.io/en/stable/tutorial.html#quick-installation --- .gitmodules | 9 +++++++++ README.md | 6 ++++++ default.nix | 4 ++-- test/git-check-assertions.bats | 6 +++++- test/test_helper/bats-assert | 1 + test/test_helper/bats-file | 1 + test/test_helper/bats-support | 1 + 7 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 .gitmodules create mode 160000 test/test_helper/bats-assert create mode 160000 test/test_helper/bats-file create mode 160000 test/test_helper/bats-support diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9ec278b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "test/test_helper/bats-support"] + path = test/test_helper/bats-support + url = https://github.com/bats-core/bats-support.git +[submodule "test/test_helper/bats-assert"] + path = test/test_helper/bats-assert + url = https://github.com/bats-core/bats-assert.git +[submodule "test/test_helper/bats-file"] + path = test/test_helper/bats-file + url = https://github.com/bats-core/bats-file.git diff --git a/README.md b/README.md index 0b302ca..01c4cb6 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,12 @@ You include a small bash script inside your commit messages, and `git-check-asse ⚠️ Only run this on repositories and branches that you trust, since the `bash` scripts in the commit messages can do whatever they want. +## Building + +```bash +nix build .?submodules=1 +``` + ## Examples of commit messages Assert that a commit builds: diff --git a/default.nix b/default.nix index ecb1f69..47212a6 100644 --- a/default.nix +++ b/default.nix @@ -20,8 +20,8 @@ resholve.mkDerivation { src = fs.toSource { root = ./.; fileset = fs.unions [ - ./bin/git-check-assertions - ./test/git-check-assertions.bats + ./bin + ./test ]; }; diff --git a/test/git-check-assertions.bats b/test/git-check-assertions.bats index 8371aea..8de6cf7 100755 --- a/test/git-check-assertions.bats +++ b/test/git-check-assertions.bats @@ -1,10 +1,14 @@ #!/usr/bin/env bats setup() { + load 'test_helper/bats-support/load' + load 'test_helper/bats-assert/load' + DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )" PATH="$DIR/../bin:$PATH" } @test "can run" { - git-check-assertions + run git-check-assertions + assert_success } diff --git a/test/test_helper/bats-assert b/test/test_helper/bats-assert new file mode 160000 index 0000000..697471b --- /dev/null +++ b/test/test_helper/bats-assert @@ -0,0 +1 @@ +Subproject commit 697471b7a89d3ab38571f38c6c7c4b460d1f5e35 diff --git a/test/test_helper/bats-file b/test/test_helper/bats-file new file mode 160000 index 0000000..6bee58b --- /dev/null +++ b/test/test_helper/bats-file @@ -0,0 +1 @@ +Subproject commit 6bee58bec7c2f4aed1a7425ccd4bdc42b4a84599 diff --git a/test/test_helper/bats-support b/test/test_helper/bats-support new file mode 160000 index 0000000..0954abb --- /dev/null +++ b/test/test_helper/bats-support @@ -0,0 +1 @@ +Subproject commit 0954abb9925cad550424cebca2b99255d4eabe96 From f5f05c0a9ef4814e5f2bd279f64ef5c71ea8fa52 Mon Sep 17 00:00:00 2001 From: Sven van Heugten Date: Mon, 2 Mar 2026 20:18:09 +0100 Subject: [PATCH 4/9] Set up the git repository in the bats file instead --- default.nix | 5 ----- test/git-check-assertions.bats | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/default.nix b/default.nix index 47212a6..e159ff1 100644 --- a/default.nix +++ b/default.nix @@ -38,11 +38,6 @@ resholve.mkDerivation { checkPhase = '' runHook preCheck shellcheck bin/git-check-assertions test/git-check-assertions.bats - git init - git config user.email test - git config user.name test - git checkout -b main - git commit --allow-empty -m "initial" ./test/git-check-assertions.bats runHook postCheck ''; diff --git a/test/git-check-assertions.bats b/test/git-check-assertions.bats index 8de6cf7..f4b27e8 100755 --- a/test/git-check-assertions.bats +++ b/test/git-check-assertions.bats @@ -6,9 +6,15 @@ setup() { DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )" PATH="$DIR/../bin:$PATH" + + git init + git config user.email "john.doe@example.com" + git config user.name "John Doe" + git checkout -b main } @test "can run" { + git commit --allow-empty -m "Initial" run git-check-assertions assert_success } From 769d7da9b21fc58bf82aebb3b1d9d5714c479ad8 Mon Sep 17 00:00:00 2001 From: Sven van Heugten Date: Mon, 2 Mar 2026 20:25:46 +0100 Subject: [PATCH 5/9] Use git init to immediately create the correct branch --- test/git-check-assertions.bats | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/git-check-assertions.bats b/test/git-check-assertions.bats index f4b27e8..9c5006f 100755 --- a/test/git-check-assertions.bats +++ b/test/git-check-assertions.bats @@ -7,10 +7,9 @@ setup() { DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )" PATH="$DIR/../bin:$PATH" - git init + git init -b main git config user.email "john.doe@example.com" git config user.name "John Doe" - git checkout -b main } @test "can run" { From 5dbb6aea8f5ceaff9f6ce3f6fd1099cb6e46ff6d Mon Sep 17 00:00:00 2001 From: Sven van Heugten Date: Mon, 2 Mar 2026 20:53:52 +0100 Subject: [PATCH 6/9] Set up shfmt --- bin/git-check-assertions | 11 +++++++---- default.nix | 4 ++++ flake.nix | 5 ++++- test/git-check-assertions.bats | 2 +- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/bin/git-check-assertions b/bin/git-check-assertions index a023370..f7fe936 100755 --- a/bin/git-check-assertions +++ b/bin/git-check-assertions @@ -25,7 +25,10 @@ set -euo pipefail assert_fails() { - ! "$@" || { echo "Expected command to fail, but it succeeded."; exit 1; } + ! "$@" || { + echo "Expected command to fail, but it succeeded." + exit 1 + } } export -f assert_fails @@ -42,9 +45,9 @@ for commit_hash in "${commits[@]}"; do git -c advice.detachedHead=false checkout -q "$commit_hash" commit_msg="$(git log -1 --format=%B "$commit_hash")" # shellcheck disable=SC2016 - block="$(printf '%s\n' "$commit_msg" \ - | sed -n '/^```git-check-assertions[[:space:]]*$/,/^```[[:space:]]*$/p' \ - | sed '1d;$d')" + block="$(printf '%s\n' "$commit_msg" | + sed -n '/^```git-check-assertions[[:space:]]*$/,/^```[[:space:]]*$/p' | + sed '1d;$d')" if [ -n "$block" ]; then echo "git-check-assertions block in $commit_hash:" printf '%s\n' "$block" | sed 's/^/> /' diff --git a/default.nix b/default.nix index e159ff1..a956baf 100644 --- a/default.nix +++ b/default.nix @@ -8,6 +8,7 @@ shellcheck-minimal, gitMinimal, resholve, + shfmt, }: let @@ -20,6 +21,7 @@ resholve.mkDerivation { src = fs.toSource { root = ./.; fileset = fs.unions [ + ./.editorconfig ./bin ./test ]; @@ -33,11 +35,13 @@ resholve.mkDerivation { shellcheck-minimal bats gitMinimal + shfmt ]; checkPhase = '' runHook preCheck shellcheck bin/git-check-assertions test/git-check-assertions.bats + shfmt -d bin/git-check-assertions test/git-check-assertions.bats ./test/git-check-assertions.bats runHook postCheck ''; diff --git a/flake.nix b/flake.nix index 55f8f46..60198ee 100644 --- a/flake.nix +++ b/flake.nix @@ -16,7 +16,10 @@ { packages.default = pkgs.callPackage ./default.nix { }; devShells.default = pkgs.mkShell { - packages = with pkgs; [ bats ]; + packages = with pkgs; [ + bats + shfmt + ]; }; } ); diff --git a/test/git-check-assertions.bats b/test/git-check-assertions.bats index 9c5006f..4ad07e9 100755 --- a/test/git-check-assertions.bats +++ b/test/git-check-assertions.bats @@ -4,7 +4,7 @@ setup() { load 'test_helper/bats-support/load' load 'test_helper/bats-assert/load' - DIR="$( cd "$( dirname "$BATS_TEST_FILENAME" )" >/dev/null 2>&1 && pwd )" + DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")" >/dev/null 2>&1 && pwd)" PATH="$DIR/../bin:$PATH" git init -b main From f4cdb276c39eb0eea0b4b8ec12b776d1fcc25e06 Mon Sep 17 00:00:00 2001 From: Sven van Heugten Date: Mon, 2 Mar 2026 20:26:02 +0100 Subject: [PATCH 7/9] Add some initial tests --- test/git-check-assertions.bats | 99 +++++++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 2 deletions(-) diff --git a/test/git-check-assertions.bats b/test/git-check-assertions.bats index 4ad07e9..0b0b0e1 100755 --- a/test/git-check-assertions.bats +++ b/test/git-check-assertions.bats @@ -1,19 +1,114 @@ #!/usr/bin/env bats setup() { + set -euo pipefail + load 'test_helper/bats-support/load' load 'test_helper/bats-assert/load' + load 'test_helper/bats-file/load' DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")" >/dev/null 2>&1 && pwd)" PATH="$DIR/../bin:$PATH" + mkdir "$BATS_TEST_TMPDIR/repo" + cd "$BATS_TEST_TMPDIR/repo" git init -b main git config user.email "john.doe@example.com" git config user.name "John Doe" + touch readme + git add readme + git commit -m "initial" } -@test "can run" { - git commit --allow-empty -m "Initial" +commit_with_assertion() { + git commit --allow-empty -F - <<-EOF + test + + \`\`\`git-check-assertions + $1 + \`\`\` + EOF +} + +@test "should not run any assertion blocks when on main" { + commit_with_assertion "touch ../test" + run git-check-assertions + + assert_success + assert_file_not_exists ../test +} + +@test "should not run any assertion blocks from main when on a feature branch" { + commit_with_assertion "touch ../test" + git checkout -b feature + git commit --allow-empty -m "feature" + + run git-check-assertions + + assert_success + assert_file_not_exists ../test +} + +@test "should run all succeeding assertion blocks on the feature branch and finally return to the original branch" { + git checkout -b feature + commit_with_assertion "touch ../test1" + commit_with_assertion "touch ../test2" + + run git-check-assertions + + assert_success + assert_file_exists ../test1 + assert_file_exists ../test2 + run git symbolic-ref --short HEAD + assert_output "feature" +} + +@test "should stop at the first failing assertion block and return to the original branch" { + git checkout -b feature + commit_with_assertion "touch ../test1 && exit 3" + commit_with_assertion "touch ../test2" + + run git-check-assertions + + assert_failure + assert_file_exists ../test1 + assert_file_not_exists ../test2 + run git symbolic-ref --short HEAD + assert_output "feature" +} + +@test "should restore worktree when finished" { + git checkout -b feature + commit_with_assertion 'echo blah >> readme' + + run git-check-assertions + + assert_success + assert_size_zero readme +} + +@test "should restore worktree between commits" { + git checkout -b feature + commit_with_assertion 'echo blah >> readme' + commit_with_assertion 'cp readme ../test' + + run git-check-assertions + + assert_success + assert_size_zero ../test +} + +@test "assertions should run against the version of the code inside of the commit" { + git checkout -b feature + echo commit1 >readme + git add readme + commit_with_assertion 'grep commit1 readme' + echo commit2 >readme + git add readme + commit_with_assertion 'grep commit2 readme' + + run git-check-assertions + assert_success } From e9c8e3b35eca32b1d93be4009e9308b99a9b2380 Mon Sep 17 00:00:00 2001 From: Sven van Heugten Date: Tue, 3 Mar 2026 07:07:28 +0100 Subject: [PATCH 8/9] Use bats.withLibraries instead of submodules --- .gitmodules | 9 --------- README.md | 2 +- default.nix | 6 +++++- flake.nix | 10 +++++++--- test/git-check-assertions.bats | 6 +++--- test/test_helper/bats-assert | 1 - test/test_helper/bats-file | 1 - test/test_helper/bats-support | 1 - 8 files changed, 16 insertions(+), 20 deletions(-) delete mode 100644 .gitmodules delete mode 160000 test/test_helper/bats-assert delete mode 160000 test/test_helper/bats-file delete mode 160000 test/test_helper/bats-support diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 9ec278b..0000000 --- a/.gitmodules +++ /dev/null @@ -1,9 +0,0 @@ -[submodule "test/test_helper/bats-support"] - path = test/test_helper/bats-support - url = https://github.com/bats-core/bats-support.git -[submodule "test/test_helper/bats-assert"] - path = test/test_helper/bats-assert - url = https://github.com/bats-core/bats-assert.git -[submodule "test/test_helper/bats-file"] - path = test/test_helper/bats-file - url = https://github.com/bats-core/bats-file.git diff --git a/README.md b/README.md index 01c4cb6..79ff8de 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ You include a small bash script inside your commit messages, and `git-check-asse ## Building ```bash -nix build .?submodules=1 +nix build . ``` ## Examples of commit messages diff --git a/default.nix b/default.nix index a956baf..d8055a8 100644 --- a/default.nix +++ b/default.nix @@ -33,7 +33,11 @@ resholve.mkDerivation { nativeCheckInputs = [ shellcheck-minimal - bats + (bats.withLibraries (p: [ + p.bats-assert + p.bats-support + p.bats-file + ])) gitMinimal shfmt ]; diff --git a/flake.nix b/flake.nix index 60198ee..e82af69 100644 --- a/flake.nix +++ b/flake.nix @@ -16,9 +16,13 @@ { packages.default = pkgs.callPackage ./default.nix { }; devShells.default = pkgs.mkShell { - packages = with pkgs; [ - bats - shfmt + packages = [ + (pkgs.bats.withLibraries (p: [ + p.bats-assert + p.bats-support + p.bats-file + ])) + pkgs.shfmt ]; }; } diff --git a/test/git-check-assertions.bats b/test/git-check-assertions.bats index 0b0b0e1..f58c3ea 100755 --- a/test/git-check-assertions.bats +++ b/test/git-check-assertions.bats @@ -3,9 +3,9 @@ setup() { set -euo pipefail - load 'test_helper/bats-support/load' - load 'test_helper/bats-assert/load' - load 'test_helper/bats-file/load' + bats_load_library bats-support + bats_load_library bats-assert + bats_load_library bats-file DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")" >/dev/null 2>&1 && pwd)" PATH="$DIR/../bin:$PATH" diff --git a/test/test_helper/bats-assert b/test/test_helper/bats-assert deleted file mode 160000 index 697471b..0000000 --- a/test/test_helper/bats-assert +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 697471b7a89d3ab38571f38c6c7c4b460d1f5e35 diff --git a/test/test_helper/bats-file b/test/test_helper/bats-file deleted file mode 160000 index 6bee58b..0000000 --- a/test/test_helper/bats-file +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6bee58bec7c2f4aed1a7425ccd4bdc42b4a84599 diff --git a/test/test_helper/bats-support b/test/test_helper/bats-support deleted file mode 160000 index 0954abb..0000000 --- a/test/test_helper/bats-support +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0954abb9925cad550424cebca2b99255d4eabe96 From 1fb1fcc4fa0c07197ccb1e64cc1030859c013688 Mon Sep 17 00:00:00 2001 From: Sven van Heugten Date: Tue, 3 Mar 2026 07:15:06 +0100 Subject: [PATCH 9/9] Add installation instructions --- README.md | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 79ff8de..f0479cd 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,41 @@ You include a small bash script inside your commit messages, and `git-check-asse ⚠️ Only run this on repositories and branches that you trust, since the `bash` scripts in the commit messages can do whatever they want. -## Building +## Installation -```bash -nix build . +On most systems, clone this repository and add the `bin` directory to your `PATH`. + +If you use Nix with flakes, you can simply add it to your program's devshell instead: + +```diff +@@ -2,12 +2,18 @@ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; ++ git-check-assertions = { ++ url = "git+https://codeberg.org/svenvanheugten/git-check-assertions.git?ref=main"; ++ inputs.nixpkgs.follows = "nixpkgs"; ++ inputs.flake-utils.follows = "flake-utils"; ++ }; + }; + outputs = + { + self, + nixpkgs, + flake-utils, ++ git-check-assertions, + }: + flake-utils.lib.eachDefaultSystem ( + system: +@@ -17,7 +23,10 @@ + { + packages.default = pkgs.callPackage ./default.nix { }; + devShells.default = pkgs.mkShell { +- packages = [ ]; ++ packages = [ git-check-assertions.packages.${system}.default ]; + }; + } + ) ``` ## Examples of commit messages