Re: [PATCH 3/3] builtin-merge: add support for default merge options

3 messages, 2 authors, 2016-06-15 · open the first message on its own page

Re: [PATCH 3/3] builtin-merge: add support for default merge options

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:46:20

Jay Soffian [off-list ref] writes:
quoted hunk
@@ -838,6 +847,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	if (is_null_sha1(head))
 		head_invalid = 1;
 
+	git_config(git_merge_config_default, NULL);
 	git_config(git_merge_config, NULL);

The placement of this comes before parse_options(), just like the part
that slurps "branch.*.mergeoptions", so it can be overridden by the
command line just like "branch.*.mergeoptions" can, which is good.

When you are on branch "frotz", your config have both merge.options and
branch.frotz.mergeoptions, and you give some other options from the
command line, how should they interact?  I'd expect the branch.*.options
to take effect, ignoring merge.options entirely.

I think the right way to structure this is to change the code in
git_merge_config() that accepts "branch.*.mergeoptions" to just store a
xstrdup() pointer away, add a similar thing in the same function for the
new "merge.options" variable.  Get rid of your git_merge_config_default
function that forces git_config() to iterate over the same config file one
more time.  And after the config parser returns, run the parse_options
only once.

In other words, the overall code structure would look like this:

static char *options_from_config;
static int options_from_config_taken_from_branch_config;

static int git_merge_config(...)
{
	if (branch && !prefixcmp(k, "branch.") ... ) {
		/*
                 * We may have found merge.options first;
		 * free it and override it with the value of
                 * branch.*.mergeoptions for the current branch
                 * we just found.
                 */
        	free(options_from_config);
               	options_from_config_taken_from_branch_config = 1;
               	options_from_config = xstrdup(value);
		return 0;
	}
        if (!strcmp(k, "merge.options")) {
		/*
                 * Do not override branch.*.mergeoptions for the
                 * current branch if we already found one.
                 */
               	if (!options_from_config_taken_from_branch_config)
                	options_from_config = xstrdup(value);
		return 0;
	}
        ...
}

int cmd_merge(...)
{
	...
        git_config(git_merge_config, NULL);
        if (options_from_config)
		/*
                 * There is a "prime" options given in
                 * the configuration file.  Parse it.
                 */
                git_config_option_string(builtin_merge_options, ...,
                			options_from_config);
	...
        argc = parse_options(argc, argv, builtin_merge_options,...);
	...
}

If for some reason you would want to have cumulative options across
branch.*.merge, merge.options and the command line, then you would instead
keep two separate strings, and call git_config_option_string() for both of
them, before processing the real command line options.

Hmm?

Re: [PATCH 3/3] builtin-merge: add support for default merge options

From: Jay Soffian <hidden>
Date: 2016-06-15 22:46:20

On Fri, Mar 6, 2009 at 5:46 PM, Junio C Hamano [off-list ref] wrote:
When you are on branch "frotz", your config have both merge.options and
branch.frotz.mergeoptions, and you give some other options from the
command line, how should they interact?  I'd expect the branch.*.options
to take effect, ignoring merge.options entirely.
Really? I didn't think that would be consistent with the fact that the
the command line options override branch.*.options, but don't replace
them. So I specifically coded it such that there are three separate
layers all merged together. (Which is also how I documented it in the
man page.)
If for some reason you would want to have cumulative options across
Which I do, or I wouldn't have coded it that way. :-)
branch.*.merge, merge.options and the command line, then you would instead
keep two separate strings, and call git_config_option_string() for both of
them, before processing the real command line options.
Ah, right that would be better.

j.

[PATCH v2 3/3] builtin-merge: add support for default merge options

From: Jay Soffian <hidden>
Date: 2016-06-15 22:46:20

This patch teaches merge a new setting, merge.options, which is
processed before any of the other merge configuration settings. It may
be used to establish a default which can then be overridden by more
specific branch.<name>.mergeoptions (or, obviously, command-line
switches).

Signed-off-by: Jay Soffian <redacted>
---
On Fri, Mar 6, 2009 at 5:46 PM, Junio C Hamano [off-list ref] wrote:
If for some reason you would want to have cumulative options across
branch.*.merge, merge.options and the command line, then you would instead
keep two separate strings, and call git_config_option_string() for both of
them, before processing the real command line options.
Which is what this version does. I also made the explanation of this behavior
in the man page more explicit.

 Documentation/git-merge.txt |   12 +++++--
 builtin-merge.c             |   22 +++++++++++--
 t/t7600-merge.sh            |   69 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 96 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index f7be584..5d80a78 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -47,10 +47,16 @@ CONFIGURATION
 -------------
 include::merge-config.txt[]
 
+merge.options::
+	Sets default options for merging. The syntax and supported options are
+	equal to that of 'git-merge'. Arguments are split by spaces, and may be
+	quoted in the same way as alias.* config options.
+
 branch.<name>.mergeoptions::
-	Sets default options for merging into branch <name>. The syntax and
-	supported options are equal to that of 'git-merge', but option values
-	containing whitespace characters are currently not supported.
+	Sets default options for merging into branch <name>. This setting is
+	handled after and is cumulative to `merge.options`. So it may override,
+	but does replace, any settings appearing there. The syntax is identical
+	to `merge.options`.
 
 HOW MERGE WORKS
 ---------------
