git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCHv7 3/3] git rebase -i: add static check for commands and SHA-1

From
Galan Rémi <remi.galan-alfonso@ensimag.grenoble-inp.fr>
Date
Jun 29, 2015, 20:20 UTC
Message-ID
<1435609232-14232-4-git-send-email-remi.galan-alfonso@ensimag.grenoble-inp.fr>
In-Reply-To
<1435609232-14232-1-git-send-email-remi.galan-alfonso@ensimag.grenoble-inp.fr>

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>
---
 git-rebase--interactive.sh    | 75 +++++++++++++++++++++++++++++++++++++++++++
 t/lib-rebase.sh               |  5 +++
 t/t3404-rebase-interactive.sh | 39 ++++++++++++++++++++++
 3 files changed, 119 insertions(+)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 66daacf..ec4a068 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -834,6 +834,73 @@ 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 x $line
+			shift
+			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)
+				check_commit_sha $sha1 "$line"
+				if test $? -ne 0
+				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 () {
@@ -868,6 +935,8 @@ checkout_onto () {
 
 # 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
 
@@ -919,6 +988,12 @@ check_todo_list () {
 		;;
 	esac
 
+	check_bad_cmd_and_sha <"$todo"
+	if test $? -ne 0
+	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 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 904a2d0..9b2c51c 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 <<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
-- 
2.4.3.532.gf6210e5.dirty
Previous: Galan RémiNext: Matthieu Moy
Message 4 of 14 in “rebase -i: drop, missing commits and static checks”
  1. Galan RémiJun 29, 2015
  2. 1/3 git-rebase -i: add command "drop" to remove a commitGalan Rémi, Jun 29, 2015
  3. 2/3 git rebase -i: warn about removed commitsGalan Rémi, Jun 29, 2015
  4. 3/3 git rebase -i: add static check for commands and SHA-1Galan Rémi, Jun 29, 2015
  5. 0/3 rebase -i: drop, missing commits and static checksMatthieu Moy, Jun 30, 2015
  6. 1/3 fixup! git rebase -i: add static check for commands and SHA-1Matthieu Moy, Jun 30, 2015
  7. 2/3 fixup! git rebase -i: warn about removed commitsMatthieu Moy, Jun 30, 2015
  8. 3/3 fixup! git rebase -i: warn about removed commitsMatthieu Moy, Jun 30, 2015
  9. Remi Galan AlfonsoJun 30, 2015
  10. Matthieu MoyJun 30, 2015
  11. Junio C HamanoJun 30, 2015
  12. Remi Galan AlfonsoJun 30, 2015
  13. Matthieu MoyJun 30, 2015
  14. Junio C HamanoJun 30, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.