revert: pass around rev-list args in already-parsed form

Since 7e2bfd3f (revert: allow cherry-picking more than one commit,
2010-07-02), the pick/revert machinery has kept track of the set of
commits to be cherry-picked or reverted using commit_argc and
commit_argv variables, storing the corresponding command-line
parameters.

Future callers as other commands are built in (am, rebase, sequencer)
may find it easier to pass rev-list options to this machinery in
already-parsed form.  Teach cmd_cherry_pick and cmd_revert to parse
the rev-list arguments in advance and pass the commit set to
pick_revisions() as a rev_info structure.

Original patch by Jonathan, tweaks and test from Ram.

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Improved-by: Ramkumar Ramachandra <artagnon@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jonathan Nieder 2011-08-13 12:06:23 -05:00 коммит произвёл Junio C Hamano
Родитель 093a309136
Коммит 7f13334e07
2 изменённых файлов: 34 добавлений и 24 удалений

Просмотреть файл

@ -60,13 +60,14 @@ struct replay_opts {
int allow_rerere_auto; int allow_rerere_auto;
int mainline; int mainline;
int commit_argc;
const char **commit_argv;
/* Merge strategy */ /* Merge strategy */
const char *strategy; const char *strategy;
const char **xopts; const char **xopts;
size_t xopts_nr, xopts_alloc; size_t xopts_nr, xopts_alloc;
/* Only used by REPLAY_NONE */
struct rev_info *revs;
}; };
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION" #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
@ -169,9 +170,9 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
die(_("program error")); die(_("program error"));
} }
opts->commit_argc = parse_options(argc, argv, NULL, options, usage_str, argc = parse_options(argc, argv, NULL, options, usage_str,
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_ARGV0 |
PARSE_OPT_KEEP_UNKNOWN); PARSE_OPT_KEEP_UNKNOWN);
/* Check for incompatible subcommands */ /* Check for incompatible subcommands */
verify_opt_mutually_compatible(me, verify_opt_mutually_compatible(me,
@ -213,9 +214,6 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
NULL); NULL);
} }
else if (opts->commit_argc < 2)
usage_with_options(usage_str, options);
if (opts->allow_ff) if (opts->allow_ff)
verify_opt_compatible(me, "--ff", verify_opt_compatible(me, "--ff",
"--signoff", opts->signoff, "--signoff", opts->signoff,
@ -223,7 +221,20 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
"-x", opts->record_origin, "-x", opts->record_origin,
"--edit", opts->edit, "--edit", opts->edit,
NULL); NULL);
opts->commit_argv = argv;
if (opts->subcommand != REPLAY_NONE) {
opts->revs = NULL;
} else {
opts->revs = xmalloc(sizeof(*opts->revs));
init_revisions(opts->revs, NULL);
opts->revs->no_walk = 1;
if (argc < 2)
usage_with_options(usage_str, options);
argc = setup_revisions(argc, argv, opts->revs, NULL);
}
if (argc > 1)
usage_with_options(usage_str, options);
} }
struct commit_message { struct commit_message {
@ -631,23 +642,15 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
return res; return res;
} }
static void prepare_revs(struct rev_info *revs, struct replay_opts *opts) static void prepare_revs(struct replay_opts *opts)
{ {
int argc;
init_revisions(revs, NULL);
revs->no_walk = 1;
if (opts->action != REVERT) if (opts->action != REVERT)
revs->reverse = 1; opts->revs->reverse ^= 1;
argc = setup_revisions(opts->commit_argc, opts->commit_argv, revs, NULL); if (prepare_revision_walk(opts->revs))
if (argc > 1)
usage(*revert_or_cherry_pick_usage(opts));
if (prepare_revision_walk(revs))
die(_("revision walk setup failed")); die(_("revision walk setup failed"));
if (!revs->commits) if (!opts->revs->commits)
die(_("empty commit set passed")); die(_("empty commit set passed"));
} }
@ -844,14 +847,13 @@ static void read_populate_opts(struct replay_opts **opts_ptr)
static void walk_revs_populate_todo(struct commit_list **todo_list, static void walk_revs_populate_todo(struct commit_list **todo_list,
struct replay_opts *opts) struct replay_opts *opts)
{ {
struct rev_info revs;
struct commit *commit; struct commit *commit;
struct commit_list **next; struct commit_list **next;
prepare_revs(&revs, opts); prepare_revs(opts);
next = todo_list; next = todo_list;
while ((commit = get_revision(&revs))) while ((commit = get_revision(opts->revs)))
next = commit_list_append(commit, next); next = commit_list_append(commit, next);
} }
@ -1075,6 +1077,9 @@ static int pick_revisions(struct replay_opts *opts)
struct commit_list *todo_list = NULL; struct commit_list *todo_list = NULL;
unsigned char sha1[20]; unsigned char sha1[20];
if (opts->subcommand == REPLAY_NONE)
assert(opts->revs);
read_and_refresh_cache(opts); read_and_refresh_cache(opts);
/* /*

Просмотреть файл

@ -461,4 +461,9 @@ test_expect_success 'malformed instruction sheet 2' '
test_must_fail git cherry-pick --continue test_must_fail git cherry-pick --continue
' '
test_expect_success 'empty commit set' '
pristine_detach initial &&
test_expect_code 128 git cherry-pick base..base
'
test_done test_done