Skip to content

Commit 9044143

Browse files
artagnongitster
authored andcommitted
revert: Don't create invalid replay_opts in parse_args
The "--ff" command-line option cannot be used with some other command-line options. However, parse_args still parses these incompatible options into a replay_opts structure for use by the rest of the program. Although pick_commits, the current gatekeeper to the cherry-pick machinery, checks the validity of the replay_opts structure before before starting its operation, there will be multiple entry points to the cherry-pick machinery in future. To futureproof the code and catch these errors in one place, make sure that an invalid replay_opts structure is not created by parse_args in the first place. We still check the replay_opts structure for validity in pick_commits, but this is an assert() now to emphasize that it's the caller's responsibility to get it right. Inspired-by: Christian Couder <[email protected]> Mentored-by: Jonathan Nieder <[email protected]> Helped-by: Junio C Hamano <[email protected]> Signed-off-by: Ramkumar Ramachandra <[email protected]> Signed-off-by: Jonathan Nieder <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8964147 commit 9044143

File tree

1 file changed

+27
-11
lines changed

1 file changed

+27
-11
lines changed

builtin/revert.c

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,26 @@ static int option_parse_x(const struct option *opt,
8686
return 0;
8787
}
8888

89+
static void verify_opt_compatible(const char *me, const char *base_opt, ...)
90+
{
91+
const char *this_opt;
92+
va_list ap;
93+
94+
va_start(ap, base_opt);
95+
while ((this_opt = va_arg(ap, const char *))) {
96+
if (va_arg(ap, int))
97+
break;
98+
}
99+
va_end(ap);
100+
101+
if (this_opt)
102+
die(_("%s: %s cannot be used with %s"), me, this_opt, base_opt);
103+
}
104+
89105
static void parse_args(int argc, const char **argv, struct replay_opts *opts)
90106
{
91107
const char * const * usage_str = revert_or_cherry_pick_usage(opts);
108+
const char *me = action_name(opts);
92109
int noop;
93110
struct option options[] = {
94111
OPT_BOOLEAN('n', "no-commit", &opts->no_commit, "don't automatically commit"),
@@ -122,6 +139,13 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
122139
if (opts->commit_argc < 2)
123140
usage_with_options(usage_str, options);
124141

142+
if (opts->allow_ff)
143+
verify_opt_compatible(me, "--ff",
144+
"--signoff", opts->signoff,
145+
"--no-commit", opts->no_commit,
146+
"-x", opts->record_origin,
147+
"--edit", opts->edit,
148+
NULL);
125149
opts->commit_argv = argv;
126150
}
127151

@@ -569,17 +593,9 @@ static int pick_commits(struct replay_opts *opts)
569593
struct commit *commit;
570594

571595
setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
572-
if (opts->allow_ff) {
573-
if (opts->signoff)
574-
die(_("cherry-pick --ff cannot be used with --signoff"));
575-
if (opts->no_commit)
576-
die(_("cherry-pick --ff cannot be used with --no-commit"));
577-
if (opts->record_origin)
578-
die(_("cherry-pick --ff cannot be used with -x"));
579-
if (opts->edit)
580-
die(_("cherry-pick --ff cannot be used with --edit"));
581-
}
582-
596+
if (opts->allow_ff)
597+
assert(!(opts->signoff || opts->no_commit ||
598+
opts->record_origin || opts->edit));
583599
read_and_refresh_cache(opts);
584600

585601
prepare_revs(&revs, opts);

0 commit comments

Comments
 (0)