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
This commit is contained in:
commit
2bb76e139e
@ -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
|
|||||||
>>>>>>> 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
|
|||||||
|
|
||||||
--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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
55
ll-merge.c
55
ll-merge.c
@ -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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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)' '
|
|||||||
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" {
|
|||||||
#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,
|
|||||||
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 {
|
|||||||
* 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,
|
|||||||
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,
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
} 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);
|
||||||
|
Loading…
Reference in New Issue
Block a user