Merge branch 'pw/rebase-cleanup-merge-strategy-option-handling'

Clean-up of the code path that deals with merge strategy option
handling in "git rebase".

* pw/rebase-cleanup-merge-strategy-option-handling:
  rebase: remove a couple of redundant strategy tests
  rebase -m: fix serialization of strategy options
  rebase -m: cleanup --strategy-option handling
  sequencer: use struct strvec to store merge strategy options
  rebase: stop reading and writing unnecessary strategy state
This commit is contained in:
Junio C Hamano 2023-04-17 18:05:13 -07:00
commit 3c957e6d39
11 changed files with 115 additions and 179 deletions

18
alias.c
View File

@ -3,6 +3,7 @@
#include "alloc.h" #include "alloc.h"
#include "config.h" #include "config.h"
#include "gettext.h" #include "gettext.h"
#include "strbuf.h"
#include "string-list.h" #include "string-list.h"
struct config_alias_data { struct config_alias_data {
@ -46,6 +47,23 @@ void list_aliases(struct string_list *list)
read_early_config(config_alias_cb, &data); read_early_config(config_alias_cb, &data);
} }
void quote_cmdline(struct strbuf *buf, const char **argv)
{
for (const char **argp = argv; *argp; argp++) {
if (argp != argv)
strbuf_addch(buf, ' ');
strbuf_addch(buf, '"');
for (const char *p = *argp; *p; p++) {
const char c = *p;
if (c == '"' || c =='\\')
strbuf_addch(buf, '\\');
strbuf_addch(buf, c);
}
strbuf_addch(buf, '"');
}
}
#define SPLIT_CMDLINE_BAD_ENDING 1 #define SPLIT_CMDLINE_BAD_ENDING 1
#define SPLIT_CMDLINE_UNCLOSED_QUOTE 2 #define SPLIT_CMDLINE_UNCLOSED_QUOTE 2
#define SPLIT_CMDLINE_ARGC_OVERFLOW 3 #define SPLIT_CMDLINE_ARGC_OVERFLOW 3

View File

@ -1,9 +1,12 @@
#ifndef ALIAS_H #ifndef ALIAS_H
#define ALIAS_H #define ALIAS_H
struct strbuf;
struct string_list; struct string_list;
char *alias_lookup(const char *alias); char *alias_lookup(const char *alias);
/* Quote argv so buf can be parsed by split_cmdline() */
void quote_cmdline(struct strbuf *buf, const char **argv);
int split_cmdline(char *cmdline, const char ***argv); int split_cmdline(char *cmdline, const char ***argv);
/* Takes a negative value returned by split_cmdline */ /* Takes a negative value returned by split_cmdline */
const char *split_cmdline_strerror(int cmdline_errno); const char *split_cmdline_strerror(int cmdline_errno);

View File

