Skip to content

Commit 82fd285

Browse files
committed
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
2 parents 22eee7f + 39edfd5 commit 82fd285

File tree

4 files changed

+77
-17
lines changed

4 files changed

+77
-17
lines changed

builtin/revert.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
182182
"--signoff", opts->signoff,
183183
"--no-commit", opts->no_commit,
184184
"-x", opts->record_origin,
185-
"--edit", opts->edit,
185+
"--edit", opts->edit > 0,
186186
NULL);
187187

188188
if (cmd) {
@@ -230,8 +230,6 @@ int cmd_revert(int argc, const char **argv, const char *prefix)
230230
struct replay_opts opts = REPLAY_OPTS_INIT;
231231
int res;
232232

233-
if (isatty(0))
234-
opts.edit = 1;
235233
opts.action = REPLAY_REVERT;
236234
sequencer_init_config(&opts);
237235
res = run_sequencer(argc, argv, &opts);

sequencer.c

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,13 +2032,24 @@ static void record_in_rewritten(struct object_id *oid,
20322032
flush_rewritten_pending();
20332033
}
20342034

2035+
static int should_edit(struct replay_opts *opts) {
2036+
if (opts->edit < 0)
2037+
/*
2038+
* Note that we only handle the case of non-conflicted
2039+
* commits; continue_single_pick() handles the conflicted
2040+
* commits itself instead of calling this function.
2041+
*/
2042+
return (opts->action == REPLAY_REVERT && isatty(0)) ? 1 : 0;
2043+
return opts->edit;
2044+
}
2045+
20352046
static int do_pick_commit(struct repository *r,
20362047
struct todo_item *item,
20372048
struct replay_opts *opts,
20382049
int final_fixup, int *check_todo)
20392050
{
2040-
unsigned int flags = opts->edit ? EDIT_MSG : 0;
2041-
const char *msg_file = opts->edit ? NULL : git_path_merge_msg(r);
2051+
unsigned int flags = should_edit(opts) ? EDIT_MSG : 0;
2052+
const char *msg_file = should_edit(opts) ? NULL : git_path_merge_msg(r);
20422053
struct object_id head;
20432054
struct commit *base, *next, *parent;
20442055
const char *base_label, *next_label;
@@ -3283,9 +3294,9 @@ static int save_opts(struct replay_opts *opts)
32833294
if (opts->no_commit)
32843295
res |= git_config_set_in_file_gently(opts_file,
32853296
"options.no-commit", "true");
3286-
if (opts->edit)
3287-
res |= git_config_set_in_file_gently(opts_file,
3288-
"options.edit", "true");
3297+
if (opts->edit >= 0)
3298+
res |= git_config_set_in_file_gently(opts_file, "options.edit",
3299+
opts->edit ? "true" : "false");
32893300
if (opts->allow_empty)
32903301
res |= git_config_set_in_file_gently(opts_file,
32913302
"options.allow-empty", "true");
@@ -4259,7 +4270,7 @@ static int pick_commits(struct repository *r,
42594270
prev_reflog_action = xstrdup(getenv(GIT_REFLOG_ACTION));
42604271
if (opts->allow_ff)
42614272
assert(!(opts->signoff || opts->no_commit ||
4262-
opts->record_origin || opts->edit ||
4273+
opts->record_origin || should_edit(opts) ||
42634274
opts->committer_date_is_author_date ||
42644275
opts->ignore_date));
42654276
if (read_and_refresh_cache(r, opts))
@@ -4552,14 +4563,33 @@ static int pick_commits(struct repository *r,
45524563
return sequencer_remove_state(opts);
45534564
}
45544565

4555-
static int continue_single_pick(struct repository *r)
4566+
static int continue_single_pick(struct repository *r, struct replay_opts *opts)
45564567
{
4557-
const char *argv[] = { "commit", NULL };
4568+
struct strvec argv = STRVEC_INIT;
4569+
int ret;
45584570

45594571
if (!refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD") &&
45604572
!refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD"))
45614573
return error(_("no cherry-pick or revert in progress"));
4562-
return run_command_v_opt(argv, RUN_GIT_CMD);
4574+
4575+
strvec_push(&argv, "commit");
4576+
4577+
/*
4578+
* continue_single_pick() handles the case of recovering from a
4579+
* conflict. should_edit() doesn't handle that case; for a conflict,
4580+
* we want to edit if the user asked for it, or if they didn't specify
4581+
* and stdin is a tty.
4582+
*/
4583+
if (!opts->edit || (opts->edit < 0 && !isatty(0)))
4584+
/*
4585+
* Include --cleanup=strip as well because we don't want the
4586+
* "# Conflicts:" messages.
4587+
*/
4588+
strvec_pushl(&argv, "--no-edit", "--cleanup=strip", NULL);
4589+
4590+
ret = run_command_v_opt(argv.v, RUN_GIT_CMD);
4591+
strvec_clear(&argv);
4592+
return ret;
45634593
}
45644594

45654595
static int commit_staged_changes(struct repository *r,
@@ -4729,7 +4759,7 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)
47294759
goto release_todo_list;
47304760
}
47314761
} else if (!file_exists(get_todo_path(opts)))
4732-
return continue_single_pick(r);
4762+
return continue_single_pick(r, opts);
47334763
else if ((res = read_populate_todo(r, &todo_list, opts)))
47344764
goto release_todo_list;
47354765

@@ -4738,7 +4768,7 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)
47384768
if (refs_ref_exists(get_main_ref_store(r),
47394769
"CHERRY_PICK_HEAD") ||
47404770
refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD")) {
4741-
res = continue_single_pick(r);
4771+
res = continue_single_pick(r, opts);
47424772
if (res)
47434773
goto release_todo_list;
47444774
}

sequencer.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ enum commit_msg_cleanup_mode {
3131
struct replay_opts {
3232
enum replay_action action;
3333

34-
/* Boolean options */
34+
/* Tri-state options: unspecified, false, or true */
3535
int edit;
36+
37+
/* Boolean options */
3638
int record_origin;
3739
int no_commit;
3840
int signoff;
@@ -71,7 +73,7 @@ struct replay_opts {
7173
/* Only used by REPLAY_NONE */
7274
struct rev_info *revs;
7375
};
74-
#define REPLAY_OPTS_INIT { .action = -1, .current_fixups = STRBUF_INIT }
76+
#define REPLAY_OPTS_INIT { .edit = -1, .action = -1, .current_fixups = STRBUF_INIT }
7577

7678
/*
7779
* Note that ordering matters in this enum. Not only must it match the mapping

t/t3510-cherry-pick-sequence.sh

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ test_expect_success 'cherry-pick persists opts correctly' '
6565
# gets interrupted, use a high-enough number that is larger
6666
# than the number of parents of any commit we have created
6767
mainline=4 &&
68-
test_expect_code 128 git cherry-pick -s -m $mainline --strategy=recursive -X patience -X ours initial..anotherpick &&
68+
test_expect_code 128 git cherry-pick -s -m $mainline --strategy=recursive -X patience -X ours --edit initial..anotherpick &&
6969
test_path_is_dir .git/sequencer &&
7070
test_path_is_file .git/sequencer/head &&
7171
test_path_is_file .git/sequencer/todo &&
@@ -84,6 +84,36 @@ test_expect_success 'cherry-pick persists opts correctly' '
8484
ours
8585
EOF
8686
git config --file=.git/sequencer/opts --get-all options.strategy-option >actual &&
87+
test_cmp expect actual &&
88+
echo "true" >expect &&
89+
git config --file=.git/sequencer/opts --get-all options.edit >actual &&
90+
test_cmp expect actual
91+
'
92+
93+
test_expect_success 'revert persists opts correctly' '
94+
pristine_detach initial &&
95+
# to make sure that the session to revert a sequence
96+
# gets interrupted, revert commits that are not in the history
97+
# of HEAD.
98+
test_expect_code 1 git revert -s --strategy=recursive -X patience -X ours --no-edit picked yetanotherpick &&
99+
test_path_is_dir .git/sequencer &&
100+
test_path_is_file .git/sequencer/head &&
101+
test_path_is_file .git/sequencer/todo &&
102+
test_path_is_file .git/sequencer/opts &&
103+
echo "true" >expect &&
104+
git config --file=.git/sequencer/opts --get-all options.signoff >actual &&
105+
test_cmp expect actual &&
106+
echo "recursive" >expect &&
107+
git config --file=.git/sequencer/opts --get-all options.strategy >actual &&
108+
test_cmp expect actual &&
109+
cat >expect <<-\EOF &&
110+
patience
111+
ours
112+
EOF
113+
git config --file=.git/sequencer/opts --get-all options.strategy-option >actual &&
114+
test_cmp expect actual &&
115+
echo "false" >expect &&
116+
git config --file=.git/sequencer/opts --get-all options.edit >actual &&
87117
test_cmp expect actual
88118
'
89119

0 commit comments

Comments
 (0)