Merge branch 'jk/cherry-pick-root-with-resolve'
authorJunio C Hamano <gitster@pobox.com>
Fri, 20 May 2011 03:37:19 +0000 (20:37 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 20 May 2011 03:37:19 +0000 (20:37 -0700)
* jk/cherry-pick-root-with-resolve:
t3503: test cherry picking and reverting root commits
revert: allow reverting a root commit
cherry-pick: handle root commits with external strategies

1  2 
builtin/merge.c
diff --combined builtin/merge.c
index 7eebb71491047b2df6231df500e5fc28db1881b4,8a0f6901f90c9728fb7521121ead030325ce3a45..5a2a1eb797c88990337f0b9cbb5dcabc73222a22
@@@ -56,7 -56,6 +56,7 @@@ static size_t use_strategies_nr, use_st
  static const char **xopts;
  static size_t xopts_nr, xopts_alloc;
  static const char *branch;
 +static char *branch_mergeoptions;
  static int option_renormalize;
  static int verbosity;
  static int allow_rerere_auto;
@@@ -504,34 -503,26 +504,34 @@@ cleanup
        strbuf_release(&bname);
  }
  
 +static void parse_branch_merge_options(char *bmo)
 +{
 +      const char **argv;
 +      int argc;
 +
 +      if (!bmo)
 +              return;
 +      argc = split_cmdline(bmo, &argv);
 +      if (argc < 0)
 +              die(_("Bad branch.%s.mergeoptions string: %s"), branch,
 +                  split_cmdline_strerror(argc));
 +      argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
 +      memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
 +      argc++;
 +      argv[0] = "branch.*.mergeoptions";
 +      parse_options(argc, argv, NULL, builtin_merge_options,
 +                    builtin_merge_usage, 0);
 +      free(argv);
 +}
 +
  static int git_merge_config(const char *k, const char *v, void *cb)
  {
        if (branch && !prefixcmp(k, "branch.") &&
                !prefixcmp(k + 7, branch) &&
                !strcmp(k + 7 + strlen(branch), ".mergeoptions")) {
 -              const char **argv;
 -              int argc;
 -              char *buf;
 -
 -              buf = xstrdup(v);
 -              argc = split_cmdline(buf, &argv);
 -              if (argc < 0)
 -                      die(_("Bad branch.%s.mergeoptions string: %s"), branch,
 -                          split_cmdline_strerror(argc));
 -              argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
 -              memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
 -              argc++;
 -              parse_options(argc, argv, NULL, builtin_merge_options,
 -                            builtin_merge_usage, 0);
 -              free(buf);
 +              free(branch_mergeoptions);
 +              branch_mergeoptions = xstrdup(v);
 +              return 0;
        }
  
        if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat"))
                if (is_bool && shortlog_len)
                        shortlog_len = DEFAULT_MERGE_LOG_LEN;
                return 0;
 +      } else if (!strcmp(k, "merge.ff")) {
 +              int boolval = git_config_maybe_bool(k, v);
 +              if (0 <= boolval) {
 +                      allow_fast_forward = boolval;
 +              } else if (v && !strcmp(v, "only")) {
 +                      allow_fast_forward = 1;
 +                      fast_forward_only = 1;
 +              } /* do not barf on values from future versions of git */
 +              return 0;
        } else if (!strcmp(k, "merge.defaulttoupstream")) {
                default_to_upstream = git_config_bool(k, v);
                return 0;
@@@ -608,6 -590,14 +608,14 @@@ static void write_tree_trivial(unsigne
                die(_("git write-tree failed to write a tree"));
  }
  
+ static const char *merge_argument(struct commit *commit)
+ {
+       if (commit)
+               return sha1_to_hex(commit->object.sha1);
+       else
+               return EMPTY_TREE_SHA1_HEX;
+ }
  int try_merge_command(const char *strategy, size_t xopts_nr,
                      const char **xopts, struct commit_list *common,
                      const char *head_arg, struct commit_list *remotes)
                args[i++] = s;
        }
        for (j = common; j; j = j->next)
-               args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1));
+               args[i++] = xstrdup(merge_argument(j->item));
        args[i++] = "--";
        args[i++] = head_arg;
        for (j = remotes; j; j = j->next)
-               args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1));
+               args[i++] = xstrdup(merge_argument(j->item));
        args[i] = NULL;
        ret = run_command_v_opt(args, RUN_GIT_CMD);
        strbuf_release(&buf);
@@@ -840,7 -830,7 +848,7 @@@ static void read_merge_msg(void
  {
        strbuf_reset(&merge_msg);
        if (strbuf_read_file(&merge_msg, git_path("MERGE_MSG"), 0) < 0)
 -              die_errno("Could not read from '%s'", git_path("MERGE_MSG"));
 +              die_errno(_("Could not read from '%s'"), git_path("MERGE_MSG"));
  }
  
  static void run_prepare_commit_msg(void)
@@@ -980,16 -970,16 +988,16 @@@ static int setup_with_upstream(const ch
        const char **args;
  
        if (!branch)
 -              die("No current branch.");
 +              die(_("No current branch."));
        if (!branch->remote)
 -              die("No remote for the current branch.");
 +              die(_("No remote for the current branch."));
        if (!branch->merge_nr)
 -              die("No default upstream defined for the current branch.");
 +              die(_("No default upstream defined for the current branch."));
  
        args = xcalloc(branch->merge_nr + 1, sizeof(char *));
        for (i = 0; i < branch->merge_nr; i++) {
                if (!branch->merge[i]->dst)
 -                      die("No remote tracking branch for %s from %s",
 +                      die(_("No remote tracking branch for %s from %s"),
                            branch->merge[i]->src, branch->remote_name);
                args[i] = branch->merge[i]->dst;
        }
@@@ -1028,8 -1018,6 +1036,8 @@@ int cmd_merge(int argc, const char **ar
        if (diff_use_color_default == -1)
                diff_use_color_default = git_use_color_default;
  
 +      if (branch_mergeoptions)
 +              parse_branch_merge_options(branch_mergeoptions);
        argc = parse_options(argc, argv, prefix, builtin_merge_options,
                        builtin_merge_usage, 0);
  
        }
        if (file_exists(git_path("CHERRY_PICK_HEAD"))) {
                if (advice_resolve_conflict)
 -                      die("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
 -                          "Please, commit your changes before you can merge.");
 +                      die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
 +                          "Please, commit your changes before you can merge."));
                else
 -                      die("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).");
 +                      die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."));
        }
        resolve_undo_clear();
  
        if (!allow_fast_forward && fast_forward_only)
                die(_("You cannot combine --no-ff with --ff-only."));
  
 -      if (!argc && !abort_current_merge && default_to_upstream)
 -              argc = setup_with_upstream(&argv);
 -
 +      if (!abort_current_merge) {
 +              if (!argc && default_to_upstream)
 +                      argc = setup_with_upstream(&argv);
 +              else if (argc == 1 && !strcmp(argv[0], "-"))
 +                      argv[0] = "@{-1}";
 +      }
        if (!argc)
                usage_with_options(builtin_merge_usage,
                        builtin_merge_options);