diff --git a/Makefile b/Makefile index 30a556e04..329c64ba2 100644 --- a/Makefile +++ b/Makefile @@ -1212,3 +1212,38 @@ reg-tests-help: @echo "(see --help option of this script for more information)." .PHONY: reg-tests reg-tests-help + +# "make range" iteratively builds using "make all" and the exact same build +# options for all commits within RANGE. RANGE may be either a git range +# such as ref1..ref2 or a single commit, in which case all commits from +# the master branch to this one will be tested. + +range: + $(Q)[ -d .git/. ] || { echo "## Fatal: \"make $@\" may only be used inside a Git repository."; exit 1; } + + $(Q)if git diff-index --name-only HEAD 2>/dev/null | grep -q ^; then \ + echo "Fatal: \"make $@\" requires a clean working tree."; exit 1; fi + + $(Q)[ -n "$(RANGE)" ] || { echo "## Fatal: \"make $@\" requires a git commit range in RANGE."; exit 1; } + $(Q)[ -n "$(TARGET)" ] || { echo "## Fatal: \"make $@\" needs the same variables as \"all\" (TARGET etc)."; exit 1; } + + $(Q) ( die() { echo;echo "## Stopped in error at index [ $$index/$$count ] commit $$commit";\ + echo "Previous branch was $$BRANCH"; exit $$1; }; \ + BRANCH=$$(git branch --show-current HEAD 2>/dev/null); \ + [ -n "$$BRANCH" ] || { echo "Fatal: \"make $@\" may only be used inside a checked out branch."; exit 1; }; \ + [ -z "$${RANGE##*..*}" ] || RANGE="master..$${RANGE}"; \ + COMMITS=( $$(git rev-list --abbrev-commit --reverse "$${RANGE}") ); \ + index=1; count=$${#COMMITS[@]}; \ + [ "$${count}" -gt 0 ] || { echo "## Fatal: no commit(s) found in range $${RANGE}."; exit 1; }; \ + echo "Found $${count} commit(s) in range $${RANGE}." ; \ + echo "Current branch is $$BRANCH"; \ + echo "Starting to building now..."; \ + for commit in $${COMMITS[@]}; do \ + echo "[ $$index/$$count ] $$commit #############################"; \ + git checkout -q $$commit || die 1; \ + $(MAKE) all || die 1; \ + ((index++)); \ + done; \ + echo;echo "Done! $${count} commit(s) built successfully for RANGE $${RANGE}" ; \ + git checkout -q "$$BRANCH"; \ + )