diff --git a/builtin-merge.c b/builtin-merge.c
index 504f2be..d4dc4fe 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -50,6 +50,8 @@ static unsigned char head[20], stash[20];
 static struct strategy **use_strategies;
 static size_t use_strategies_nr, use_strategies_alloc;
 static const char *branch;
+static const char *branch_option_string = NULL;
+static const char *default_option_string = NULL;
 static int verbosity;
 
 static struct strategy all_strategy[] = {
@@ -451,10 +453,8 @@ 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")) {
-		if (git_config_option_string(builtin_merge_options, 0, k, v))
-			die("Bad branch.%s.mergeoptions string", branch);
-	}
+		!strcmp(k + 7 + strlen(branch), ".mergeoptions"))
+			return git_config_string(&branch_option_string, k, v);
 
 	if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat"))
 		show_diffstat = git_config_bool(k, v);
@@ -462,6 +462,8 @@ static int git_merge_config(const char *k, const char *v, void *cb)
 		return git_config_string(&pull_twohead, k, v);
 	else if (!strcmp(k, "pull.octopus"))
 		return git_config_string(&pull_octopus, k, v);
+	else if (!strcmp(k, "merge.options"))
+		return git_config_string(&default_option_string, k, v);
 	else if (!strcmp(k, "merge.log") || !strcmp(k, "merge.summary"))
 		option_log = git_config_bool(k, v);
 	return git_diff_ui_config(k, v, cb);
@@ -839,6 +841,18 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		head_invalid = 1;
 
 	git_config(git_merge_config, NULL);
+	if (default_option_string) {
+		if (git_config_option_string(builtin_merge_options, 0,
+		    "merge.options", default_option_string))
+			die("Bad merge.options string");
+	}
+	if (branch_option_string) {
+		strbuf_addf(&buf, "branch.%s.mergeoptions", branch);
+		if (git_config_option_string(builtin_merge_options, 0,
+		     buf.buf, branch_option_string))
+			die("Bad %s string", buf.buf);
+		strbuf_reset(&buf);
+	}
 
 	/* for color.ui */
 	if (diff_use_color_default == -1)
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 9db8bb4..aaecdab 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -367,6 +367,16 @@ test_expect_success 'merge c1 with c2 (no-commit in config)' '
 
 test_debug 'gitk --all'
 
+test_expect_success 'merge c1 with c2 (no-commit in merge.options)' '
+	git reset --hard c1 &&
+	with_config merge.options --no-commit -- merge c2 &&
+	verify_merge file result.1-5 &&
+	verify_head $c1 &&
+	verify_mergeheads $c2
+'
+
+test_debug 'gitk --all'
+
 test_expect_success 'merge c1 with c2 (squash in config)' '
 	git reset --hard c1 &&
 	with_config branch.master.mergeoptions --squash -- \
@@ -379,6 +389,17 @@ test_expect_success 'merge c1 with c2 (squash in config)' '
 
 test_debug 'gitk --all'
 
+test_expect_success 'merge c1 with c2 (squash in merge.options)' '
+	git reset --hard c1 &&
+	with_config merge.options --squash -- merge c2 &&
+	verify_merge file result.1-5 &&
+	verify_head $c1 &&
+	verify_no_mergehead &&
+	verify_diff squash.1-5 .git/SQUASH_MSG "[OOPS] bad squash message"
+'
+
+test_debug 'gitk --all'
+
 test_expect_success 'override config option -n with --summary' '
 	git reset --hard c1 &&
 	test_tick &&
@@ -425,6 +446,54 @@ test_expect_success 'override config option --stat' '
 
 test_debug 'gitk --all'
 
+test_expect_success 'override merge.options -n with branch mergeoptions --summary' '
+	git reset --hard c1 &&
+	test_tick &&
+	with_config merge.options -n branch.master.mergeoptions --summary -- \
+		merge c2 >diffstat.txt &&
+	verify_merge file result.1-5 msg.1-5 &&
+	verify_parents $c1 $c2 &&
+	if ! grep "^ file |  *2 +-$" diffstat.txt
+	then
+		echo "[OOPS] diffstat was not generated with --summary"
+		false
+	fi
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'override merge.options -n with branch mergeoptions --stat' '
+	git reset --hard c1 &&
+	test_tick &&
+	with_config merge.options -n branch.master.mergeoptions --stat -- \
+		merge c2 >diffstat.txt &&
+	verify_merge file result.1-5 msg.1-5 &&
+	verify_parents $c1 $c2 &&
+	if ! grep "^ file |  *2 +-$" diffstat.txt
+	then
+		echo "[OOPS] diffstat was not generated with --stat"
+		false
+	fi
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'override merge.options --stat' '
+	git reset --hard c1 &&
+	test_tick &&
+	with_config merge.options --stat branch.master.mergeoptions -n -- \
+		merge c2 >diffstat.txt &&
+	verify_merge file result.1-5 msg.1-5 &&
+	verify_parents $c1 $c2 &&
+	if grep "^ file |  *2 +-$" diffstat.txt
+	then
+		echo "[OOPS] diffstat was generated"
+		false
+	fi
+'
+
+test_debug 'gitk --all'
+
 test_expect_success 'merge c1 with c2 (override --no-commit)' '
 	git reset --hard c1 &&
 	test_tick &&
-- 
1.6.2.rc2.332.g5d21b
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help