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

[PATCHv6 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 22, 2015, 21:42 UTC
Message-ID
<1435009369-11496-3-git-send-email-remi.galan-alfonso@ensimag.grenoble-inp.fr>
In-Reply-To
<1435009369-11496-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>
---
 I used:
   read -r command sha1 rest <<EOF
   $line
   EOF
 because
   printf '%s' "$line" | read -r command sha1 rest
 doesn't work (the 3 variables have no value as a result).
 There might be a better way to do this, but I don't have it right now.
 git-rebase--interactive.sh    | 70 +++++++++++++++++++++++++++++++++++++++++++
 t/lib-rebase.sh               |  5 ++++
 t/t3404-rebase-interactive.sh | 40 +++++++++++++++++++++++++
 3 files changed, 115 insertions(+)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 66daacf..6381686 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -834,6 +834,52 @@ 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=f
+	if test -z $1
+	then
+		badsha=t
+	else
+		sha1_verif="$(git rev-parse --verify --quiet $1^{commit})"
+		if test -z $sha1_verif
+		then
+			badsha=t
+		fi
+	fi
+
+	if test $badsha = t
+	then
+		printf '%s\n' "$2" >>"$todo".badsha
+	fi
+}
+
+# prints the bad commits and bad commands
+# from the todolist in stdin
+check_bad_cmd_and_sha () {
+	git stripspace --strip-comments |
+	while read -r line
+	do
+		read -r command sha1 rest <<EOF
+$line
+EOF
+		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"
+			;;
+		*)
+			printf '%s\n' "$line" >>"$todo".badcmd
+			;;
+		esac
+	done
+}
+
 # Print the list of the SHA-1 of the commits
 # from stdin to stdout
 todo_list_to_sha_list () {
@@ -868,6 +914,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 +967,28 @@ check_todo_list () {
 		;;
 	esac
 
+	check_bad_cmd_and_sha <"$todo"
+
+	if test -s "$todo".badsha
+	then
+		raise_error=t
+
+		warn "Warning: the SHA-1 is missing or isn't" \
+			"a commit in the following line(s):"
+		warn_lines <"$todo".badsha
+		warn
+	fi
+
+	if test -s "$todo".badcmd
+	then
+		raise_error=t
+
+		warn "Warning: the command isn't recognized" \
+			"in the following line(s):"
+		warn_lines <"$todo".badcmd
+		warn
+	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 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.3.371.g8992f2a
Previous: Galan RémiNext: Junio C Hamano
Message 3 of 16 in “[PATCHv6 1/3] git-rebase -i: add command "drop" to remove a commit”
  1. Galan RémiJun 22, 2015
  2. 2/3 git rebase -i: warn about removed commitsGalan Rémi, Jun 22, 2015
  3. 3/3 git rebase -i: add static check for commands and SHA-1Galan Rémi, Jun 22, 2015
  4. Junio C HamanoJun 23, 2015
  5. Remi Galan AlfonsoJun 23, 2015
  6. Eric SunshineJun 23, 2015
  7. Remi Galan AlfonsoJun 23, 2015
  8. Matthieu MoyJun 23, 2015
  9. Remi Galan AlfonsoJun 23, 2015
  10. Matthieu MoyJun 23, 2015
  11. Junio C HamanoJun 23, 2015
  12. Remi Galan AlfonsoJun 23, 2015
  13. Eric SunshineJun 23, 2015
  14. Junio C HamanoJun 23, 2015
  15. Remi Galan AlfonsoJun 23, 2015
  16. Junio C HamanoJun 23, 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.