mirror of
https://github.com/git/git.git
synced 2025-12-12 20:36:24 +01:00
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:
@@ -182,7 +182,7 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
|
|||||||
"--signoff", opts->signoff,
|
"--signoff", opts->signoff,
|
||||||
"--no-commit", opts->no_commit,
|
"--no-commit", opts->no_commit,
|
||||||
"-x", opts->record_origin,
|
"-x", opts->record_origin,
|
||||||
"--edit", opts->edit,
|
"--edit", opts->edit > 0,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (cmd) {
|
if (cmd) {
|
||||||
@@ -230,8 +230,6 @@ int cmd_revert(int argc, const char **argv, const char *prefix)
|
|||||||
struct replay_opts opts = REPLAY_OPTS_INIT;
|
struct replay_opts opts = REPLAY_OPTS_INIT;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (isatty(0))
|
|
||||||
opts.edit = 1;
|
|
||||||
opts.action = REPLAY_REVERT;
|
opts.action = REPLAY_REVERT;
|
||||||
sequencer_init_config(&opts);
|
sequencer_init_config(&opts);
|
||||||
res = run_sequencer(argc, argv, &opts);
|
res = run_sequencer(argc, argv, &opts);
|
||||||
|
|||||||
52
sequencer.c
52
sequencer.c
@@ -2032,13 +2032,24 @@ static void record_in_rewritten(struct object_id *oid,
|
|||||||
flush_rewritten_pending();
|
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,
|
static int do_pick_commit(struct repository *r,
|
||||||
struct todo_item *item,
|
struct todo_item *item,
|
||||||
struct replay_opts *opts,
|
struct replay_opts *opts,
|
||||||
int final_fixup, int *check_todo)
|
int final_fixup, int *check_todo)
|
||||||
{
|
{
|
||||||
unsigned int flags = opts->edit ? EDIT_MSG : 0;
|
unsigned int flags = should_edit(opts) ? EDIT_MSG : 0;
|
||||||
const char *msg_file = opts->edit ? NULL : git_path_merge_msg(r);
|
const char *msg_file = should_edit(opts) ? NULL : git_path_merge_msg(r);
|
||||||
struct object_id head;
|
struct object_id head;
|
||||||
struct commit *base, *next, *parent;
|
struct commit *base, *next, *parent;
|
||||||
const char *base_label, *next_label;
|
const char *base_label, *next_label;
|
||||||
@@ -3283,9 +3294,9 @@ static int save_opts(struct replay_opts *opts)
|
|||||||
if (opts->no_commit)
|
if (opts->no_commit)
|
||||||
res |= git_config_set_in_file_gently(opts_file,
|
res |= git_config_set_in_file_gently(opts_file,
|
||||||
"options.no-commit", "true");
|
"options.no-commit", "true");
|
||||||
if (opts->edit)
|
if (opts->edit >= 0)
|
||||||
res |= git_config_set_in_file_gently(opts_file,
|
res |= git_config_set_in_file_gently(opts_file, "options.edit",
|
||||||
"options.edit", "true");
|
opts->edit ? "true" : "false");
|
||||||
if (opts->allow_empty)
|
if (opts->allow_empty)
|
||||||
res |= git_config_set_in_file_gently(opts_file,
|
res |= git_config_set_in_file_gently(opts_file,
|
||||||
"options.allow-empty", "true");
|
"options.allow-empty", "true");
|
||||||
@@ -4259,7 +4270,7 @@ static int pick_commits(struct repository *r,
|
|||||||
prev_reflog_action = xstrdup(getenv(GIT_REFLOG_ACTION));
|
prev_reflog_action = xstrdup(getenv(GIT_REFLOG_ACTION));
|
||||||
if (opts->allow_ff)
|
if (opts->allow_ff)
|
||||||
assert(!(opts->signoff || opts->no_commit ||
|
assert(!(opts->signoff || opts->no_commit ||
|
||||||
opts->record_origin || opts->edit ||
|
opts->record_origin || should_edit(opts) ||
|
||||||
opts->committer_date_is_author_date ||
|
opts->committer_date_is_author_date ||
|
||||||
opts->ignore_date));
|
opts->ignore_date));
|
||||||
if (read_and_refresh_cache(r, opts))
|
if (read_and_refresh_cache(r, opts))
|
||||||
@@ -4552,14 +4563,33 @@ cleanup_head_ref:
|
|||||||
return sequencer_remove_state(opts);
|
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") &&
|
if (!refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD") &&
|
||||||
!refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD"))
|
!refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD"))
|
||||||
return error(_("no cherry-pick or revert in progress"));
|
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,
|
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;
|
goto release_todo_list;
|
||||||
}
|
}
|
||||||
} else if (!file_exists(get_todo_path(opts)))
|
} 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)))
|
else if ((res = read_populate_todo(r, &todo_list, opts)))
|
||||||
goto release_todo_list;
|
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),
|
if (refs_ref_exists(get_main_ref_store(r),
|
||||||
"CHERRY_PICK_HEAD") ||
|
"CHERRY_PICK_HEAD") ||
|
||||||
refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD")) {
|
refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD")) {
|
||||||
res = continue_single_pick(r);
|
res = continue_single_pick(r, opts);
|
||||||
if (res)
|
if (res)
|
||||||
goto release_todo_list;
|
goto release_todo_list;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,8 +31,10 @@ enum commit_msg_cleanup_mode {
|
|||||||
struct replay_opts {
|
struct replay_opts {
|
||||||
enum replay_action action;
|
enum replay_action action;
|
||||||
|
|
||||||
/* Boolean options */
|
/* Tri-state options: unspecified, false, or true */
|
||||||
int edit;
|
int edit;
|
||||||
|
|
||||||
|
/* Boolean options */
|
||||||
int record_origin;
|
int record_origin;
|
||||||
int no_commit;
|
int no_commit;
|
||||||
int signoff;
|
int signoff;
|
||||||
@@ -71,7 +73,7 @@ struct replay_opts {
|
|||||||
/* Only used by REPLAY_NONE */
|
/* Only used by REPLAY_NONE */
|
||||||
struct rev_info *revs;
|
struct rev_info *revs;
|
||||||
};
|
};
|
||||||
#define REPLAY_OPTS_INIT { .action = -1, .current_fixups = STRBUF_INIT }
|
#define REPLAY_OPTS_INIT { .edit = -1, .action = -1, .current_fixups = STRBUF_INIT }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that ordering matters in this enum. Not only must it match the mapping
|
* Note that ordering matters in this enum. Not only must it match the mapping
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ test_expect_success 'cherry-pick persists opts correctly' '
|
|||||||
# gets interrupted, use a high-enough number that is larger
|
# gets interrupted, use a high-enough number that is larger
|
||||||
# than the number of parents of any commit we have created
|
# than the number of parents of any commit we have created
|
||||||
mainline=4 &&
|
mainline=4 &&
|
||||||
test_expect_code 128 git cherry-pick -s -m $mainline --strategy=recursive -X patience -X ours initial..anotherpick &&
|
test_expect_code 128 git cherry-pick -s -m $mainline --strategy=recursive -X patience -X ours --edit initial..anotherpick &&
|
||||||
test_path_is_dir .git/sequencer &&
|
test_path_is_dir .git/sequencer &&
|
||||||
test_path_is_file .git/sequencer/head &&
|
test_path_is_file .git/sequencer/head &&
|
||||||
test_path_is_file .git/sequencer/todo &&
|
test_path_is_file .git/sequencer/todo &&
|
||||||
@@ -84,6 +84,36 @@ test_expect_success 'cherry-pick persists opts correctly' '
|
|||||||
ours
|
ours
|
||||||
EOF
|
EOF
|
||||||
git config --file=.git/sequencer/opts --get-all options.strategy-option >actual &&
|
git config --file=.git/sequencer/opts --get-all options.strategy-option >actual &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
echo "true" >expect &&
|
||||||
|
git config --file=.git/sequencer/opts --get-all options.edit >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'revert persists opts correctly' '
|
||||||
|
pristine_detach initial &&
|
||||||
|
# to make sure that the session to revert a sequence
|
||||||
|
# gets interrupted, revert commits that are not in the history
|
||||||
|
# of HEAD.
|
||||||
|
test_expect_code 1 git revert -s --strategy=recursive -X patience -X ours --no-edit picked yetanotherpick &&
|
||||||
|
test_path_is_dir .git/sequencer &&
|
||||||
|
test_path_is_file .git/sequencer/head &&
|
||||||
|
test_path_is_file .git/sequencer/todo &&
|
||||||
|
test_path_is_file .git/sequencer/opts &&
|
||||||
|
echo "true" >expect &&
|
||||||
|
git config --file=.git/sequencer/opts --get-all options.signoff >actual &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
echo "recursive" >expect &&
|
||||||
|
git config --file=.git/sequencer/opts --get-all options.strategy >actual &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
patience
|
||||||
|
ours
|
||||||
|
EOF
|
||||||
|
git config --file=.git/sequencer/opts --get-all options.strategy-option >actual &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
echo "false" >expect &&
|
||||||
|
git config --file=.git/sequencer/opts --get-all options.edit >actual &&
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user