[PATCH 1/4] make union merge an xdl merge favor

Subsystems: the rest

DORMANTno replies

4 messages, 1 author, 2016-06-15 · open the first message on its own page

[PATCH 1/4] make union merge an xdl merge favor

From: Bert Wesarg <hidden>
Date: 2016-06-15 22:48:22

The current union merge driver is implemented as an post process.  But the
xdl_merge code is quite capable to produce the result by itself.  Therefore
move it there.

Signed-off-by: Bert Wesarg <redacted>
---
 ll-merge.c     |   43 +++++--------------------------------------
 xdiff/xdiff.h  |    1 +
 xdiff/xmerge.c |   20 +++++++++++++-------
 3 files changed, 19 insertions(+), 45 deletions(-)
diff --git a/ll-merge.c b/ll-merge.c
index 4c7f11b..a4b2f4c 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -98,44 +98,11 @@ static int ll_union_merge(const struct ll_merge_driver *drv_unused,
 			  mmfile_t *src2, const char *name2,
 			  int flag, int marker_size)
 {
-	char *src, *dst;
-	long size;
-	int status, saved_style;
-
-	/* We have to force the RCS "merge" style */
-	saved_style = git_xmerge_style;
-	git_xmerge_style = 0;
-	status = ll_xdl_merge(drv_unused, result, path_unused,
-			      orig, src1, NULL, src2, NULL,
-			      flag, marker_size);
-	git_xmerge_style = saved_style;
-	if (status <= 0)
-		return status;
-	size = result->size;
-	src = dst = result->ptr;
-	while (size) {
-		char ch;
-		if ((marker_size < size) &&
-		    (*src == '<' || *src == '=' || *src == '>')) {
-			int i;
-			ch = *src;
-			for (i = 0; i < marker_size; i++)
-				if (src[i] != ch)
-					goto not_a_marker;
-			if (src[marker_size] != '\n')
-				goto not_a_marker;
-			src += marker_size + 1;
-			size -= marker_size + 1;
-			continue;
-		}
-	not_a_marker:
-		do {
-			ch = *src++;
-			*dst++ = ch;
-			size--;
-		} while (ch != '\n' && size);
-	}
-	result->size = dst - result->ptr;
+	/* Use union favor */
+	flag = (flag & 1) | (XDL_MERGE_FAVOR_UNION << 1);
+	return ll_xdl_merge(drv_unused, result, path_unused,
+			    orig, src1, NULL, src2, NULL,
+			    flag, marker_size);
 	return 0;
 }
 
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index 3f6229e..22614d5 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -61,6 +61,7 @@ extern "C" {
 /* merge favor modes */
 #define XDL_MERGE_FAVOR_OURS 1
 #define XDL_MERGE_FAVOR_THEIRS 2
+#define XDL_MERGE_FAVOR_UNION 3
 #define XDL_MERGE_FAVOR(flags) (((flags)>>4) & 3)
 #define XDL_MERGE_FLAGS(level, style, favor) ((level)|(style)|((favor)<<4))
 
diff --git a/xdiff/xmerge.c b/xdiff/xmerge.c
index 8cbe45e..c901ecb 100644
--- a/xdiff/xmerge.c
+++ b/xdiff/xmerge.c
@@ -28,6 +28,7 @@ typedef struct s_xdmerge {
 	 * 0 = conflict,
 	 * 1 = no conflict, take first,
 	 * 2 = no conflict, take second.
+	 * 3 = no conflict, take both.
 	 */
 	int mode;
 	/*
@@ -230,14 +231,19 @@ static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
 			size = fill_conflict_hunk(xe1, name1, xe2, name2,
 						  size, i, style, m, dest,
 						  marker_size);
-		else if (m->mode == 1)
-			size += xdl_recs_copy(xe1, i, m->i1 + m->chg1 - i, 0,
+		else if (m->mode & 3) {
+			/* Before conflicting part */
+			size += xdl_recs_copy(xe1, i, m->i1 - i, 0,
 					      dest ? dest + size : NULL);
-		else if (m->mode == 2)
-			size += xdl_recs_copy(xe2, m->i2 - m->i1 + i,
-					      m->i1 + m->chg2 - i, 0,
-					      dest ? dest + size : NULL);
-		else
+			/* Postimage from side #1 */
+			if (m->mode & 1)
+				size += xdl_recs_copy(xe1, m->i1, m->chg1, 1,
+						      dest ? dest + size : NULL);
+			/* Postimage from side #2 */
+			if (m->mode & 2)
+				size += xdl_recs_copy(xe2, m->i2, m->chg2, 1,
+						      dest ? dest + size : NULL);
+		} else
 			continue;
 		i = m->i1 + m->chg1;
 	}
-- 
1.7.0.584.g2da2b

[RFC/PATCH 3/4] merge-file: add option to specify the marker size