@ -121,7 +121,8 @@ struct rebase_options {
struct string_list exec; struct string_list exec;
int allow_empty_message; int allow_empty_message;
int rebase_merges, rebase_cousins; int rebase_merges, rebase_cousins;
char *strategy, *strategy_opts; char *strategy;
struct string_list strategy_opts;
struct strbuf git_format_patch_opt; struct strbuf git_format_patch_opt;
int reschedule_failed_exec; int reschedule_failed_exec;
int reapply_cherry_picks; int reapply_cherry_picks;
@ -150,6 +151,7 @@ struct rebase_options {
.config_rebase_merges = -1, \ .config_rebase_merges = -1, \
.update_refs = -1, \ .update_refs = -1, \
.config_update_refs = -1, \ .config_update_refs = -1, \
.strategy_opts = STRING_LIST_INIT_NODUP,\
} }
static struct replay_opts get_replay_opts(const struct rebase_options *opts) static struct replay_opts get_replay_opts(const struct rebase_options *opts)
@ -183,8 +185,8 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
replay.default_strategy = NULL; replay.default_strategy = NULL;
} }
if (opts->strategy_opts) for (size_t i = 0; i < opts->strategy_opts.nr; i++)
parse_strategy_opts(&replay, opts->strategy_opts); strvec_push(&replay.xopts, opts->strategy_opts.items[i].string);
if (opts->squash_onto) { if (opts->squash_onto) {
oidcpy(&replay.squash_onto, opts->squash_onto); oidcpy(&replay.squash_onto, opts->squash_onto);
@ -492,24 +494,6 @@ static int read_basic_state(struct rebase_options *opts)
opts->gpg_sign_opt = xstrdup(buf.buf); opts->gpg_sign_opt = xstrdup(buf.buf);
} }
if (file_exists(state_dir_path("strategy", opts))) {
strbuf_reset(&buf);
if (!read_oneliner(&buf, state_dir_path("strategy", opts),
READ_ONELINER_WARN_MISSING))
return -1;
free(opts->strategy);
opts->strategy = xstrdup(buf.buf);
}
if (file_exists(state_dir_path("strategy_opts", opts))) {
strbuf_reset(&buf);
if (!read_oneliner(&buf, state_dir_path("strategy_opts", opts),
READ_ONELINER_WARN_MISSING))
return -1;
free(opts->strategy_opts);
opts->strategy_opts = xstrdup(buf.buf);
}
strbuf_release(&buf); strbuf_release(&buf);
return 0; return 0;
@ -527,12 +511,6 @@ static int rebase_write_basic_state(struct rebase_options *opts)
write_file(state_dir_path("quiet", opts), "%s", ""); write_file(state_dir_path("quiet", opts), "%s", "");
if (opts->flags & REBASE_VERBOSE) if (opts->flags & REBASE_VERBOSE)
write_file(state_dir_path("verbose", opts), "%s", ""); write_file(state_dir_path("verbose", opts), "%s", "");
if (opts->strategy)
write_file(state_dir_path("strategy", opts), "%s",
opts->strategy);
if (opts->strategy_opts)
write_file(state_dir_path("strategy_opts", opts), "%s",
opts->strategy_opts);
if (opts->allow_rerere_autoupdate > 0) if (opts->allow_rerere_autoupdate > 0)
write_file(state_dir_path("allow_rerere_autoupdate", opts), write_file(state_dir_path("allow_rerere_autoupdate", opts),
"-%s-rerere-autoupdate", "-%s-rerere-autoupdate",
@ -1089,7 +1067,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
struct object_id branch_base; struct object_id branch_base;
int ignore_whitespace = 0; int ignore_whitespace = 0;
const char *gpg_sign = NULL; const char *gpg_sign = NULL;
struct string_list strategy_options = STRING_LIST_INIT_NODUP;
struct object_id squash_onto; struct object_id squash_onto;
char *squash_onto_name = NULL; char *squash_onto_name = NULL;
char *keep_base_onto_name = NULL; char *keep_base_onto_name = NULL;
@ -1197,7 +1174,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
N_("use 'merge-base --fork-point' to refine upstream")), N_("use 'merge-base --fork-point' to refine upstream")),
OPT_STRING('s', "strategy", &options.strategy, OPT_STRING('s', "strategy", &options.strategy,
N_("strategy"), N_("use the given merge strategy")), N_("strategy"), N_("use the given merge strategy")),
OPT_STRING_LIST('X', "strategy-option", &strategy_options, OPT_STRING_LIST('X', "strategy-option", &options.strategy_opts,
N_("option"), N_("option"),
N_("pass the argument through to the merge " N_("pass the argument through to the merge "
"strategy")), "strategy")),
@ -1500,24 +1477,14 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
} else { } else {
/* REBASE_MERGE */ /* REBASE_MERGE */
if (ignore_whitespace) { if (ignore_whitespace) {
string_list_append(&strategy_options, string_list_append(&options.strategy_opts,
"ignore-space-change"); "ignore-space-change");
} }
} }
if (strategy_options.nr) { if (options.strategy_opts.nr && !options.strategy)
int i;
if (!options.strategy)
options.strategy = "ort"; options.strategy = "ort";
strbuf_reset(&buf);
for (i = 0; i < strategy_options.nr; i++)
strbuf_addf(&buf, " --%s",
strategy_options.items[i].string);
options.strategy_opts = xstrdup(buf.buf);
}
if (options.strategy) { if (options.strategy) {
options.strategy = xstrdup(options.strategy); options.strategy = xstrdup(options.strategy);
switch (options.type) { switch (options.type) {
@ -1898,10 +1865,9 @@ cleanup:
free(options.gpg_sign_opt); free(options.gpg_sign_opt);
string_list_clear(&options.exec, 0); string_list_clear(&options.exec, 0);
free(options.strategy); free(options.strategy);
free(options.strategy_opts); string_list_clear(&options.strategy_opts, 0);
strbuf_release(&options.git_format_patch_opt); strbuf_release(&options.git_format_patch_opt);
free(squash_onto_name); free(squash_onto_name);
free(keep_base_onto_name); free(keep_base_onto_name);
string_list_clear(&strategy_options, 0);
return !!ret; return !!ret;
} }

View File

@ -45,20 +45,6 @@ static const char * const *revert_or_cherry_pick_usage(struct replay_opts *opts)
return opts->action == REPLAY_REVERT ? revert_usage : cherry_pick_usage; return opts->action == REPLAY_REVERT ? revert_usage : cherry_pick_usage;
} }
static int option_parse_x(const struct option *opt,
const char *arg, int unset)
{
struct replay_opts **opts_ptr = opt->value;
struct replay_opts *opts = *opts_ptr;
if (unset)
return 0;
ALLOC_GROW(opts->xopts, opts->xopts_nr + 1, opts->xopts_alloc);
opts->xopts[opts->xopts_nr++] = xstrdup(arg);
return 0;
}
static int option_parse_m(const struct option *opt, static int option_parse_m(const struct option *opt,
const char *arg, int unset) const char *arg, int unset)
{ {
@ -116,8 +102,8 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
N_("select mainline parent"), option_parse_m), N_("select mainline parent"), option_parse_m),
OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto), OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto),
OPT_STRING(0, "strategy", &opts->strategy, N_("strategy"), N_("merge strategy")), OPT_STRING(0, "strategy", &opts->strategy, N_("strategy"), N_("merge strategy")),
OPT_CALLBACK('X', "strategy-option", &opts, N_("option"), OPT_STRVEC('X', "strategy-option", &opts->xopts, N_("option"),
N_("option for merge strategy"), option_parse_x), N_("option for merge strategy")),
{ OPTION_STRING, 'S', "gpg-sign", &opts->gpg_sign, N_("key-id"), { OPTION_STRING, 'S', "gpg-sign", &opts->gpg_sign, N_("key-id"),
N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
OPT_END() OPT_END()
@ -178,7 +164,7 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
"--signoff", opts->signoff, "--signoff", opts->signoff,
"--mainline", opts->mainline, "--mainline", opts->mainline,
"--strategy", opts->strategy ? 1 : 0, "--strategy", opts->strategy ? 1 : 0,
"--strategy-option", opts->xopts ? 1 : 0, "--strategy-option", opts->xopts.nr ? 1 : 0,
"-x", opts->record_origin, "-x", opts->record_origin,
"--ff", opts->allow_ff, "--ff", opts->allow_ff,
"--rerere-autoupdate", opts->allow_rerere_auto == RERERE_AUTOUPDATE, "--rerere-autoupdate", opts->allow_rerere_auto == RERERE_AUTOUPDATE,

View File

@ -210,6 +210,22 @@ int parse_opt_string_list(const struct option *opt, const char *arg, int unset)
return 0; return 0;
} }
int parse_opt_strvec(const struct option *opt, const char *arg, int unset)
{
struct strvec *v = opt->value;
if (unset) {
strvec_clear(v);
return 0;
}
if (!arg)
return -1;
strvec_push(v, arg);
return 0;
}
int parse_opt_noop_cb(const struct option *opt, const char *arg, int unset) int parse_opt_noop_cb(const struct option *opt, const char *arg, int unset)
{ {
return 0; return 0;

View File

@ -287,6 +287,15 @@ struct option {
.help = (h), \ .help = (h), \
.callback = &parse_opt_string_list, \ .callback = &parse_opt_string_list, \
} }
#define OPT_STRVEC(s, l, v, a, h) { \
.type = OPTION_CALLBACK, \
.short_name = (s), \
.long_name = (l), \
.value = (v), \
.argh = (a), \
.help = (h), \
.callback = &parse_opt_strvec, \
}
#define OPT_UYN(s, l, v, h) { \ #define OPT_UYN(s, l, v, h) { \
.type = OPTION_CALLBACK, \ .type = OPTION_CALLBACK, \
.short_name = (s), \ .short_name = (s), \
@ -480,6 +489,7 @@ int parse_opt_commits(const struct option *, const char *, int);
int parse_opt_commit(const struct option *, const char *, int); int parse_opt_commit(const struct option *, const char *, int);
int parse_opt_tertiary(const struct option *, const char *, int); int parse_opt_tertiary(const struct option *, const char *, int);
int parse_opt_string_list(const struct option *, const char *, int); int parse_opt_string_list(const struct option *, const char *, int);
int parse_opt_strvec(const struct option *, const char *, int);
int parse_opt_noop_cb(const struct option *, const char *, int); int parse_opt_noop_cb(const struct option *, const char *, int);
int parse_opt_passthru(const struct option *, const char *, int); int parse_opt_passthru(const struct option *, const char *, int);
int parse_opt_passthru_argv(const struct option *, const char *, int); int parse_opt_passthru_argv(const struct option *, const char *, int);

