diff --git a/bin/git-test-sequence b/bin/git-test-sequence new file mode 100755 index 0000000..98c73b6 --- /dev/null +++ b/bin/git-test-sequence @@ -0,0 +1,99 @@ +#!/bin/sh +# Run a command over a sequence of commits. +# Example: +# git test-sequence origin/master.. 'make clean && make test' + +. "$(git --exec-path)/git-sh-setup" +require_work_tree + +t= +force= +run_once= +ref_name=pass + +# The tree must be really really clean. +if ! git update-index --ignore-submodules --refresh > /dev/null; then + echo >&2 "cannot rebase: you have unstaged changes" + git diff-files --name-status -r --ignore-submodules -- >&2 + exit 1 +fi +diff=$(git diff-index --cached --name-status -r --ignore-submodules HEAD --) +case "$diff" in + ?*) echo >&2 "cannot rebase: your index contains uncommitted changes" + echo >&2 "$diff" + exit 1 + ;; +esac + +start_branch=`git rev-parse --symbolic-full-name HEAD | sed s,refs/heads/,,` +git checkout `git rev-parse HEAD` > /dev/null 2>/dev/null + +cleanup() { + git checkout $start_branch > /dev/null 2>/dev/null +} + +already_passed() { + obdata=${ref_name}-$t-$1 + obhash=`echo $obdata | git hash-object --stdin` + git cat-file blob $obhash > /dev/null 2>/dev/null \ + && echo "Already ${ref_name} $1" +} + +passed_on() { + obdata=${ref_name}-$t-$1 + echo $obdata | git hash-object -w --stdin > /dev/null + echo "Passed: $1." +} + +broke_on() { + git log --pretty="format:Broke on %H (%s)%n" -n 1 $1 + cleanup + exit 1 +} + +new_test() { + echo "Testing $2" + git reset --hard $v && eval "$2" && passed_on $1 || broke_on $v + status=$? + if test -n "$run_once"; then + cleanup + exit $status + fi +} + + +while test $# != 0 +do + case "$1" in + --force) + force=yes + ;; + --once) + run_once=yes + ;; + --ref-name) + ref_name=$2 + shift + ;; + *) + break; + ;; + esac + shift +done + +t=`echo "$2" | git hash-object --stdin` + +for v in `git rev-list --reverse $1` +do + tree_ver=`git rev-parse "$v^{tree}"` + test -z "$force" && already_passed $tree_ver || new_test $tree_ver "$2" +done +cleanup + +if test -n "$run_once"; then + echo "All commits already passed for --once argument. Quiting." + exit 127 +fi + +echo "All's well."