From: Bert Wesarg <hidden>
Date: 2016-06-15 22:48:22

This adds the abbility to specify the conflict marker size for merges outside
a git repository.

Signed-off-by: Bert Wesarg <redacted>
---

For merges inside a git repository, there is a proposed idea to use a --path
argument like git hash-object to get the marker size from git attributes.
Which I'm all for it. A second proposal is to give attributes as arguments to
git merge-file, which I suspect involves very intrusive changes.

There where also a suggestion that merge-file should support file arguments
that points to blob objects (ie. master:Makefile). I think the --path argument
would fit this usecase too.

There is also currently no sane upper bound for marker sizes. Neither in
the git attribute case nor in this patch.

 Documentation/git-merge-file.txt |    5 +++--
 builtin-merge-file.c             |    2 ++
 t/t6023-merge-file.sh            |   37 +++++++++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-merge-file.txt b/Documentation/git-merge-file.txt
index 234269a..a5b9c1f 100644
--- a/Documentation/git-merge-file.txt
+++ b/Documentation/git-merge-file.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git merge-file' [-L <current-name> [-L <base-name> [-L <other-name>]]]
-	[--ours|--theirs] [-p|--stdout] [-q|--quiet]
+	[--ours|--theirs] [-p|--stdout] [-q|--quiet] [--marker-size=<n>]
 	<current-file> <base-file> <other-file>
 
 
@@ -37,7 +37,8 @@ normally outputs a warning and brackets the conflict with lines containing
 If there are conflicts, the user should edit the result and delete one of
 the alternatives.  When `--ours` or `--theirs` option is in effect, however,
 these conflicts are resolved favouring lines from `<current-file>` or
-lines from `<other-file>` respectively.
+lines from `<other-file>` respectively.  The length of the conflict markers
+can be given with the `--marker-size` option.
 
 The exit value of this program is negative on error, and the number of
 conflicts otherwise. If the merge was clean, the exit value is 0.
diff --git a/builtin-merge-file.c b/builtin-merge-file.c
index 3389dd0..c1a35b9 100644
--- a/builtin-merge-file.c
+++ b/builtin-merge-file.c
@@ -41,6 +41,8 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 			    XDL_MERGE_FAVOR_OURS),
 		OPT_SET_INT(0, "theirs", &xmp.favor, "for conflicts, use their version",
 			    XDL_MERGE_FAVOR_THEIRS),
+		OPT_INTEGER(0, "marker-size", &xmp.marker_size,
+			    "for conflicts, use this marker size"),
 		OPT__QUIET(&quiet),
 		OPT_CALLBACK('L', NULL, names, "name",
 			     "set labels for file1/orig_file/file2", &label_cb),
diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh
index d605024..5034dd1 100755
--- a/t/t6023-merge-file.sh
+++ b/t/t6023-merge-file.sh
@@ -215,4 +215,41 @@ test_expect_success '"diff3 -m" style output (2)' '
 	test_cmp expect actual
 '
 
+cat >expect <<\EOF
+Dominus regit me,
+<<<<<<<<<< new8.txt
+et nihil mihi deerit;
+
+
+
+
+In loco pascuae ibi me collocavit;
+super aquam refectionis educavit me.
+||||||||||
+et nihil mihi deerit.
+In loco pascuae ibi me collocavit,
+super aquam refectionis educavit me;
+==========
+et nihil mihi deerit,
+
+
+
+
+In loco pascuae ibi me collocavit --
+super aquam refectionis educavit me,
+>>>>>>>>>> new9.txt
+animam meam convertit,
+deduxit me super semitas jusitiae,
+propter nomen suum.
+Nam et si ambulavero in medio umbrae mortis,
+non timebo mala, quoniam TU mecum es:
+virga tua et baculus tuus ipsa me consolata sunt.
+EOF
+
+test_expect_success 'marker size' '
+	test_must_fail git merge-file -p --marker-size=10 \
+		new8.txt new5.txt new9.txt >actual &&
+	test_cmp expect actual
+'
+
 test_done
-- 
1.7.0.584.g2da2b

[PATCH 2/4] refactor merge flags into xmparam_t

From: Bert Wesarg <hidden>
Date: 2016-06-15 22:48:22

Include the merge level, favor, and style flags into the xmparam_t struct.
This removes the bit twiddling with these three values into the one flags
parameter.

Signed-off-by: Bert Wesarg <redacted>
---
 builtin-merge-file.c |   18 ++++++++++--------
 ll-merge.c           |   12 ++++--------
 xdiff/xdiff.h        |   11 +++++------
 xdiff/xmerge.c       |   12 ++++++------
 4 files changed, 25 insertions(+), 28 deletions(-)
