Skip to content

Commit 8c1ce0f

Browse files
dschogitster
authored andcommitted
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>
1 parent 09ff69b commit 8c1ce0f

File tree

2 files changed

+36
-11
lines changed

2 files changed

+36
-11
lines changed

git-filter-branch.sh

100644100755
Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ map()
2828
fi
2929
}
3030

31+
# override die(): this version puts in an extra line break, so that
32+
# the progress is still visible
33+
34+
die()
35+
{
36+
echo >&2
37+
echo "$*" >&2
38+
exit 1
39+
}
40+
3141
# When piped a commit, output a script to set the ident of either
3242
# "author" or "committer
3343

@@ -181,23 +191,29 @@ while read commit parents; do
181191
export GIT_COMMIT=$commit
182192
git cat-file commit "$commit" >../commit
183193

184-
eval "$(set_ident AUTHOR <../commit)"
185-
eval "$(set_ident COMMITTER <../commit)"
186-
eval "$filter_env" < /dev/null
194+
eval "$(set_ident AUTHOR <../commit)" ||
195+
die "setting author failed for commit $commit"
196+
eval "$(set_ident COMMITTER <../commit)" ||
197+
die "setting committer failed for commit $commit"
198+
eval "$filter_env" < /dev/null ||
199+
die "env filter failed: $filter_env"
187200

188201
if [ "$filter_tree" ]; then
189202
git checkout-index -f -u -a
190203
# files that $commit removed are now still in the working tree;
191204
# remove them, else they would be added again
192205
git ls-files -z --others | xargs -0 rm -f
193-
eval "$filter_tree" < /dev/null
206+
eval "$filter_tree" < /dev/null ||
207+
die "tree filter failed: $filter_tree"
208+
194209
git diff-index -r $commit | cut -f 2- | tr '\n' '\0' | \
195210
xargs -0 git update-index --add --replace --remove
196211
git ls-files -z --others | \
197212
xargs -0 git update-index --add --replace --remove
198213
fi
199214

200-
eval "$filter_index" < /dev/null
215+
eval "$filter_index" < /dev/null ||
216+
die "index filter failed: $filter_index"
201217

202218
parentstr=
203219
for parent in $parents; do
@@ -206,13 +222,15 @@ while read commit parents; do
206222
done
207223
done
208224
if [ "$filter_parent" ]; then
209-
parentstr="$(echo "$parentstr" | eval "$filter_parent")"
225+
parentstr="$(echo "$parentstr" | eval "$filter_parent")" ||
226+
die "parent filter failed: $filter_parent"
210227
fi
211228

212229
sed -e '1,/^$/d' <../commit | \
213-
eval "$filter_msg" | \
214-
sh -c "$filter_commit" "git commit-tree" $(git write-tree) \
215-
$parentstr > ../map/$commit
230+
eval "$filter_msg" > ../message ||
231+
die "msg filter failed: $filter_msg"
232+
sh -c "$filter_commit" "git commit-tree" \
233+
$(git write-tree) $parentstr < ../message > ../map/$commit
216234
done <../revs
217235

218236
src_head=$(tail -n 1 ../revs | sed -e 's/ .*//')
@@ -249,7 +267,8 @@ if [ "$filter_tag_name" ]; then
249267
[ -f "../map/$sha1" ] || continue
250268
new_sha1="$(cat "../map/$sha1")"
251269
export GIT_COMMIT="$sha1"
252-
new_ref="$(echo "$ref" | eval "$filter_tag_name")"
270+
new_ref="$(echo "$ref" | eval "$filter_tag_name")" ||
271+
die "tag name filter failed: $filter_tag_name"
253272

254273
echo "$ref -> $new_ref ($sha1 -> $new_sha1)"
255274

t/t7003-filter-branch.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,19 @@ test_expect_success 'use index-filter to move into a subdirectory' '
107107
mv \$GIT_INDEX_FILE.new \$GIT_INDEX_FILE" directorymoved &&
108108
test -z "$(git diff HEAD directorymoved:newsubdir)"'
109109

110+
test_expect_success 'stops when msg filter fails' '
111+
! git-filter-branch --msg-filter false nonono &&
112+
rm -rf .git-rewrite &&
113+
! git rev-parse nonono
114+
'
115+
110116
test_expect_success 'author information is preserved' '
111117
: > i &&
112118
git add i &&
113119
test_tick &&
114120
GIT_AUTHOR_NAME="B V Uips" git commit -m bvuips &&
115121
git-filter-branch --msg-filter "cat; \
116-
test \$GIT_COMMIT = $(git rev-parse master) && \
122+
test \$GIT_COMMIT != $(git rev-parse master) || \
117123
echo Hallo" \
118124
preserved-author &&
119125
test 1 = $(git rev-list --author="B V Uips" preserved-author | wc -l)

0 commit comments

Comments
 (0)