Merge branch 'hu/cherry-pick-previous-branch'
authorJunio C Hamano <gitster@pobox.com>
Wed, 23 Oct 2013 20:21:35 +0000 (13:21 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 23 Oct 2013 20:21:35 +0000 (13:21 -0700)
"git cherry-pick" without further options would segfault.

Could use a follow-up to handle '-' after argv[1] better.

* hu/cherry-pick-previous-branch:
cherry-pick: handle "-" after parsing options

1  2 
builtin/revert.c
t/t3501-revert-cherry-pick.sh
diff --combined builtin/revert.c
index 52c35e75d90dc07f6a80362f200212e314a14ec8,38aaa16fa9328cb4d776001382d19cec82a73d8d..87659c9fdb749bf8cbf33ce71391fdfe284edd6d
@@@ -54,7 -54,6 +54,7 @@@ static int option_parse_x(const struct 
        return 0;
  }
  
 +LAST_ARG_MUST_BE_NULL
  static void verify_opt_compatible(const char *me, const char *base_opt, ...)
  {
        const char *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;
 -              }
 -      }
 -      va_end(ap);
 -
 -      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;
 +      int cmd = 0;
        struct option options[] = {
 -              OPT_BOOLEAN(0, "quit", &remove_state, N_("end revert or cherry-pick sequence")),
 -              OPT_BOOLEAN(0, "continue", &contin, N_("resume revert or cherry-pick sequence")),
 -              OPT_BOOLEAN(0, "abort", &rollback, N_("cancel revert or cherry-pick sequence")),
 -              OPT_BOOLEAN('n', "no-commit", &opts->no_commit, N_("don't automatically commit")),
 -              OPT_BOOLEAN('e', "edit", &opts->edit, N_("edit the commit message")),
 +              OPT_CMDMODE(0, "quit", &cmd, N_("end revert or cherry-pick sequence"), 'q'),
 +              OPT_CMDMODE(0, "continue", &cmd, N_("resume revert or cherry-pick sequence"), 'c'),
 +              OPT_CMDMODE(0, "abort", &cmd, N_("cancel revert or cherry-pick sequence"), 'a'),
 +              OPT_BOOL('n', "no-commit", &opts->no_commit, N_("don't automatically commit")),
 +              OPT_BOOL('e', "edit", &opts->edit, N_("edit the commit message")),
                OPT_NOOP_NOARG('r', NULL),
 -              OPT_BOOLEAN('s', "signoff", &opts->signoff, N_("add Signed-off-by:")),
 +              OPT_BOOL('s', "signoff", &opts->signoff, N_("add Signed-off-by:")),
                OPT_INTEGER('m', "mainline", &opts->mainline, N_("parent number")),
                OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto),
                OPT_STRING(0, "strategy", &opts->strategy, N_("strategy"), N_("merge strategy")),
  
        if (opts->action == REPLAY_PICK) {
                struct option cp_extra[] = {
 -                      OPT_BOOLEAN('x', NULL, &opts->record_origin, N_("append commit name")),
 -                      OPT_BOOLEAN(0, "ff", &opts->allow_ff, N_("allow fast-forward")),
 -                      OPT_BOOLEAN(0, "allow-empty", &opts->allow_empty, N_("preserve initially empty commits")),
 -                      OPT_BOOLEAN(0, "allow-empty-message", &opts->allow_empty_message, N_("allow commits with empty messages")),
 -                      OPT_BOOLEAN(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("keep redundant, empty commits")),
 +                      OPT_BOOL('x', NULL, &opts->record_origin, N_("append commit name")),
 +                      OPT_BOOL(0, "ff", &opts->allow_ff, N_("allow fast-forward")),
 +                      OPT_BOOL(0, "allow-empty", &opts->allow_empty, N_("preserve initially empty commits")),
 +                      OPT_BOOL(0, "allow-empty-message", &opts->allow_empty_message, N_("allow commits with empty messages")),
 +                      OPT_BOOL(0, "keep-redundant-commits", &opts->keep_redundant_commits, N_("keep redundant, empty commits")),
                        OPT_END(),
                };
                if (parse_options_concat(options, ARRAY_SIZE(options), cp_extra))
                        PARSE_OPT_KEEP_ARGV0 |
                        PARSE_OPT_KEEP_UNKNOWN);
  
 -      /* Check for incompatible subcommands */
 -      verify_opt_mutually_compatible(me,
 -                              "--quit", remove_state,
 -                              "--continue", contin,
 -                              "--abort", rollback,
 -                              NULL);
 -
        /* implies allow_empty */
        if (opts->keep_redundant_commits)
                opts->allow_empty = 1;
  
        /* Set the subcommand */
 -      if (remove_state)
 +      if (cmd == 'q')
                opts->subcommand = REPLAY_REMOVE_STATE;
 -      else if (contin)
 +      else if (cmd == 'c')
                opts->subcommand = REPLAY_CONTINUE;
 -      else if (rollback)
 +      else if (cmd == 'a')
                opts->subcommand = REPLAY_ROLLBACK;
        else
                opts->subcommand = REPLAY_NONE;
                opts->revs->no_walk = REVISION_WALK_NO_WALK_UNSORTED;
                if (argc < 2)
                        usage_with_options(usage_str, options);
+               if (!strcmp(argv[1], "-"))
+                       argv[1] = "@{-1}";
                memset(&s_r_opt, 0, sizeof(s_r_opt));
                s_r_opt.assume_dashdash = 1;
                argc = setup_revisions(argc, argv, opts->revs, &s_r_opt);
@@@ -202,8 -234,6 +204,6 @@@ int cmd_cherry_pick(int argc, const cha
        memset(&opts, 0, sizeof(opts));
        opts.action = REPLAY_PICK;
        git_config(git_default_config, NULL);
-       if (!strcmp(argv[1], "-"))
-               argv[1] = "@{-1}";
        parse_args(argc, argv, &opts);
        res = sequencer_pick_revisions(&opts);
        if (res < 0)
index bff6ffe08817ed0c057909aa1d3f93140cf6a3e0,12c246f7f47812e42c68467c2c5755f4d4c0339d..51f3bbb8af446dd24a835a8593475b59a73f6d1f
@@@ -100,7 -100,7 +100,7 @@@ test_expect_success 'revert forbidden o
  
  '
  
 -test_expect_success 'chery-pick on unborn branch' '
 +test_expect_success 'cherry-pick on unborn branch' '
        git checkout --orphan unborn &&
        git rm --cached -r . &&
        rm -rf * &&
@@@ -129,4 -129,16 +129,16 @@@ test_expect_success 'cherry-pick "-" i
        )
  '
  
+ test_expect_success 'cherry-pick "-" works with arguments' '
+       git checkout -b side-branch &&
+       test_commit change actual change &&
+       git checkout master &&
+       git cherry-pick -s - &&
+       echo "Signed-off-by: C O Mitter <committer@example.com>" >expect &&
+       git cat-file commit HEAD | grep ^Signed-off-by: >signoff &&
+       test_cmp expect signoff &&
+       echo change >expect &&
+       test_cmp expect actual
+ '
  test_done