Skip to content

Commit

Permalink
git rebase -i: add static check for commands and SHA-1
Browse files Browse the repository at this point in the history
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 <remi.galan-alfonso@ensimag.grenoble-inp.fr>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Galan Rémi authored and Junio C Hamano committed Jun 30, 2015
1 parent 3707995 commit 804098b
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
72 changes: 72 additions & 0 deletions git-rebase--interactive.sh
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,71 @@ add_exec_commands () {
mv "$1.new" "$1"
}

# Check if the SHA-1 passed as an argument is a
# correct one, if not then print $2 in "$todo".badsha
# $1: the SHA-1 to test
# $2: the line to display if incorrect SHA-1
check_commit_sha () {
badsha=0
if test -z $1
then
badsha=1
else
sha1_verif="$(git rev-parse --verify --quiet $1^{commit})"
if test -z $sha1_verif
then
badsha=1
fi
fi

if test $badsha -ne 0
then
warn "Warning: the SHA-1 is missing or isn't" \
"a commit in the following line:"
warn " - $2"
warn
fi

return $badsha
}

# prints the bad commits and bad commands
# from the todolist in stdin
check_bad_cmd_and_sha () {
retval=0
git stripspace --strip-comments |
(
while read -r line
do
IFS=' '
set -- $line
command=$1
sha1=$2

case $command in
''|noop|x|"exec")
# Doesn't expect a SHA-1
;;
pick|p|drop|d|reword|r|edit|e|squash|s|fixup|f)
if ! check_commit_sha $sha1 "$line"
then
retval=1
fi
;;
*)
warn "Warning: the command isn't recognized" \
"in the following line:"
warn " - $line"
warn
retval=1
;;
esac
done

return $retval
)
}

# Print the list of the SHA-1 of the commits
# from stdin to stdout
todo_list_to_sha_list () {
Expand Down Expand Up @@ -887,6 +952,8 @@ get_missing_commit_check_level () {

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

Expand Down Expand Up @@ -935,6 +1002,11 @@ check_todo_list () {
;;
esac

if ! check_bad_cmd_and_sha <"$todo"
then
raise_error=t
fi

if test $raise_error = t
then
# Checkout before the first commit of the
Expand Down
5 changes: 5 additions & 0 deletions t/lib-rebase.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ set_fake_editor () {
echo '# comment' >> "$1";;
">")
echo >> "$1";;
bad)
action="badcmd";;
fakesha)
echo "$action XXXXXXX False commit" >> "$1"
action=pick;;
*)
sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1"
action=pick;;
Expand Down
39 changes: 39 additions & 0 deletions t/t3404-rebase-interactive.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1186,4 +1186,43 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' '
test B = $(git cat-file commit HEAD^ | sed -ne \$p)
'

cat >expect <<EOF
Warning: the command isn't recognized in the following line:
- badcmd $(git rev-list --oneline -1 master~1)
You can fix this with 'git rebase --edit-todo'.
Or you can abort the rebase with 'git rebase --abort'.
EOF

test_expect_success 'static check of bad command' '
rebase_setup_and_clean bad-cmd &&
set_fake_editor &&
test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \
git rebase -i --root 2>actual &&
test_cmp expect actual &&
FAKE_LINES="1 2 3 drop 4 5" git rebase --edit-todo &&
git rebase --continue &&
test E = $(git cat-file commit HEAD | sed -ne \$p) &&
test C = $(git cat-file commit HEAD^ | sed -ne \$p)
'

cat >expect <<EOF
Warning: the SHA-1 is missing or isn't a commit in the following line:
- edit XXXXXXX False commit
You can fix this with 'git rebase --edit-todo'.
Or you can abort the rebase with 'git rebase --abort'.
EOF

test_expect_success 'static check of bad SHA-1' '
rebase_setup_and_clean bad-sha &&
set_fake_editor &&
test_must_fail env FAKE_LINES="1 2 edit fakesha 3 4 5 #" \
git rebase -i --root 2>actual &&
test_cmp expect actual &&
FAKE_LINES="1 2 4 5 6" git rebase --edit-todo &&
git rebase --continue &&
test E = $(git cat-file commit HEAD | sed -ne \$p)
'

test_done

0 comments on commit 804098b

Please sign in to comment.