diff --git a/builtin-merge-file.c b/builtin-merge-file.c
index 1e70073..3389dd0 100644
--- a/builtin-merge-file.c
+++ b/builtin-merge-file.c
@@ -27,17 +27,19 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 	mmbuffer_t result = {NULL, 0};
 	xmparam_t xmp = {{XDF_NEED_MINIMAL}};
 	int ret = 0, i = 0, to_stdout = 0;
-	int level = XDL_MERGE_ZEALOUS_ALNUM;
-	int style = 0, quiet = 0;
-	int favor = 0;
+	int quiet = 0;
 	int nongit;
 
+	xmp.level = XDL_MERGE_ZEALOUS_ALNUM;
+	xmp.style = 0;
+	xmp.favor = 0;
+
 	struct option options[] = {
 		OPT_BOOLEAN('p', "stdout", &to_stdout, "send results to standard output"),
-		OPT_SET_INT(0, "diff3", &style, "use a diff3 based merge", XDL_MERGE_DIFF3),
-		OPT_SET_INT(0, "ours", &favor, "for conflicts, use our version",
+		OPT_SET_INT(0, "diff3", &xmp.style, "use a diff3 based merge", XDL_MERGE_DIFF3),
+		OPT_SET_INT(0, "ours", &xmp.favor, "for conflicts, use our version",
 			    XDL_MERGE_FAVOR_OURS),
-		OPT_SET_INT(0, "theirs", &favor, "for conflicts, use their version",
+		OPT_SET_INT(0, "theirs", &xmp.favor, "for conflicts, use their version",
 			    XDL_MERGE_FAVOR_THEIRS),
 		OPT__QUIET(&quiet),
 		OPT_CALLBACK('L', NULL, names, "name",
@@ -50,7 +52,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 		/* Read the configuration file */
 		git_config(git_xmerge_config, NULL);
 		if (0 <= git_xmerge_style)
-			style = git_xmerge_style;
+			xmp.style = git_xmerge_style;
 	}
 
 	argc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);
@@ -73,7 +75,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 	}
 
 	ret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2],
-			&xmp, XDL_MERGE_FLAGS(level, style, favor), &result);
+			&xmp, &result);
 
 	for (i = 0; i < 3; i++)
 		free(mmfs[i].ptr);
diff --git a/ll-merge.c b/ll-merge.c
index a4b2f4c..82c7742 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -63,8 +63,6 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
 			int flag, int marker_size)
 {
 	xmparam_t xmp;
-	int style = 0;
-	int favor = (flag >> 1) & 03;
 
 	if (buffer_is_binary(orig->ptr, orig->size) ||
 	    buffer_is_binary(src1->ptr, src1->size) ||
@@ -79,15 +77,13 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
 	}
 
 	memset(&xmp, 0, sizeof(xmp));
+	xmp.level = XDL_MERGE_ZEALOUS;
+	xmp.favor= (flag >> 1) & 03;
 	if (git_xmerge_style >= 0)
-		style = git_xmerge_style;
+		xmp.style = git_xmerge_style;
 	if (marker_size > 0)
 		xmp.marker_size = marker_size;
-	return xdl_merge(orig,
-			 src1, name1,
-			 src2, name2,
-			 &xmp, XDL_MERGE_FLAGS(XDL_MERGE_ZEALOUS, style, favor),
-			 result);
+	return xdl_merge(orig, src1, name1, src2, name2, &xmp, result);
 }
 
 static int ll_union_merge(const struct ll_merge_driver *drv_unused,
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index 22614d5..a71763a 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -56,18 +56,14 @@ extern "C" {
 #define XDL_MERGE_EAGER 1
 #define XDL_MERGE_ZEALOUS 2
 #define XDL_MERGE_ZEALOUS_ALNUM 3
-#define XDL_MERGE_LEVEL_MASK 0x0f
 
 /* merge favor modes */
 #define XDL_MERGE_FAVOR_OURS 1
 #define XDL_MERGE_FAVOR_THEIRS 2
 #define XDL_MERGE_FAVOR_UNION 3
-#define XDL_MERGE_FAVOR(flags) (((flags)>>4) & 3)
-#define XDL_MERGE_FLAGS(level, style, favor) ((level)|(style)|((favor)<<4))
 
 /* merge output styles */
-#define XDL_MERGE_DIFF3 0x8000
-#define XDL_MERGE_STYLE_MASK 0x8000
+#define XDL_MERGE_DIFF3 1
 
 typedef struct s_mmfile {
 	char *ptr;
@@ -118,13 +114,16 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 typedef struct s_xmparam {
 	xpparam_t xpp;
 	int marker_size;
+	int level;
+	int favor;
+	int style;
 } xmparam_t;
 
 #define DEFAULT_CONFLICT_MARKER_SIZE 7
 
 int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
 		mmfile_t *mf2, const char *name2,
-		xmparam_t const *xmp, int flags, mmbuffer_t *result);
+		xmparam_t const *xmp, mmbuffer_t *result);
 
 #ifdef __cplusplus
 }
