diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index c26a200a6c..dcc3401b5a 100644 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -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 () { @@ -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 @@ -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 diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh index fdbc9007d0..9a96e1566d 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 cfa741018d..ebdab4b95d 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -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 <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 <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