diff --git a/.gitignore b/.gitignore index c4a847d..0c4cad3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /result +.git-check-assertions-cache diff --git a/README.md b/README.md index a128ef8..22e4448 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,12 @@ You can technically assert that a command fails by writing `! ... || exit 1`, or I'm considering taking `bats-assert` as a dependency, but for now, this very minimal set of functions with a similar interface should get you on your way. +## Cache of successful commits + +After a commit's assertions run successfully, `git-check-assertions` appends the commit hash to `.git-check-assertions-cache` in the repo root. On the next run, any commit listed there is skipped. + +Be sure to add `.git-check-assertions-cache` to your `.gitignore`. + ## Examples of commit messages Assert that a commit builds: diff --git a/bin/git-check-assertions b/bin/git-check-assertions index e111637..28cc9b5 100755 --- a/bin/git-check-assertions +++ b/bin/git-check-assertions @@ -87,7 +87,22 @@ echo "Base: $base" echo "Commits to visit: ${#commits[@]}" echo +declare -A cached_commits=() +if [ -f .git-check-assertions-cache ]; then + while IFS= read -r cached_commit; do + if [ -n "$cached_commit" ]; then + cached_commits["$cached_commit"]=1 + fi + done < .git-check-assertions-cache +fi + for commit_hash in "${commits[@]}"; do + if [ -n "${cached_commits[$commit_hash]+x}" ]; then + echo "Skipping $commit_hash (cached)" + echo + continue + fi + echo "Checking out $commit_hash" git -c advice.detachedHead=false checkout -q "$commit_hash" commit_msg="$(git log -1 --format=%B "$commit_hash")" @@ -107,6 +122,7 @@ for commit_hash in "${commits[@]}"; do fi restore fi + printf '%s\n' "$commit_hash" >>.git-check-assertions-cache echo done diff --git a/test/git-check-assertions.bats b/test/git-check-assertions.bats index 1550ae5..e706f41 100755 --- a/test/git-check-assertions.bats +++ b/test/git-check-assertions.bats @@ -9,9 +9,14 @@ init_repo() { git init -b "$main_branch" git config user.email "john.doe@example.com" git config user.name "John Doe" + + echo ".git-check-assertions-cache" >>.gitignore + git add .gitignore + git commit -m "add .git-check-assertions-cache to gitignore" + touch readme git add readme - git commit -m "initial" + git commit -m "add readme" } setup() { @@ -195,6 +200,57 @@ commit_with_assertion() { assert_size_zero readme } +@test "should skip cached commits on subsequent runs" { + git checkout -b feature + commit_with_assertion "touch ../test" + + run git-check-assertions + + assert_success + assert_file_exists ../test + rm ../test + + run git-check-assertions + + assert_success + assert_file_not_exists ../test +} + +@test "should not cache failed commits" { + git checkout -b feature + commit_with_assertion "touch ../test && exit 3" + + run git-check-assertions + + assert_failure + assert_file_exists ../test + rm ../test + + run git-check-assertions + + assert_failure + assert_file_exists ../test +} + +@test "should skip cached commits when multiple commits are cached" { + 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 + rm ../test1 ../test2 + + run git-check-assertions + + assert_success + assert_file_not_exists ../test1 + assert_file_not_exists ../test2 +} + @test "assertions should run against the version of the code inside of the commit" { git checkout -b feature echo commit1 >readme