#include "cache.h"
#include "builtin.h"
#include "object.h"
#include "commit.h"
#include "tag.h"
#include "run-command.h"
#include "exec_cmd.h"
#include "utf8.h"
#include "parse-options.h"
#include "cache-tree.h"
#include "diff.h"
#include "revision.h"
#include "rerere.h"
#include "merge-recursive.h"
#include "refs.h"
#include "dir.h"
#include "sequencer.h"
/*
* This implements the builtins revert and cherry-pick.
*
* Copyright (c) 2007 Johannes E. Schindelin
*
* Based on git-revert.sh, which is
*
* Copyright (c) 2005 Linus Torvalds
* Copyright (c) 2005 Junio C Hamano
*/
static const char * const revert_usage[] = {
"git revert [options] <commit-ish>",
"git revert <subcommand>",
NULL
};
static const char * const cherry_pick_usage[] = {
"git cherry-pick [options] <commit-ish>",
"git cherry-pick <subcommand>",
NULL
};
enum replay_action { REVERT, CHERRY_PICK };
enum replay_subcommand {
REPLAY_NONE,
REPLAY_REMOVE_STATE,
REPLAY_CONTINUE,
REPLAY_ROLLBACK
};
struct replay_opts {
enum replay_action action;
enum replay_subcommand subcommand;
/* Boolean options */
int edit;
int record_origin;
int no_commit;
int signoff;
int allow_ff;
int allow_rerere_auto;
int mainline;
/* Merge strategy */
const char *strategy;
const char **xopts;
size_t xopts_nr, xopts_alloc;
/* Only used by REPLAY_NONE */
struct rev_info *revs;
};
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
static const char *action_name(const struct replay_opts *opts)
{
return opts->action == REVERT ? "revert" : "cherry-pick";
}
static char *get_encoding(const char *message);
static const char * const *revert_or_cherry_pick_usage(struct replay_opts *opts)
{
return opts->action == 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 void verify_opt_compatible(const char *me, const char *base_opt, ...)
{
const char *this_opt;
va_list ap;
va_start(ap, base_opt);
while ((this_opt = va_arg(ap, const char *))) {
if (va_arg(ap, int))
break;
}
va_end(ap);
if (this_opt)
die(_("%s: %s cannot be used with %s"), me, this_opt, base_opt);
}
static void verify_opt_mutually_compatible(const char *me, ...)
{
const char *opt1, *opt2 = NULL;
va_list ap;
va_start(ap, me);
while ((opt1 = va_arg(ap, const char *))) {
if (va_arg(ap, int))
break;
}
if (opt1) {
while ((opt2 = va_arg(ap, const char *))) {
if (va_arg(ap, int))
break;
}
}
if (opt1 && opt2)
die(_("%s: %s cannot be used with %s"), me, opt1, opt2);
}
static void parse_args(int argc, const char **argv, struct replay_opts *opts)
{
const char * const * usage_str = revert_or_cherry_pick_usage(opts);
const char *me = action_name(opts);
int remove_state = 0;
int contin = 0;
int rollback = 0;
struct option options[] = {
OPT_BOOLEAN(0, "quit", &remove_state, "end revert or cherry-pick sequence"),
OPT_BOOLEAN(0, "continue", &contin, "resume revert or cherry-pick sequence"),
OPT_BOOLEAN(0, "abort", &rollback, "cancel revert or cherry-pick sequence"),
OPT_BOOLEAN('n', "no-commit", &opts->no_commit, "don't automatically commit"),
OPT_BOOLEAN('e', "edit", &opts->edit, "edit the commit message"),
OPT_NOOP_NOARG(
|