--- /dev/null
+#!/bin/sh
+
+log=Meta/AT.log
+>>"$log"
+buildlog=Meta/AT.build-logs
+mkdir -p "$buildlog"
+t="/tmp/AT.$$"
+
+trap 'rm -f "$t.*"; exit' 0 1 2 3 15
+
+_x40="[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]"
+_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
+
+log_prune () {
+ cp "$log" "$log.bak"
+
+ git for-each-ref --format='%(objectname)' 'refs/heads/*/*' |
+ git rev-list --not ko/maint --not --stdin |
+ while read commit
+ do
+ git rev-parse --verify "$commit^{tree}"
+ done | sort -u >"$t.tree0"
+ sed -ne "s/A \($_x40\) .*/\1/p" "$log" | sort -u >"$t.tree1"
+ comm -13 "$t.tree0" "$t.tree1" | sed -e 's|.*|/^A &/d|' >"$t.prune"
+
+ next=$(git rev-parse --verify "refs/heads/next^0")
+ ko_next=$(git rev-parse --verify "refs/remotes/ko/next^0")
+ echo "/^N /{
+ s/^N $next /&/
+ t ok
+ s/^N $ko_next /&/
+ t ok
+ d
+ : ok
+}" >>"$t.prune"
+
+ sed -f "$t.prune" "$log" >"$t.pruned"
+ cat "$t.pruned" >"$log"
+}
+
+check_skip_test () {
+ GIT_SKIP_TESTS=
+ git diff --name-only ko/master "$1" >"$t.d"
+ if ! grep -q -e git-svn "$t.d"
+ then
+ GIT_SKIP_TESTS="$GIT_SKIP_TESTS t91??"
+ fi
+ if ! grep -q -e git-cvsexportcommit "$t.d"
+ then
+ GIT_SKIP_TESTS="$GIT_SKIP_TESTS t9200"
+ fi
+ if ! grep -q -e git-cvsimport "$t.d"
+ then
+ GIT_SKIP_TESTS="$GIT_SKIP_TESTS t9600"
+ fi
+ if test -n "$GIT_SKIP_TESTS"
+ then
+ export GIT_SKIP_TESTS
+ else
+ unset GIT_SKIP_TESTS
+ fi
+}
+
+autotest () {
+ commit=$(git rev-parse --verify "$1^0") &&
+ tree=$(git rev-parse --verify "$commit^{tree}") || return 1
+ grep -s "^A $tree " "$log" >/dev/null && return 0
+ o="$buildlog/$tree"
+
+ git reset -q --hard HEAD^0 &&
+ git checkout -q "$commit^0" || return 1
+
+ check_skip_test "$tree"
+
+ PAGER= git show -s --pretty='format:* %h %s%n' "$commit" --
+ if ! Meta/Make -pedantic >"$o" 2>&1
+ then
+ status="build error"
+ elif ! Meta/Make -pedantic test >>"$o" 2>&1
+ then
+ status="test error"
+ else
+ status=ok
+ rm -f "$o"
+ fi
+ : Meta/Make clean >/dev/null 2>&1
+ echo "A $tree $status" >>"$log"
+ echo "$status"
+}
+
+append_to_status () {
+ if test -z "$status"
+ then
+ status="$1"
+ else
+ status="$status; $1"
+ fi
+}
+
+nexttest () {
+ mb=$(git merge-base "$commit" "$next") || return 1
+ test "$mb" = "$commit" && return 0
+ grep -s "^N $next $commit " "$log" >/dev/null && return 0
+
+ branch="${refname#refs/heads/}"
+ git reset -q --hard next^0
+
+ echo "* $branch"
+
+ status= skip_build=
+ if ! git merge "$commit" >/dev/null 2>&1
+ then
+ conflict_count=$(git ls-files -u |
+ sed -e 's/.* //' |
+ sort -u |
+ xargs grep -e '^<<<<<<< ' |
+ wc -l)
+ if test $conflict_count = 0
+ then
+ append_to_status "rerere ok"
+ else
+ skip_build=t
+ append_to_status "conflict $conflict_count"
+ fi
+ fi
+ if test -z "$skip_build"
+ then
+ o="$buildlog/$commit"
+ check_skip_test "$commit"
+ if ! Meta/Make -pedantic >"$o" 2>&1
+ then
+ append_to_status "build error"
+ elif ! Meta/Make -pedantic test >>"$o" 2>&1
+ then
+ append_to_status "test error"
+ else
+ append_to_status "test ok"
+ rm -f "$o"
+ fi
+ fi
+ : Meta/Make clean >/dev/null 2>&1
+ echo "N $next $commit $status" >>"$log"
+ echo "$status"
+}
+
+loop () {
+ Meta/Make clean >/dev/null 2>&1
+ git reset --hard -q
+ git checkout -q HEAD^0
+ next=$(git rev-parse --verify "refs/remotes/ko/next^0")
+
+ while :
+ do
+ log_prune
+
+ date
+
+ l0=$(ls -l "$log")
+
+ git for-each-ref --format='%(objectname)' 'refs/heads/*/*' |
+ git rev-list --not ko/maint ko/master --not --stdin |
+ while read commit
+ do
+ autotest "$commit" || echo "oops?"
+ done
+
+ l1=$(ls -l "$log")
+ test "$l0" = "$l1" || continue
+
+ git for-each-ref --format='%(objectname) %(refname)' \
+ 'refs/heads/*/*' |
+ while read commit refname
+ do
+ nexttest "$commit" "$refname" || echo "oops?"
+ done
+
+ l1=$(ls -l "$log")
+ test "$l0" = "$l1" || continue
+
+ sleep 600 || exit
+ done
+}
+
+case "$#" in
+0)
+ loop
+ exit ;;
+esac
+
+(
+ git rev-list --no-walk "$@" 2>/dev/null || git rev-list "$@"
+) |
+while read commit
+do
+ autotest "$commit"
+done