Re: [PATCH v3 2/2] rebase-interactive: warn if commit is dropped with `rebase --edit-todo'

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Alban

On 02/12/2019 23:47, Alban Gruin wrote:
> [...]
diff --git a/sequencer.c b/sequencer.c
index 181bb35f5f..75d5ad0496 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -4271,8 +4271,20 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)
  	if (read_populate_opts(opts))
  		return -1;
  	if (is_rebase_i(opts)) {
+		struct todo_list backup = TODO_LIST_INIT;
+
  		if ((res = read_populate_todo(r, &todo_list, opts)))
  			goto release_todo_list;
+
+		if (strbuf_read_file(&backup.buf, rebase_path_todo_backup(), 0) > 0) {
+			todo_list_parse_insn_buffer(r, backup.buf.buf, &backup);
+			res = todo_list_check(&backup, &todo_list);
+			todo_list_release(&backup);

This causes problems if the user edits the todo list and then later runs 'git rebase --continue' after resolving conflicts as the backup todo list has a bunch of commands that have already been processed but they are seen as missing

This test fails

test_expect_success 'rebase.missingCommitsCheck = error after resolving conflicts' '
	test_config rebase.missingCommitsCheck error &&
	(
		set_fake_editor &&
		FAKE_LINES="break 2 3 4" git rebase -i A E
	) &&
	git rebase --edit-todo &&
	test_must_fail git rebase --continue &&
	echo x >file1 &&
	git add file1 &&
	git rebase --continue
'

I think it would be better to write a file if the check fails when editing the todo list and check for the presence of that file when continuing and error out if it exists. This would also allow --edit-todo to only remove the backup file if there are no outstanding errors from the last edit and so check that those errors are fixed by the second edit. I think we'd only want to do this if rebase.missingCommitsCheck is set to error.

Best Wishes

Phillip

+
+			if (res)
+				goto release_todo_list;
+		}
+
  		if (commit_staged_changes(r, opts, &todo_list))
  			return -1;
  	} else if (!file_exists(get_todo_path(opts)))
@@ -4986,12 +4998,6 @@ int todo_list_write_to_file(struct repository *r, struct todo_list *todo_list,
  	return res;
  }
-static const char edit_todo_list_advice[] =
-N_("You can fix this with 'git rebase --edit-todo' "
-"and then run 'git rebase --continue'.\n"
-"Or you can abort the rebase with 'git rebase"
-" --abort'.\n");
-
  /* skip picking commits whose parents are unchanged */
  static int skip_unnecessary_picks(struct repository *r,
  				  struct todo_list *todo_list,
@@ -5089,11 +5095,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
  		todo_list_release(&new_todo);
return error(_("nothing to do"));
-	}
-
-	if (todo_list_parse_insn_buffer(r, new_todo.buf.buf, &new_todo) ||
-	    todo_list_check(todo_list, &new_todo)) {
-		fprintf(stderr, _(edit_todo_list_advice));
+	} else if (res == -4) {
  		checkout_onto(r, opts, onto_name, &onto->object.oid, orig_head);
  		todo_list_release(&new_todo);
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 29a35840ed..9051c1e11d 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -1343,6 +1343,89 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' '
  	test B = $(git cat-file commit HEAD^ | sed -ne \$p)
  '
+test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = ignore' '
+	test_config rebase.missingCommitsCheck ignore &&
+	rebase_setup_and_clean missing-commit &&
+	set_fake_editor &&
+	FAKE_LINES="break 1 2 3 4 5" git rebase -i --root &&
+	FAKE_LINES="1 2 3 4" git rebase --edit-todo 2>actual &&
+	git rebase --continue 2>actual &&
+	test D = $(git cat-file commit HEAD | sed -ne \$p) &&
+	test_i18ngrep \
+		"Successfully rebased and updated refs/heads/missing-commit" \
+		actual
+'
+
+test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = warn' '
+	cat >expect <<-EOF &&
+	error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 master~4)
+	Warning: some commits may have been dropped accidentally.
+	Dropped commits (newer to older):
+	 - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
+	To avoid this message, use "drop" to explicitly remove a commit.
+	EOF
+	tail -n4 expect >expect.2 &&
+	test_config rebase.missingCommitsCheck warn &&
+	rebase_setup_and_clean missing-commit &&
+	set_fake_editor &&
+	test_must_fail env FAKE_LINES="bad 1 2 3 4 5" \
+		git rebase -i --root &&
+	cp .git/rebase-merge/git-rebase-todo.backup orig &&
+	FAKE_LINES="2 3 4" git rebase --edit-todo 2>actual.2 &&
+	head -n5 actual.2 >actual &&
+	test_i18ncmp expect actual &&
+	cp orig .git/rebase-merge/git-rebase-todo &&
+	FAKE_LINES="1 2 3 4" git rebase --edit-todo 2>actual.2 &&
+	head -n4 actual.2 >actual &&
+	test_i18ncmp expect.2 actual &&
+	git rebase --continue 2>actual &&
+	test D = $(git cat-file commit HEAD | sed -ne \$p) &&
+	test_i18ngrep \
+		"Successfully rebased and updated refs/heads/missing-commit" \
+		actual
+'
+
+test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = error' '
+	cat >expect <<-EOF &&
+	error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 master~4)
+	Warning: some commits may have been dropped accidentally.
+	Dropped commits (newer to older):
+	 - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
+	To avoid this message, use "drop" to explicitly remove a commit.
+
+	Use '\''git config rebase.missingCommitsCheck'\'' to change the level of warnings.
+	The possible behaviours are: ignore, warn, error.
+
+	You can fix this with '\''git rebase --edit-todo'\'' and then run '\''git rebase --continue'\''.
+	Or you can abort the rebase with '\''git rebase --abort'\''.
+	EOF
+	tail -n10 expect >expect.2 &&
+	test_config rebase.missingCommitsCheck error &&
+	rebase_setup_and_clean missing-commit &&
+	set_fake_editor &&
+	test_must_fail env FAKE_LINES="bad 1 2 3 4 5" \
+		git rebase -i --root &&
+	cp .git/rebase-merge/git-rebase-todo.backup orig &&
+	test_must_fail env FAKE_LINES="2 3 4" \
+		git rebase --edit-todo 2>actual &&
+	test_i18ncmp expect actual &&
+	test_must_fail git rebase --continue 2>actual &&
+	test_i18ncmp expect actual &&
+	cp orig .git/rebase-merge/git-rebase-todo &&
+	test_must_fail env FAKE_LINES="1 2 3 4" \
+		git rebase --edit-todo 2>actual &&
+	test_i18ncmp expect.2 actual &&
+	test_must_fail git rebase --continue 2>actual &&
+	test_i18ncmp expect.2 actual &&
+	cp orig .git/rebase-merge/git-rebase-todo &&
+	FAKE_LINES="1 2 3 4 drop 5" git rebase --edit-todo &&
+	git rebase --continue 2>actual &&
+	test D = $(git cat-file commit HEAD | sed -ne \$p) &&
+	test_i18ngrep \
+		"Successfully rebased and updated refs/heads/missing-commit" \
+		actual
+'
+
  test_expect_success 'respects rebase.abbreviateCommands with fixup, squash and exec' '
  	rebase_setup_and_clean abbrevcmd &&
  	test_commit "first" file1.txt "first line" first &&




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux