merge: make branch.<name>.mergeoptions correctly override merge.<option>
authorJunio C Hamano <gitster@pobox.com>
Thu, 5 May 2011 00:42:51 +0000 (17:42 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 6 May 2011 22:01:56 +0000 (15:01 -0700)
The parsing of the additional command line parameters supplied to
the branch.<name>.mergeoptions configuration variable was implemented
at the wrong stage.  If any merge-related variable came after we read
branch.<name>.mergeoptions, the earlier value was overwritten.

We should first read all the merge.* configuration, override them by
reading from branch.<name>.mergeoptions and then finally read from
the command line.

This patch should fix it, even though I now strongly suspect that
branch.<name>.mergeoptions that gives a single command line that
needs to be parsed was likely to be an ill-conceived idea to begin
with.  Sigh...

Helped-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-merge.c
t/t7600-merge.sh

index 3aaec7b..b0d3c09 100644 (file)
@@ -54,6 +54,7 @@ static size_t use_strategies_nr, use_strategies_alloc;
 static const char **xopts;
 static size_t xopts_nr, xopts_alloc;
 static const char *branch;
+static char *branch_mergeoptions;
 static int verbosity;
 static int allow_rerere_auto;
 
@@ -474,25 +475,33 @@ 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", branch);
+       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", branch);
-               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"))
@@ -918,6 +927,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
        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 (verbosity < 0)
index 57f6d2b..56c653d 100755 (executable)
@@ -372,6 +372,38 @@ test_expect_success 'merge c1 with c2 (no-commit in config)' '
 
 test_debug 'gitk --all'
 
+test_expect_success 'merge c1 with c2 (log in config)' '
+       git config branch.master.mergeoptions "" &&
+       git reset --hard c1 &&
+       git merge --log c2 &&
+       git show -s --pretty=tformat:%s%n%b >expect &&
+
+       git config branch.master.mergeoptions --log &&
+       git reset --hard c1 &&
+       git merge c2 &&
+       git show -s --pretty=tformat:%s%n%b >actual &&
+
+       test_cmp expect actual
+'
+
+test_expect_success 'merge c1 with c2 (log in config gets overridden)' '
+       (
+               git config --remove-section branch.master
+               git config --remove-section merge
+       )
+       git reset --hard c1 &&
+       git merge c2 &&
+       git show -s --pretty=tformat:%s%n%b >expect &&
+
+       git config branch.master.mergeoptions "--no-log" &&
+       git config merge.log true &&
+       git reset --hard c1 &&
+       git merge c2 &&
+       git show -s --pretty=tformat:%s%n%b >actual &&
+
+       test_cmp expect actual
+'
+
 test_expect_success 'merge c1 with c2 (squash in config)' '
        git reset --hard c1 &&
        git config branch.master.mergeoptions "--squash" &&