diff --git a/xdiff/xmerge.c b/xdiff/xmerge.c
index c901ecb..87cafa7 100644
--- a/xdiff/xmerge.c
+++ b/xdiff/xmerge.c
@@ -400,13 +400,13 @@ static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m,
  */
 static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
 		xdfenv_t *xe2, xdchange_t *xscr2, const char *name2,
-		int flags, xmparam_t const *xmp, mmbuffer_t *result) {
+		xmparam_t const *xmp, mmbuffer_t *result) {
 	xdmerge_t *changes, *c;
 	xpparam_t const *xpp = &xmp->xpp;
 	int i0, i1, i2, chg0, chg1, chg2;
-	int level = flags & XDL_MERGE_LEVEL_MASK;
-	int style = flags & XDL_MERGE_STYLE_MASK;
-	int favor = XDL_MERGE_FAVOR(flags);
+	int level = xmp->level;
+	int style = xmp->style;
+	int favor = xmp->favor;
 
 	if (style == XDL_MERGE_DIFF3) {
 		/*
@@ -556,7 +556,7 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
 
 int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
 		mmfile_t *mf2, const char *name2,
-		xmparam_t const *xmp, int flags, mmbuffer_t *result) {
+		xmparam_t const *xmp, mmbuffer_t *result) {
 	xdchange_t *xscr1, *xscr2;
 	xdfenv_t xe1, xe2;
 	int status;
@@ -593,7 +593,7 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
 	} else {
 		status = xdl_do_merge(&xe1, xscr1, name1,
 				      &xe2, xscr2, name2,
-				      flags, xmp, result);
+				      xmp, result);
 	}
 	xdl_free_script(xscr1);
 	xdl_free_script(xscr2);
-- 
1.7.0.584.g2da2b

[RFC/PATCH 4/4] merge-file: add option to select union merge favor

From: Bert Wesarg <hidden>
Date: 2016-06-15 22:48:22

Signed-off-by: Bert Wesarg <redacted>
---

The same argument as for the --marker-size apply here. For merges outside a
git repository, its the only way to get access to the union merge driver.

 Documentation/git-merge-file.txt |   13 +++++++------
 builtin-merge-file.c             |    2 ++
 2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/Documentation/git-merge-file.txt b/Documentation/git-merge-file.txt
index a5b9c1f..f334d69 100644
--- a/Documentation/git-merge-file.txt
+++ b/Documentation/git-merge-file.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git merge-file' [-L <current-name> [-L <base-name> [-L <other-name>]]]
-	[--ours|--theirs] [-p|--stdout] [-q|--quiet] [--marker-size=<n>]
+	[--ours|--theirs|--union] [-p|--stdout] [-q|--quiet] [--marker-size=<n>]
 	<current-file> <base-file> <other-file>
 
 
@@ -35,10 +35,10 @@ normally outputs a warning and brackets the conflict with lines containing
 	>>>>>>> B
 
 If there are conflicts, the user should edit the result and delete one of
-the alternatives.  When `--ours` or `--theirs` option is in effect, however,
-these conflicts are resolved favouring lines from `<current-file>` or
-lines from `<other-file>` respectively.  The length of the conflict markers
-can be given with the `--marker-size` option.
+the alternatives.  When `--ours`, `--theirs`, or `--union` option is in effect,
+however, these conflicts are resolved favouring lines from `<current-file>`,
+lines from `<other-file>`, or lines from both respectively.  The length of the
+conflict markers can be given with the `--marker-size` option.
 
 The exit value of this program is negative on error, and the number of
 conflicts otherwise. If the merge was clean, the exit value is 0.
@@ -68,8 +68,9 @@ OPTIONS
 
 --ours::
 --theirs::
+--union::
 	Instead of leaving conflicts in the file, resolve conflicts
-	favouring our (or their) side of the lines.
+	favouring our (or their or both) side of the lines.
 
 
 EXAMPLES
diff --git a/builtin-merge-file.c b/builtin-merge-file.c
index c1a35b9..eaa4917 100644
--- a/builtin-merge-file.c
+++ b/builtin-merge-file.c
@@ -41,6 +41,8 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
 			    XDL_MERGE_FAVOR_OURS),
 		OPT_SET_INT(0, "theirs", &xmp.favor, "for conflicts, use their version",
 			    XDL_MERGE_FAVOR_THEIRS),
+		OPT_SET_INT(0, "union", &xmp.favor, "for conflicts, use a union version",
+			    XDL_MERGE_FAVOR_UNION),
 		OPT_INTEGER(0, "marker-size", &xmp.marker_size,
 			    "for conflicts, use this marker size"),
 		OPT__QUIET(&quiet),
-- 
1.7.0.584.g2da2b
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help