View File

@ -359,9 +359,7 @@ void replay_opts_release(struct replay_opts *opts)
free(opts->reflog_action); free(opts->reflog_action);
free(opts->default_strategy); free(opts->default_strategy);
free(opts->strategy); free(opts->strategy);
for (size_t i = 0; i < opts->xopts_nr; i++) strvec_clear (&opts->xopts);
free(opts->xopts[i]);
free(opts->xopts);
strbuf_release(&opts->current_fixups); strbuf_release(&opts->current_fixups);
if (opts->revs) if (opts->revs)
release_revisions(opts->revs); release_revisions(opts->revs);
@ -699,8 +697,8 @@ static int do_recursive_merge(struct repository *r,
next_tree = next ? repo_get_commit_tree(r, next) : empty_tree(r); next_tree = next ? repo_get_commit_tree(r, next) : empty_tree(r);
base_tree = base ? repo_get_commit_tree(r, base) : empty_tree(r); base_tree = base ? repo_get_commit_tree(r, base) : empty_tree(r);
for (i = 0; i < opts->xopts_nr; i++) for (i = 0; i < opts->xopts.nr; i++)
parse_merge_opt(&o, opts->xopts[i]); parse_merge_opt(&o, opts->xopts.v[i]);
if (!opts->strategy || !strcmp(opts->strategy, "ort")) { if (!opts->strategy || !strcmp(opts->strategy, "ort")) {
memset(&result, 0, sizeof(result)); memset(&result, 0, sizeof(result));
@ -2336,7 +2334,7 @@ static int do_pick_commit(struct repository *r,
commit_list_insert(base, &common); commit_list_insert(base, &common);
commit_list_insert(next, &remotes); commit_list_insert(next, &remotes);
res |= try_merge_command(r, opts->strategy, res |= try_merge_command(r, opts->strategy,
opts->xopts_nr, (const char **)opts->xopts, opts->xopts.nr, opts->xopts.v,
common, oid_to_hex(&head), remotes); common, oid_to_hex(&head), remotes);
free_commit_list(common); free_commit_list(common);
free_commit_list(remotes); free_commit_list(remotes);
@ -2909,8 +2907,7 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
else if (!strcmp(key, "options.gpg-sign")) else if (!strcmp(key, "options.gpg-sign"))
git_config_string_dup(&opts->gpg_sign, key, value); git_config_string_dup(&opts->gpg_sign, key, value);
else if (!strcmp(key, "options.strategy-option")) { else if (!strcmp(key, "options.strategy-option")) {
ALLOC_GROW(opts->xopts, opts->xopts_nr + 1, opts->xopts_alloc); strvec_push(&opts->xopts, value);
opts->xopts[opts->xopts_nr++] = xstrdup(value);
} else if (!strcmp(key, "options.allow-rerere-auto")) } else if (!strcmp(key, "options.allow-rerere-auto"))
opts->allow_rerere_auto = opts->allow_rerere_auto =
git_config_bool_or_int(key, value, &error_flag) ? git_config_bool_or_int(key, value, &error_flag) ?
@ -2927,27 +2924,27 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
return 0; return 0;
} }
void parse_strategy_opts(struct replay_opts *opts, char *raw_opts) static void parse_strategy_opts(struct replay_opts *opts, char *raw_opts)
{ {
int i; int i;
int count; int count;
const char **argv;
char *strategy_opts_string = raw_opts; char *strategy_opts_string = raw_opts;
if (*strategy_opts_string == ' ') if (*strategy_opts_string == ' ')
strategy_opts_string++; strategy_opts_string++;
count = split_cmdline(strategy_opts_string, count = split_cmdline(strategy_opts_string, &argv);
(const char ***)&opts->xopts);
if (count < 0) if (count < 0)
die(_("could not split '%s': %s"), strategy_opts_string, BUG("could not split '%s': %s", strategy_opts_string,
split_cmdline_strerror(count)); split_cmdline_strerror(count));
opts->xopts_nr = count; for (i = 0; i < count; i++) {
for (i = 0; i < opts->xopts_nr; i++) { const char *arg = argv[i];
const char *arg = opts->xopts[i];
skip_prefix(arg, "--", &arg); skip_prefix(arg, "--", &arg);
opts->xopts[i] = xstrdup(arg); strvec_push(&opts->xopts, arg);
} }
free(argv);
} }
static void read_strategy_opts(struct replay_opts *opts, struct strbuf *buf) static void read_strategy_opts(struct replay_opts *opts, struct strbuf *buf)
@ -2955,7 +2952,6 @@ static void read_strategy_opts(struct replay_opts *opts, struct strbuf *buf)
strbuf_reset(buf); strbuf_reset(buf);
if (!read_oneliner(buf, rebase_path_strategy(), 0)) if (!read_oneliner(buf, rebase_path_strategy(), 0))
return; return;
free(opts->strategy);
opts->strategy = strbuf_detach(buf, NULL); opts->strategy = strbuf_detach(buf, NULL);
if (!read_oneliner(buf, rebase_path_strategy_opts(), 0)) if (!read_oneliner(buf, rebase_path_strategy_opts(), 0))
return; return;
@ -3064,12 +3060,13 @@ done_rebase_i:
static void write_strategy_opts(struct replay_opts *opts) static void write_strategy_opts(struct replay_opts *opts)
{ {
int i;
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
for (i = 0; i < opts->xopts_nr; ++i) /*
strbuf_addf(&buf, " --%s", opts->xopts[i]); * Quote strategy options so that they can be read correctly
* by split_cmdline().
*/
quote_cmdline(&buf, opts->xopts.v);
write_file(rebase_path_strategy_opts(), "%s\n", buf.buf); write_file(rebase_path_strategy_opts(), "%s\n", buf.buf);
strbuf_release(&buf); strbuf_release(&buf);
} }
@ -3092,7 +3089,7 @@ int write_basic_state(struct replay_opts *opts, const char *head_name,
write_file(rebase_path_verbose(), "%s", ""); write_file(rebase_path_verbose(), "%s", "");
if (opts->strategy) if (opts->strategy)
write_file(rebase_path_strategy(), "%s\n", opts->strategy); write_file(rebase_path_strategy(), "%s\n", opts->strategy);
if (opts->xopts_nr > 0) if (opts->xopts.nr > 0)
write_strategy_opts(opts); write_strategy_opts(opts);
if (opts->allow_rerere_auto == RERERE_AUTOUPDATE) if (opts->allow_rerere_auto == RERERE_AUTOUPDATE)
@ -3461,13 +3458,10 @@ static int save_opts(struct replay_opts *opts)
if (opts->gpg_sign) if (opts->gpg_sign)
res |= git_config_set_in_file_gently(opts_file, res |= git_config_set_in_file_gently(opts_file,
"options.gpg-sign", opts->gpg_sign); "options.gpg-sign", opts->gpg_sign);
if (opts->xopts) { for (size_t i = 0; i < opts->xopts.nr; i++)
int i;
for (i = 0; i < opts->xopts_nr; i++)
res |= git_config_set_multivar_in_file_gently(opts_file, res |= git_config_set_multivar_in_file_gently(opts_file,
"options.strategy-option", "options.strategy-option",
opts->xopts[i], "^$", 0); opts->xopts.v[i], "^$", 0);
}
if (opts->allow_rerere_auto) if (opts->allow_rerere_auto)
res |= git_config_set_in_file_gently(opts_file, res |= git_config_set_in_file_gently(opts_file,
"options.allow-rerere-auto", "options.allow-rerere-auto",
@ -3879,7 +3873,7 @@ static int do_merge(struct repository *r,
struct commit *head_commit, *merge_commit, *i; struct commit *head_commit, *merge_commit, *i;
struct commit_list *bases, *j; struct commit_list *bases, *j;
struct commit_list *to_merge = NULL, **tail = &to_merge; struct commit_list *to_merge = NULL, **tail = &to_merge;
const char *strategy = !opts->xopts_nr && const char *strategy = !opts->xopts.nr &&
(!opts->strategy || (!opts->strategy ||
!strcmp(opts->strategy, "recursive") || !strcmp(opts->strategy, "recursive") ||
!strcmp(opts->strategy, "ort")) ? !strcmp(opts->strategy, "ort")) ?
@ -4063,9 +4057,9 @@ static int do_merge(struct repository *r,
strvec_push(&cmd.args, "octopus"); strvec_push(&cmd.args, "octopus");
else { else {
strvec_push(&cmd.args, strategy); strvec_push(&cmd.args, strategy);
for (k = 0; k < opts->xopts_nr; k++) for (k = 0; k < opts->xopts.nr; k++)
strvec_pushf(&cmd.args, strvec_pushf(&cmd.args,
"-X%s", opts->xopts[k]); "-X%s", opts->xopts.v[k]);
} }
if (!(flags & TODO_EDIT_MERGE_MSG)) if (!(flags & TODO_EDIT_MERGE_MSG))
strvec_push(&cmd.args, "--no-edit"); strvec_push(&cmd.args, "--no-edit");

View File

@ -2,6 +2,7 @@
#define SEQUENCER_H #define SEQUENCER_H
#include "strbuf.h" #include "strbuf.h"
#include "strvec.h"
#include "wt-status.h" #include "wt-status.h"
struct commit; struct commit;
@ -60,8 +61,7 @@ struct replay_opts {
/* Merge strategy */ /* Merge strategy */
char *default_strategy; /* from config options */ char *default_strategy; /* from config options */
char *strategy; char *strategy;
char **xopts; struct strvec xopts;
size_t xopts_nr, xopts_alloc;
/* Reflog */ /* Reflog */
char *reflog_action; char *reflog_action;
@ -80,7 +80,12 @@ struct replay_opts {
/* Private use */ /* Private use */
const char *reflog_message; const char *reflog_message;
}; };
#define REPLAY_OPTS_INIT { .edit = -1, .action = -1, .current_fixups = STRBUF_INIT } #define REPLAY_OPTS_INIT { \
.edit = -1, \
.action = -1, \
.current_fixups = STRBUF_INIT, \
.xopts = STRVEC_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
@ -247,7 +252,6 @@ int read_oneliner(struct strbuf *buf,
const char *path, unsigned flags); const char *path, unsigned flags);
int read_author_script(const char *path, char **name, char **email, char **date, int read_author_script(const char *path, char **name, char **email, char **date,
int allow_missing); int allow_missing);
void parse_strategy_opts(struct replay_opts *opts, char *raw_opts);
int write_basic_state(struct replay_opts *opts, const char *head_name, int write_basic_state(struct replay_opts *opts, const char *head_name,
struct commit *onto, const struct object_id *orig_head); struct commit *onto, const struct object_id *orig_head);
void sequencer_post_commit_cleanup(struct repository *r, int verbose); void sequencer_post_commit_cleanup(struct repository *r, int verbose);

View File

@ -131,27 +131,6 @@ test_expect_success 'picking rebase' '
esac esac
' '
test_expect_success 'rebase -s funny -Xopt' '
test_when_finished "rm -fr test-bin funny.was.run" &&
mkdir test-bin &&
cat >test-bin/git-merge-funny <<-EOF &&
#!$SHELL_PATH
case "\$1" in --opt) ;; *) exit 2 ;; esac
shift &&
>funny.was.run &&
exec git merge-recursive "\$@"
EOF
chmod +x test-bin/git-merge-funny &&
git reset --hard &&
git checkout -b test-funny main^ &&
test_commit funny &&
(
PATH=./test-bin:$PATH &&
git rebase -s funny -Xopt main
) &&
test -f funny.was.run
'
test_expect_success 'rebase --skip works with two conflicts in a row' ' test_expect_success 'rebase --skip works with two conflicts in a row' '
git checkout second-side && git checkout second-side &&
tr "[A-Z]" "[a-z]" <newfile >tmp && tr "[A-Z]" "[a-z]" <newfile >tmp &&

View File

@ -62,61 +62,39 @@ test_expect_success 'rebase --continue remembers merge strategy and options' '
rm -fr .git/rebase-* && rm -fr .git/rebase-* &&
git reset --hard commit-new-file-F2-on-topic-branch && git reset --hard commit-new-file-F2-on-topic-branch &&
test_commit "commit-new-file-F3-on-topic-branch" F3 32 && test_commit "commit-new-file-F3-on-topic-branch" F3 32 &&
test_when_finished "rm -fr test-bin funny.was.run" && test_when_finished "rm -fr test-bin" &&
mkdir test-bin && mkdir test-bin &&
cat >test-bin/git-merge-funny <<-EOF &&
#!$SHELL_PATH
case "\$1" in --opt) ;; *) exit 2 ;; esac
shift &&
>funny.was.run &&
exec git merge-recursive "\$@"
EOF
chmod +x test-bin/git-merge-funny &&
(
PATH=./test-bin:$PATH &&
test_must_fail git rebase -s funny -Xopt main topic
) &&
test -f funny.was.run &&
rm funny.was.run &&
echo "Resolved" >F2 &&
git add F2 &&
(
PATH=./test-bin:$PATH &&
git rebase --continue
) &&
test -f funny.was.run
'
test_expect_success 'rebase -i --continue handles merge strategy and options' ' write_script test-bin/git-merge-funny <<-\EOF &&
rm -fr .git/rebase-* && printf "[%s]\n" $# "$1" "$2" "$3" "$5" >actual
git reset --hard commit-new-file-F2-on-topic-branch && shift 3 &&
test_commit "commit-new-file-F3-on-topic-branch-for-dash-i" F3 32 && exec git merge-recursive "$@"
test_when_finished "rm -fr test-bin funny.was.run funny.args" &&
mkdir test-bin &&
cat >test-bin/git-merge-funny <<-EOF &&
#!$SHELL_PATH
echo "\$@" >>funny.args
case "\$1" in --opt) ;; *) exit 2 ;; esac
case "\$2" in --foo) ;; *) exit 2 ;; esac
case "\$4" in --) ;; *) exit 2 ;; esac
shift 2 &&
>funny.was.run &&
exec git merge-recursive "\$@"
EOF EOF
chmod +x test-bin/git-merge-funny &&
cat >expect <<-\EOF &&
[7]
[--option=arg with space]
[--op"tion\]
[--new
line ]
[--]
EOF
rm -f actual &&
( (
PATH=./test-bin:$PATH && PATH=./test-bin:$PATH &&
test_must_fail git rebase -i -s funny -Xopt -Xfoo main topic test_must_fail git rebase -s funny -X"option=arg with space" \
-Xop\"tion\\ -X"new${LF}line " main topic
) && ) &&
test -f funny.was.run && test_cmp expect actual &&
rm funny.was.run && rm actual &&
echo "Resolved" >F2 && echo "Resolved" >F2 &&
git add F2 && git add F2 &&
( (
PATH=./test-bin:$PATH && PATH=./test-bin:$PATH &&
git rebase --continue git rebase --continue
) && ) &&
test -f funny.was.run test_cmp expect actual
' '
test_expect_success 'rebase -r passes merge strategy options correctly' ' test_expect_success 'rebase -r passes merge strategy options correctly' '

View File

@ -40,24 +40,6 @@ test_expect_success 'setup' '
EOF EOF
' '
test_expect_success 'bad -X <strategy-option> arguments: unclosed quote' '
cat >expect <<-\EOF &&
fatal: could not split '\''--bad'\'': unclosed quote
EOF
test_expect_code 128 git rebase -X"bad argument\"" side main >out 2>actual &&
test_must_be_empty out &&
test_cmp expect actual
'
test_expect_success 'bad -X <strategy-option> arguments: bad escape' '
cat >expect <<-\EOF &&
fatal: could not split '\''--bad'\'': cmdline ends with \
EOF
test_expect_code 128 git rebase -X"bad escape \\" side main >out 2>actual &&
test_must_be_empty out &&
test_cmp expect actual
'
test_expect_success '--ignore-whitespace works with apply backend' ' test_expect_success '--ignore-whitespace works with apply backend' '
test_must_fail git rebase --apply main side && test_must_fail git rebase --apply main side &&
git rebase --abort && git rebase --abort &&