Merge branch 'en/sequencer-edit-upon-conflict-fix'

"git cherry-pick/revert" with or without "--[no-]edit" did not spawn
the editor as expected (e.g. "revert --no-edit" after a conflict
still asked to edit the message), which has been corrected.

* en/sequencer-edit-upon-conflict-fix:
  sequencer: fix edit handling for cherry-pick and revert messages
This commit is contained in:
Junio C Hamano
2021-04-08 13:23:25 -07:00
4 changed files with 77 additions and 17 deletions

View File

@ -2032,13 +2032,24 @@ static void record_in_rewritten(struct object_id *oid,
flush_rewritten_pending();
}
static int should_edit(struct replay_opts *opts) {
if (opts->edit < 0)
/*
* Note that we only handle the case of non-conflicted
* commits; continue_single_pick() handles the conflicted
* commits itself instead of calling this function.
*/
return (opts->action == REPLAY_REVERT && isatty(0)) ? 1 : 0;
return opts->edit;
}
static int do_pick_commit(struct repository *r,
struct todo_item *item,
struct replay_opts *opts,
int final_fixup, int *check_todo)
{
unsigned int flags = opts->edit ? EDIT_MSG : 0;
const char *msg_file = opts->edit ? NULL : git_path_merge_msg(r);
unsigned int flags = should_edit(opts) ? EDIT_MSG : 0;
const char *msg_file = should_edit(opts) ? NULL : git_path_merge_msg(r);
struct object_id head;
struct commit *base, *next, *parent;
const char *base_label, *next_label;
@ -3283,9 +3294,9 @@ static int save_opts(struct replay_opts *opts)
if (opts->no_commit)
res |= git_config_set_in_file_gently(opts_file,
"options.no-commit", "true");
if (opts->edit)
res |= git_config_set_in_file_gently(opts_file,
"options.edit", "true");
if (opts->edit >= 0)
res |= git_config_set_in_file_gently(opts_file, "options.edit",
opts->edit ? "true" : "false");
if (opts->allow_empty)
res |= git_config_set_in_file_gently(opts_file,
"options.allow-empty", "true");
@ -4259,7 +4270,7 @@ static int pick_commits(struct repository *r,
prev_reflog_action = xstrdup(getenv(GIT_REFLOG_ACTION));
if (opts->allow_ff)
assert(!(opts->signoff || opts->no_commit ||
opts->record_origin || opts->edit ||
opts->record_origin || should_edit(opts) ||
opts->committer_date_is_author_date ||
opts->ignore_date));
if (read_and_refresh_cache(r, opts))
@ -4552,14 +4563,33 @@ cleanup_head_ref:
return sequencer_remove_state(opts);
}
static int continue_single_pick(struct repository *r)
static int continue_single_pick(struct repository *r, struct replay_opts *opts)
{
const char *argv[] = { "commit", NULL };
struct strvec argv = STRVEC_INIT;
int ret;
if (!refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD") &&
!refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD"))
return error(_("no cherry-pick or revert in progress"));
return run_command_v_opt(argv, RUN_GIT_CMD);
strvec_push(&argv, "commit");
/*
* continue_single_pick() handles the case of recovering from a
* conflict. should_edit() doesn't handle that case; for a conflict,
* we want to edit if the user asked for it, or if they didn't specify
* and stdin is a tty.
*/
if (!opts->edit || (opts->edit < 0 && !isatty(0)))
/*
* Include --cleanup=strip as well because we don't want the
* "# Conflicts:" messages.
*/
strvec_pushl(&argv, "--no-edit", "--cleanup=strip", NULL);
ret = run_command_v_opt(argv.v, RUN_GIT_CMD);
strvec_clear(&argv);
return ret;
}
static int commit_staged_changes(struct repository *r,
@ -4729,7 +4759,7 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)
goto release_todo_list;
}
} else if (!file_exists(get_todo_path(opts)))
return continue_single_pick(r);
return continue_single_pick(r, opts);
else if ((res = read_populate_todo(r, &todo_list, opts)))
goto release_todo_list;
@ -4738,7 +4768,7 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)
if (refs_ref_exists(get_main_ref_store(r),
"CHERRY_PICK_HEAD") ||
refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD")) {
res = continue_single_pick(r);
res = continue_single_pick(r, opts);
if (res)
goto release_todo_list;
}