Merge branch 'jk/cherry-pick-0-mainline'
authorJunio C Hamano <gitster@pobox.com>
Fri, 17 Mar 2017 20:50:28 +0000 (13:50 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 17 Mar 2017 20:50:28 +0000 (13:50 -0700)
"git revert -m 0 $merge_commit" complained that reverting a merge
needs to say relative to which parent the reversion needs to
happen, as if "-m 0" weren't given. The correct diagnosis is that
"-m 0" does not refer to the first parent ("-m 1" does). This has
been fixed.

* jk/cherry-pick-0-mainline:
cherry-pick: detect bogus arguments to --mainline

1  2 
builtin/revert.c
diff --combined builtin/revert.c
index 4ca5b515449a355ae04f0ff496a8ee0b7143e29a,37df613ac7eae3e37122adcaf3db931f0a325134..345d9586a709c08a1095f2635833d075c45fe7be
@@@ -54,6 -54,24 +54,24 @@@ static int option_parse_x(const struct 
        return 0;
  }
  
+ static int option_parse_m(const struct option *opt,
+                         const char *arg, int unset)
+ {
+       struct replay_opts *replay = opt->value;
+       char *end;
+       if (unset) {
+               replay->mainline = 0;
+               return 0;
+       }
+       replay->mainline = strtol(arg, &end, 10);
+       if (*end || replay->mainline <= 0)
+               return opterror(opt, "expects a number greater than zero", 0);
+       return 0;
+ }
  LAST_ARG_MUST_BE_NULL
  static void verify_opt_compatible(const char *me, const char *base_opt, ...)
  {
@@@ -71,7 -89,7 +89,7 @@@
                die(_("%s: %s cannot be used with %s"), me, this_opt, base_opt);
  }
  
 -static void parse_args(int argc, const char **argv, struct replay_opts *opts)
 +static int run_sequencer(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);
                OPT_BOOL('e', "edit", &opts->edit, N_("edit the commit message")),
                OPT_NOOP_NOARG('r', NULL),
                OPT_BOOL('s', "signoff", &opts->signoff, N_("add Signed-off-by:")),
-               OPT_INTEGER('m', "mainline", &opts->mainline, N_("parent number")),
+               OPT_CALLBACK('m', "mainline", opts, N_("parent-number"),
+                            N_("select mainline parent"), option_parse_m),
                OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto),
                OPT_STRING(0, "strategy", &opts->strategy, N_("strategy"), N_("merge strategy")),
                OPT_CALLBACK('X', "strategy-option", &opts, N_("option"),
        if (opts->keep_redundant_commits)
                opts->allow_empty = 1;
  
 -      /* Set the subcommand */
 -      if (cmd == 'q')
 -              opts->subcommand = REPLAY_REMOVE_STATE;
 -      else if (cmd == 'c')
 -              opts->subcommand = REPLAY_CONTINUE;
 -      else if (cmd == 'a')
 -              opts->subcommand = REPLAY_ROLLBACK;
 -      else
 -              opts->subcommand = REPLAY_NONE;
 -
        /* Check for incompatible command line arguments */
 -      if (opts->subcommand != REPLAY_NONE) {
 +      if (cmd) {
                char *this_operation;
 -              if (opts->subcommand == REPLAY_REMOVE_STATE)
 +              if (cmd == 'q')
                        this_operation = "--quit";
 -              else if (opts->subcommand == REPLAY_CONTINUE)
 +              else if (cmd == 'c')
                        this_operation = "--continue";
                else {
 -                      assert(opts->subcommand == REPLAY_ROLLBACK);
 +                      assert(cmd == 'a');
                        this_operation = "--abort";
                }
  
                                "--edit", opts->edit,
                                NULL);
  
 -      if (opts->subcommand != REPLAY_NONE) {
 +      if (cmd) {
                opts->revs = NULL;
        } else {
                struct setup_revision_opt s_r_opt;
  
        if (argc > 1)
                usage_with_options(usage_str, options);
 +
 +      /* These option values will be free()d */
 +      opts->gpg_sign = xstrdup_or_null(opts->gpg_sign);
 +      opts->strategy = xstrdup_or_null(opts->strategy);
 +
 +      if (cmd == 'q')
 +              return sequencer_remove_state(opts);
 +      if (cmd == 'c')
 +              return sequencer_continue(opts);
 +      if (cmd == 'a')
 +              return sequencer_rollback(opts);
 +      return sequencer_pick_revisions(opts);
  }
  
  int cmd_revert(int argc, const char **argv, const char *prefix)
  {
 -      struct replay_opts opts;
 +      struct replay_opts opts = REPLAY_OPTS_INIT;
        int res;
  
 -      memset(&opts, 0, sizeof(opts));
        if (isatty(0))
                opts.edit = 1;
        opts.action = REPLAY_REVERT;
        git_config(git_default_config, NULL);
 -      parse_args(argc, argv, &opts);
 -      res = sequencer_pick_revisions(&opts);
 +      res = run_sequencer(argc, argv, &opts);
        if (res < 0)
                die(_("revert failed"));
        return res;
  
  int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
  {
 -      struct replay_opts opts;
 +      struct replay_opts opts = REPLAY_OPTS_INIT;
        int res;
  
 -      memset(&opts, 0, sizeof(opts));
        opts.action = REPLAY_PICK;
        git_config(git_default_config, NULL);
 -      parse_args(argc, argv, &opts);
 -      res = sequencer_pick_revisions(&opts);
 +      res = run_sequencer(argc, argv, &opts);
        if (res < 0)
                die(_("cherry-pick failed"));
        return res;