Skip to content

Commit 804098b

Browse files
LostRedSkygitster
authored andcommitted
git rebase -i: add static check for commands and SHA-1
Check before the start of the rebasing if the commands exists, and for the commands expecting a SHA-1, check if the SHA-1 is present and corresponds to a commit. In case of error, print the error, stop git rebase and prompt the user to fix with 'git rebase --edit-todo' or to abort. This allows to avoid doing half of a rebase before finding an error and giving back what's left of the todo list to the user and prompt him to fix when it might be too late for him to do so (he might have to abort and restart the rebase). Signed-off-by: Galan Rémi <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 3707995 commit 804098b

File tree

3 files changed

+116
-0
lines changed

3 files changed

+116
-0
lines changed

git-rebase--interactive.sh

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,71 @@ add_exec_commands () {
846846
mv "$1.new" "$1"
847847
}
848848

849+
# Check if the SHA-1 passed as an argument is a
850+
# correct one, if not then print $2 in "$todo".badsha
851+
# $1: the SHA-1 to test
852+
# $2: the line to display if incorrect SHA-1
853+
check_commit_sha () {
854+
badsha=0
855+
if test -z $1
856+
then
857+
badsha=1
858+
else
859+
sha1_verif="$(git rev-parse --verify --quiet $1^{commit})"
860+
if test -z $sha1_verif
861+
then
862+
badsha=1
863+
fi
864+
fi
865+
866+
if test $badsha -ne 0
867+
then
868+
warn "Warning: the SHA-1 is missing or isn't" \
869+
"a commit in the following line:"
870+
warn " - $2"
871+
warn
872+
fi
873+
874+
return $badsha
875+
}
876+
877+
# prints the bad commits and bad commands
878+
# from the todolist in stdin
879+
check_bad_cmd_and_sha () {
880+
retval=0
881+
git stripspace --strip-comments |
882+
(
883+
while read -r line
884+
do
885+
IFS=' '
886+
set -- $line
887+
command=$1
888+
sha1=$2
889+
890+
case $command in
891+
''|noop|x|"exec")
892+
# Doesn't expect a SHA-1
893+
;;
894+
pick|p|drop|d|reword|r|edit|e|squash|s|fixup|f)
895+
if ! check_commit_sha $sha1 "$line"
896+
then
897+
retval=1
898+
fi
899+
;;
900+
*)
901+
warn "Warning: the command isn't recognized" \
902+
"in the following line:"
903+
warn " - $line"
904+
warn
905+
retval=1
906+
;;
907+
esac
908+
done
909+
910+
return $retval
911+
)
912+
}
913+
849914
# Print the list of the SHA-1 of the commits
850915
# from stdin to stdout
851916
todo_list_to_sha_list () {
@@ -887,6 +952,8 @@ get_missing_commit_check_level () {
887952

888953
# Check if the user dropped some commits by mistake
889954
# Behaviour determined by rebase.missingCommitsCheck.
955+
# Check if there is an unrecognized command or a
956+
# bad SHA-1 in a command.
890957
check_todo_list () {
891958
raise_error=f
892959

@@ -935,6 +1002,11 @@ check_todo_list () {
9351002
;;
9361003
esac
9371004

1005+
if ! check_bad_cmd_and_sha <"$todo"
1006+
then
1007+
raise_error=t
1008+
fi
1009+
9381010
if test $raise_error = t
9391011
then
9401012
# Checkout before the first commit of the

t/lib-rebase.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ set_fake_editor () {
5454
echo '# comment' >> "$1";;
5555
">")
5656
echo >> "$1";;
57+
bad)
58+
action="badcmd";;
59+
fakesha)
60+
echo "$action XXXXXXX False commit" >> "$1"
61+
action=pick;;
5762
*)
5863
sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1"
5964
action=pick;;

t/t3404-rebase-interactive.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,4 +1186,43 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' '
11861186
test B = $(git cat-file commit HEAD^ | sed -ne \$p)
11871187
'
11881188

1189+
cat >expect <<EOF
1190+
Warning: the command isn't recognized in the following line:
1191+
- badcmd $(git rev-list --oneline -1 master~1)
1192+
1193+
You can fix this with 'git rebase --edit-todo'.
1194+
Or you can abort the rebase with 'git rebase --abort'.
1195+
EOF
1196+
1197+
test_expect_success 'static check of bad command' '
1198+
rebase_setup_and_clean bad-cmd &&
1199+
set_fake_editor &&
1200+
test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \
1201+
git rebase -i --root 2>actual &&
1202+
test_cmp expect actual &&
1203+
FAKE_LINES="1 2 3 drop 4 5" git rebase --edit-todo &&
1204+
git rebase --continue &&
1205+
test E = $(git cat-file commit HEAD | sed -ne \$p) &&
1206+
test C = $(git cat-file commit HEAD^ | sed -ne \$p)
1207+
'
1208+
1209+
cat >expect <<EOF
1210+
Warning: the SHA-1 is missing or isn't a commit in the following line:
1211+
- edit XXXXXXX False commit
1212+
1213+
You can fix this with 'git rebase --edit-todo'.
1214+
Or you can abort the rebase with 'git rebase --abort'.
1215+
EOF
1216+
1217+
test_expect_success 'static check of bad SHA-1' '
1218+
rebase_setup_and_clean bad-sha &&
1219+
set_fake_editor &&
1220+
test_must_fail env FAKE_LINES="1 2 edit fakesha 3 4 5 #" \
1221+
git rebase -i --root 2>actual &&
1222+
test_cmp expect actual &&
1223+
FAKE_LINES="1 2 4 5 6" git rebase --edit-todo &&
1224+
git rebase --continue &&
1225+
test E = $(git cat-file commit HEAD | sed -ne \$p)
1226+
'
1227+
11891228
test_done

0 commit comments

Comments
 (0)