Skip to content

Commit

Permalink
Merge branch 'bw/union-merge-refactor'
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Junio C Hamano committed Mar 20, 2010
2 parents 96203bb + 3a15048 commit 2bb76e1
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 79 deletions.
12 changes: 7 additions & 5 deletions Documentation/git-merge-file.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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|--union] [-p|--stdout] [-q|--quiet] [--marker-size=<n>]
<current-file> <base-file> <other-file>


Expand All @@ -35,9 +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 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.
Expand Down Expand Up @@ -67,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
Expand Down
23 changes: 14 additions & 9 deletions builtin/merge-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,30 +27,35 @@ 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;

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_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_CALLBACK('L', NULL, names, "name",
"set labels for file1/orig_file/file2", &label_cb),
OPT_END(),
};

xmp.level = XDL_MERGE_ZEALOUS_ALNUM;
xmp.style = 0;
xmp.favor = 0;

prefix = setup_git_directory_gently(&nongit);
if (!nongit) {
/* 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);
Expand All @@ -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],
&xmp, XDL_MERGE_FLAGS(level, style, favor), &result);
&xmp, &result);

for (i = 0; i < 3; i++)
free(mmfs[i].ptr);
Expand Down
55 changes: 9 additions & 46 deletions ll-merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) ||
Expand All @@ -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,
Expand All @@ -98,44 +94,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;
}

Expand Down
37 changes: 37 additions & 0 deletions t/t6023-merge-file.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 6 additions & 6 deletions xdiff/xdiff.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +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(flags) (((flags)>>4) & 3)
#define XDL_MERGE_FLAGS(level, style, favor) ((level)|(style)|((favor)<<4))
#define XDL_MERGE_FAVOR_UNION 3

/* 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;
Expand Down Expand Up @@ -117,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
}
Expand Down
32 changes: 19 additions & 13 deletions xdiff/xmerge.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
/*
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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,
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) {
/*
Expand Down Expand Up @@ -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,
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;
Expand Down Expand Up @@ -587,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);
Expand Down

0 comments on commit 2bb76e1

Please sign in to comment.