From 8c1ce0f46b85d40f215084eed7313896300082df Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 4 Jul 2007 15:36:01 +0100 Subject: filter-branch: fail gracefully when a filter fails A common mistake is to provide a filter which fails unwantedly. For example, this will stop in the middle: git filter-branch --env-filter ' test $GIT_COMMITTER_EMAIL = xyz && export GIT_COMMITTER_EMAIL = abc' rewritten When $GIT_COMMITTER_EMAIL is not "xyz", the test fails, and consequently the whole filter has a non-zero exit status. However, as demonstrated in this example, filter-branch would just stop, and the user would be none the wiser. Also, a failing msg-filter would not have been caught, as was the case with one of the tests. This patch fixes both issues, by paying attention to the exit status of msg-filter, and by saying what failed before exiting. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- git-filter-branch.sh | 39 +++++++++++++++++++++++++++++---------- t/t7003-filter-branch.sh | 8 +++++++- 2 files changed, 36 insertions(+), 11 deletions(-) mode change 100644 => 100755 git-filter-branch.sh diff --git a/git-filter-branch.sh b/git-filter-branch.sh old mode 100644 new mode 100755 index 6cf67df5d6..d77902d34d --- a/git-filter-branch.sh +++ b/git-filter-branch.sh @@ -28,6 +28,16 @@ map() fi } +# override die(): this version puts in an extra line break, so that +# the progress is still visible + +die() +{ + echo >&2 + echo "$*" >&2 + exit 1 +} + # When piped a commit, output a script to set the ident of either # "author" or "committer @@ -181,23 +191,29 @@ while read commit parents; do export GIT_COMMIT=$commit git cat-file commit "$commit" >../commit - eval "$(set_ident AUTHOR <../commit)" - eval "$(set_ident COMMITTER <../commit)" - eval "$filter_env" < /dev/null + eval "$(set_ident AUTHOR <../commit)" || + die "setting author failed for commit $commit" + eval "$(set_ident COMMITTER <../commit)" || + die "setting committer failed for commit $commit" + eval "$filter_env" < /dev/null || + die "env filter failed: $filter_env" if [ "$filter_tree" ]; then git checkout-index -f -u -a # files that $commit removed are now still in the working tree; # remove them, else they would be added again git ls-files -z --others | xargs -0 rm -f - eval "$filter_tree" < /dev/null + eval "$filter_tree" < /dev/null || + die "tree filter failed: $filter_tree" + git diff-index -r $commit | cut -f 2- | tr '\n' '\0' | \ xargs -0 git update-index --add --replace --remove git ls-files -z --others | \ xargs -0 git update-index --add --replace --remove fi - eval "$filter_index" < /dev/null + eval "$filter_index" < /dev/null || + die "index filter failed: $filter_index" parentstr= for parent in $parents; do @@ -206,13 +222,15 @@ while read commit parents; do done done if [ "$filter_parent" ]; then - parentstr="$(echo "$parentstr" | eval "$filter_parent")" + parentstr="$(echo "$parentstr" | eval "$filter_parent")" || + die "parent filter failed: $filter_parent" fi sed -e '1,/^$/d' <../commit | \ - eval "$filter_msg" | \ - sh -c "$filter_commit" "git commit-tree" $(git write-tree) \ - $parentstr > ../map/$commit + eval "$filter_msg" > ../message || + die "msg filter failed: $filter_msg" + sh -c "$filter_commit" "git commit-tree" \ + $(git write-tree) $parentstr < ../message > ../map/$commit done <../revs src_head=$(tail -n 1 ../revs | sed -e 's/ .*//') @@ -249,7 +267,8 @@ if [ "$filter_tag_name" ]; then [ -f "../map/$sha1" ] || continue new_sha1="$(cat "../map/$sha1")" export GIT_COMMIT="$sha1" - new_ref="$(echo "$ref" | eval "$filter_tag_name")" + new_ref="$(echo "$ref" | eval "$filter_tag_name")" || + die "tag name filter failed: $filter_tag_name" echo "$ref -> $new_ref ($sha1 -> $new_sha1)" diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index 451ac861af..4ddd656e84 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -107,13 +107,19 @@ test_expect_success 'use index-filter to move into a subdirectory' ' mv \$GIT_INDEX_FILE.new \$GIT_INDEX_FILE" directorymoved && test -z "$(git diff HEAD directorymoved:newsubdir)"' +test_expect_success 'stops when msg filter fails' ' + ! git-filter-branch --msg-filter false nonono && + rm -rf .git-rewrite && + ! git rev-parse nonono +' + test_expect_success 'author information is preserved' ' : > i && git add i && test_tick && GIT_AUTHOR_NAME="B V Uips" git commit -m bvuips && git-filter-branch --msg-filter "cat; \ - test \$GIT_COMMIT = $(git rev-parse master) && \ + test \$GIT_COMMIT != $(git rev-parse master) || \ echo Hallo" \ preserved-author && test 1 = $(git rev-list --author="B V Uips" preserved-author | wc -l) -- cgit v1.2.3