提交 2bb76e13 编写于 作者: J Junio C Hamano

Merge branch 'bw/union-merge-refactor'

* bw/union-merge-refactor:
  merge-file: add option to select union merge favor
  merge-file: add option to specify the marker size
  refactor merge flags into xmparam_t
  make union merge an xdl merge favor
...@@ -10,7 +10,7 @@ SYNOPSIS ...@@ -10,7 +10,7 @@ SYNOPSIS
-------- --------
[verse] [verse]
'git merge-file' [-L <current-name> [-L <base-name> [-L <other-name>]]] 'git merge-file' [-L <current-name> [-L <base-name> [-L <other-name>]]]
[--ours|--theirs] [-p|--stdout] [-q|--quiet] [--ours|--theirs|--union] [-p|--stdout] [-q|--quiet] [--marker-size=<n>]
<current-file> <base-file> <other-file> <current-file> <base-file> <other-file>
...@@ -35,9 +35,10 @@ normally outputs a warning and brackets the conflict with lines containing ...@@ -35,9 +35,10 @@ normally outputs a warning and brackets the conflict with lines containing
>>>>>>> B >>>>>>> B
If there are conflicts, the user should edit the result and delete one of 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, the alternatives. When `--ours`, `--theirs`, or `--union` option is in effect,
these conflicts are resolved favouring lines from `<current-file>` or however, these conflicts are resolved favouring lines from `<current-file>`,
lines from `<other-file>` respectively. 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 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. conflicts otherwise. If the merge was clean, the exit value is 0.
...@@ -67,8 +68,9 @@ OPTIONS ...@@ -67,8 +68,9 @@ OPTIONS
--ours:: --ours::
--theirs:: --theirs::
--union::
Instead of leaving conflicts in the file, resolve conflicts 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 EXAMPLES
......
...@@ -27,30 +27,35 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix) ...@@ -27,30 +27,35 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
mmbuffer_t result = {NULL, 0}; mmbuffer_t result = {NULL, 0};
xmparam_t xmp = {{XDF_NEED_MINIMAL}}; xmparam_t xmp = {{XDF_NEED_MINIMAL}};
int ret = 0, i = 0, to_stdout = 0; int ret = 0, i = 0, to_stdout = 0;
int level = XDL_MERGE_ZEALOUS_ALNUM; int quiet = 0;
int style = 0, quiet = 0;
int favor = 0;
int nongit; int nongit;
struct option options[] = { struct option options[] = {
OPT_BOOLEAN('p', "stdout", &to_stdout, "send results to standard output"), 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, "diff3", &xmp.style, "use a diff3 based merge", XDL_MERGE_DIFF3),
OPT_SET_INT(0, "ours", &favor, "for conflicts, use our version", OPT_SET_INT(0, "ours", &xmp.favor, "for conflicts, use our version",
XDL_MERGE_FAVOR_OURS), 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), 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), OPT__QUIET(&quiet),
OPT_CALLBACK('L', NULL, names, "name", OPT_CALLBACK('L', NULL, names, "name",
"set labels for file1/orig_file/file2", &label_cb), "set labels for file1/orig_file/file2", &label_cb),
OPT_END(), OPT_END(),
}; };
xmp.level = XDL_MERGE_ZEALOUS_ALNUM;
xmp.style = 0;
xmp.favor = 0;
prefix = setup_git_directory_gently(&nongit); prefix = setup_git_directory_gently(&nongit);
if (!nongit) { if (!nongit) {
/* Read the configuration file */ /* Read the configuration file */
git_config(git_xmerge_config, NULL); git_config(git_xmerge_config, NULL);
if (0 <= git_xmerge_style) 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); argc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);
...@@ -73,7 +78,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix) ...@@ -73,7 +78,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], 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++) for (i = 0; i < 3; i++)
free(mmfs[i].ptr); free(mmfs[i].ptr);
......
...@@ -63,8 +63,6 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, ...@@ -63,8 +63,6 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
int flag, int marker_size) int flag, int marker_size)
{ {
xmparam_t xmp; xmparam_t xmp;
int style = 0;
int favor = (flag >> 1) & 03;
if (buffer_is_binary(orig->ptr, orig->size) || if (buffer_is_binary(orig->ptr, orig->size) ||
buffer_is_binary(src1->ptr, src1->size) || buffer_is_binary(src1->ptr, src1->size) ||
...@@ -79,15 +77,13 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, ...@@ -79,15 +77,13 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
} }
memset(&xmp, 0, sizeof(xmp)); memset(&xmp, 0, sizeof(xmp));
xmp.level = XDL_MERGE_ZEALOUS;
xmp.favor= (flag >> 1) & 03;
if (git_xmerge_style >= 0) if (git_xmerge_style >= 0)
style = git_xmerge_style; xmp.style = git_xmerge_style;
if (marker_size > 0) if (marker_size > 0)
xmp.marker_size = marker_size; xmp.marker_size = marker_size;
return xdl_merge(orig, return xdl_merge(orig, src1, name1, src2, name2, &xmp, result);
src1, name1,
src2, name2,
&xmp, XDL_MERGE_FLAGS(XDL_MERGE_ZEALOUS, style, favor),
result);
} }
static int ll_union_merge(const struct ll_merge_driver *drv_unused, static int ll_union_merge(const struct ll_merge_driver *drv_unused,
...@@ -98,44 +94,11 @@ static int ll_union_merge(const struct ll_merge_driver *drv_unused, ...@@ -98,44 +94,11 @@ static int ll_union_merge(const struct ll_merge_driver *drv_unused,
mmfile_t *src2, const char *name2, mmfile_t *src2, const char *name2,
int flag, int marker_size) int flag, int marker_size)
{ {
char *src, *dst; /* Use union favor */
long size; flag = (flag & 1) | (XDL_MERGE_FAVOR_UNION << 1);
int status, saved_style; return ll_xdl_merge(drv_unused, result, path_unused,
orig, src1, NULL, src2, NULL,
/* We have to force the RCS "merge" style */ flag, marker_size);
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;
return 0; return 0;
} }
......
...@@ -215,4 +215,41 @@ test_expect_success '"diff3 -m" style output (2)' ' ...@@ -215,4 +215,41 @@ test_expect_success '"diff3 -m" style output (2)' '
test_cmp expect actual 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 test_done
...@@ -56,17 +56,14 @@ extern "C" { ...@@ -56,17 +56,14 @@ extern "C" {
#define XDL_MERGE_EAGER 1 #define XDL_MERGE_EAGER 1
#define XDL_MERGE_ZEALOUS 2 #define XDL_MERGE_ZEALOUS 2
#define XDL_MERGE_ZEALOUS_ALNUM 3 #define XDL_MERGE_ZEALOUS_ALNUM 3
#define XDL_MERGE_LEVEL_MASK 0x0f
/* merge favor modes */ /* merge favor modes */
#define XDL_MERGE_FAVOR_OURS 1 #define XDL_MERGE_FAVOR_OURS 1
#define XDL_MERGE_FAVOR_THEIRS 2 #define XDL_MERGE_FAVOR_THEIRS 2
#define XDL_MERGE_FAVOR(flags) (((flags)>>4) & 3) #define XDL_MERGE_FAVOR_UNION 3
#define XDL_MERGE_FLAGS(level, style, favor) ((level)|(style)|((favor)<<4))
/* merge output styles */ /* merge output styles */
#define XDL_MERGE_DIFF3 0x8000 #define XDL_MERGE_DIFF3 1
#define XDL_MERGE_STYLE_MASK 0x8000
typedef struct s_mmfile { typedef struct s_mmfile {
char *ptr; char *ptr;
...@@ -117,13 +114,16 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, ...@@ -117,13 +114,16 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
typedef struct s_xmparam { typedef struct s_xmparam {
xpparam_t xpp; xpparam_t xpp;
int marker_size; int marker_size;
int level;
int favor;
int style;
} xmparam_t; } xmparam_t;
#define DEFAULT_CONFLICT_MARKER_SIZE 7 #define DEFAULT_CONFLICT_MARKER_SIZE 7
int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1, int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
mmfile_t *mf2, const char *name2, mmfile_t *mf2, const char *name2,
xmparam_t const *xmp, int flags, mmbuffer_t *result); xmparam_t const *xmp, mmbuffer_t *result);
#ifdef __cplusplus #ifdef __cplusplus
} }
......
...@@ -28,6 +28,7 @@ typedef struct s_xdmerge { ...@@ -28,6 +28,7 @@ typedef struct s_xdmerge {
* 0 = conflict, * 0 = conflict,
* 1 = no conflict, take first, * 1 = no conflict, take first,
* 2 = no conflict, take second. * 2 = no conflict, take second.
* 3 = no conflict, take both.
*/ */
int mode; int mode;
/* /*
...@@ -230,14 +231,19 @@ static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1, ...@@ -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 = fill_conflict_hunk(xe1, name1, xe2, name2,
size, i, style, m, dest, size, i, style, m, dest,
marker_size); marker_size);
else if (m->mode == 1) else if (m->mode & 3) {
size += xdl_recs_copy(xe1, i, m->i1 + m->chg1 - i, 0, /* Before conflicting part */
size += xdl_recs_copy(xe1, i, m->i1 - i, 0,
dest ? dest + size : NULL); dest ? dest + size : NULL);
else if (m->mode == 2) /* Postimage from side #1 */
size += xdl_recs_copy(xe2, m->i2 - m->i1 + i, if (m->mode & 1)
m->i1 + m->chg2 - i, 0, size += xdl_recs_copy(xe1, m->i1, m->chg1, 1,
dest ? dest + size : NULL); dest ? dest + size : NULL);
else /* Postimage from side #2 */
if (m->mode & 2)
size += xdl_recs_copy(xe2, m->i2, m->chg2, 1,
dest ? dest + size : NULL);
} else
continue; continue;
i = m->i1 + m->chg1; i = m->i1 + m->chg1;
} }
...@@ -394,13 +400,13 @@ static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m, ...@@ -394,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, static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
xdfenv_t *xe2, xdchange_t *xscr2, const char *name2, 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; xdmerge_t *changes, *c;
xpparam_t const *xpp = &xmp->xpp; xpparam_t const *xpp = &xmp->xpp;
int i0, i1, i2, chg0, chg1, chg2; int i0, i1, i2, chg0, chg1, chg2;
int level = flags & XDL_MERGE_LEVEL_MASK; int level = xmp->level;
int style = flags & XDL_MERGE_STYLE_MASK; int style = xmp->style;
int favor = XDL_MERGE_FAVOR(flags); int favor = xmp->favor;
if (style == XDL_MERGE_DIFF3) { if (style == XDL_MERGE_DIFF3) {
/* /*
...@@ -550,7 +556,7 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1, ...@@ -550,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, int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
mmfile_t *mf2, const char *name2, 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; xdchange_t *xscr1, *xscr2;
xdfenv_t xe1, xe2; xdfenv_t xe1, xe2;
int status; int status;
...@@ -587,7 +593,7 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1, ...@@ -587,7 +593,7 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
} else { } else {
status = xdl_do_merge(&xe1, xscr1, name1, status = xdl_do_merge(&xe1, xscr1, name1,
&xe2, xscr2, name2, &xe2, xscr2, name2,
flags, xmp, result); xmp, result);
} }
xdl_free_script(xscr1); xdl_free_script(xscr1);
xdl_free_script(xscr2); xdl_free_script(xscr2);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册