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-alfo...@ensimag.grenoble-inp.fr>
---
 git-rebase--interactive.sh    | 63 +++++++++++++++++++++++++++++++++++++++++++
 t/lib-rebase.sh               |  5 ++++
 t/t3404-rebase-interactive.sh | 40 +++++++++++++++++++++++++++
 3 files changed, 108 insertions(+)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 68a71d0..226a8a8 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -834,6 +834,47 @@ add_exec_commands () {
        mv "$1.new" "$1"
 }
 
+# prints the bad commits and bad commands
+# from the todolist in stdin
+check_bad_cmd_and_sha () {
+       git stripspace --strip-comments |
+       while read -r command sha1 rest
+       do
+               case $command in
+               ''|noop|x|"exec")
+                       ;;
+               pick|p|drop|d|reword|r|edit|e|squash|s|fixup|f)
+                       if test -z $sha1
+                       then
+                               echo "$command $rest" >>"$todo".badsha
+                       else
+                               sha1_verif="$(git rev-parse --verify --quiet 
$sha1^{commit})"
+                               if test -z $sha1_verif
+                               then
+                                       echo "$command $sha1 $rest" \
+                                               >>"$todo".badsha
+                               fi
+                       fi
+                       ;;
+               *)
+                       if test -z $sha1
+                       then
+                               echo "$command" >>"$todo".badcmd
+                       else
+                               commit="$(git rev-list --oneline -1 
--ignore-missing $sha1 2>/dev/null)"
+                               if test -z "$commit"
+                               then
+                                       echo "$command $sha1 $rest" \
+                                               >>"$todo".badcmd
+                               else
+                                       echo "$command $commit" >>"$todo".badcmd
+                               fi
+                       fi
+                       ;;
+               esac
+       done
+}
+
 # Print the list of the SHA-1 of the commits
 # from stdin to stdout
 todo_list_to_sha_list () {
@@ -913,6 +954,28 @@ check_todo_list () {
                ;;
        esac
 
+       check_bad_cmd_and_sha <"$todo"
+
+       if test -s "$todo".badsha
+       then
+               raiseError=t
+
+               warn "Warning: the SHA-1 is missing or isn't" \
+                       "a commit in the following line(s):"
+               warn_file "$todo".badsha
+               warn
+       fi
+
+       if test -s "$todo".badcmd
+       then
+               raiseError=t
+
+               warn "Warning: the command isn't recognized" \
+                       "in the following line(s):"
+               warn_file "$todo".badcmd
+               warn
+       fi
+
        if test $raiseError = t
        then
                # Checkout before the first commit of the
diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh
index fdbc900..9a96e15 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -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;;
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index a92ae19..d691b1c 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -1184,4 +1184,44 @@ 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(s):
+ - 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' '
+       test_rebase_end tmp2 &&
+       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(s):
+ - 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' '
+       test_config rebase.missingCommitsCheck error &&
+       test_rebase_end tmp2 &&
+       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
-- 
2.4.2.496.gdc9319a

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to