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 <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Johannes Schindelin 2007-07-04 15:36:01 +01:00 коммит произвёл Junio C Hamano
Родитель 09ff69bb39
Коммит 8c1ce0f46b
2 изменённых файлов: 36 добавлений и 11 удалений

39
git-filter-branch.sh Normal file → Executable file
Просмотреть файл

@ -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)"

Просмотреть файл

@ -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)