Skip to content

Commit 18a477e

Browse files
authored
Merge pull request libgit2#6195 from libgit2/ethomson/zdiff3
merge: support zdiff3 conflict styles
2 parents 50fada7 + c629d2a commit 18a477e

File tree

22 files changed

+635
-403
lines changed

22 files changed

+635
-403
lines changed

include/git2/checkout.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,10 @@ typedef enum {
182182
* notifications; don't update the working directory or index.
183183
*/
184184
GIT_CHECKOUT_DRY_RUN = (1u << 24),
185-
185+
186+
/** Include common ancestor data in zdiff3 format for conflicts */
187+
GIT_CHECKOUT_CONFLICT_STYLE_ZDIFF3 = (1u << 25),
188+
186189
/**
187190
* THE FOLLOWING OPTIONS ARE NOT YET IMPLEMENTED
188191
*/

include/git2/merge.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,10 @@ typedef enum {
159159
GIT_MERGE_FILE_DIFF_PATIENCE = (1 << 6),
160160

161161
/** Take extra time to find minimal diff */
162-
GIT_MERGE_FILE_DIFF_MINIMAL = (1 << 7)
162+
GIT_MERGE_FILE_DIFF_MINIMAL = (1 << 7),
163+
164+
/** Create zdiff3 ("zealous diff3")-style files */
165+
GIT_MERGE_FILE_STYLE_ZDIFF3 = (1 << 8)
163166
} git_merge_file_flag_t;
164167

165168
#define GIT_MERGE_CONFLICT_MARKER_SIZE 7

src/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,17 @@ endif()
207207
# errors for the xdiff sources until we've sorted them out
208208
if(MSVC)
209209
set_source_files_properties(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS -WX-)
210+
set_source_files_properties(xdiff/xemit.c PROPERTIES COMPILE_FLAGS -WX-)
211+
set_source_files_properties(xdiff/xhistogram.c PROPERTIES COMPILE_FLAGS -WX-)
212+
set_source_files_properties(xdiff/xmerge.c PROPERTIES COMPILE_FLAGS -WX-)
210213
set_source_files_properties(xdiff/xutils.c PROPERTIES COMPILE_FLAGS -WX-)
214+
set_source_files_properties(xdiff/xpatience.c PROPERTIES COMPILE_FLAGS -WX-)
215+
else()
216+
set_source_files_properties(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
217+
set_source_files_properties(xdiff/xemit.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
218+
set_source_files_properties(xdiff/xhistogram.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
219+
set_source_files_properties(xdiff/xutils.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
220+
set_source_files_properties(xdiff/xpatience.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
211221
endif()
212222

213223
# Determine architecture of the machine

src/blame_git.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ static void fill_origin_blob(git_blame__origin *o, mmfile_t *file)
393393
memset(file, 0, sizeof(*file));
394394
if (o->blob) {
395395
file->ptr = (char*)git_blob_rawcontent(o->blob);
396-
file->size = (size_t)git_blob_rawsize(o->blob);
396+
file->size = (long)git_blob_rawsize(o->blob);
397397
}
398398
}
399399

src/checkout.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2070,6 +2070,9 @@ static int checkout_write_merge(
20702070
if (data->opts.checkout_strategy & GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)
20712071
opts.flags |= GIT_MERGE_FILE_STYLE_DIFF3;
20722072

2073+
if (data->opts.checkout_strategy & GIT_CHECKOUT_CONFLICT_STYLE_ZDIFF3)
2074+
opts.flags |= GIT_MERGE_FILE_STYLE_ZDIFF3;
2075+
20732076
opts.ancestor_label = data->opts.ancestor_label ?
20742077
data->opts.ancestor_label : "ancestor";
20752078
opts.our_label = data->opts.our_label ?
@@ -2493,6 +2496,8 @@ static int checkout_data_init(
24932496
data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_MERGE;
24942497
else if (strcmp(conflict_style->value, "diff3") == 0)
24952498
data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_DIFF3;
2499+
else if (strcmp(conflict_style->value, "zdiff3") == 0)
2500+
data->opts.checkout_strategy |= GIT_CHECKOUT_CONFLICT_STYLE_ZDIFF3;
24962501
else {
24972502
git_error_set(GIT_ERROR_CHECKOUT, "unknown style '%s' given for 'merge.conflictstyle'",
24982503
conflict_style->value);

src/diff_xdiff.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -218,14 +218,9 @@ static int git_xdiff(git_patch_generated_output *output, git_patch_generated *pa
218218
* updates are needed to xo->params.flags
219219
*/
220220

221-
git_patch_generated_old_data(&info.xd_old_data.ptr, &info.xd_old_data.size, patch);
222-
git_patch_generated_new_data(&info.xd_new_data.ptr, &info.xd_new_data.size, patch);
223-
224-
if (info.xd_old_data.size > GIT_XDIFF_MAX_SIZE ||
225-
info.xd_new_data.size > GIT_XDIFF_MAX_SIZE) {
226-
git_error_set(GIT_ERROR_INVALID, "files too large for diff");
221+
if (git_patch_generated_old_data(&info.xd_old_data.ptr, &info.xd_old_data.size, patch) < 0 ||
222+
git_patch_generated_new_data(&info.xd_new_data.ptr, &info.xd_new_data.size, patch) < 0)
227223
return -1;
228-
}
229224

230225
xdl_diff(&info.xd_old_data, &info.xd_new_data,
231226
&xo->params, &xo->config, &xo->callback);
@@ -261,5 +256,5 @@ void git_xdiff_init(git_xdiff_output *xo, const git_diff_options *opts)
261256
if (flags & GIT_DIFF_IGNORE_BLANK_LINES)
262257
xo->params.flags |= XDF_IGNORE_BLANK_LINES;
263258

264-
xo->callback.outf = git_xdiff_cb;
259+
xo->callback.out_line = git_xdiff_cb;
265260
}

src/merge_file.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,22 +86,30 @@ static int merge_file__xdiff(
8686

8787
memset(&xmparam, 0x0, sizeof(xmparam_t));
8888

89+
if (ours->size > LONG_MAX ||
90+
theirs->size > LONG_MAX ||
91+
(ancestor && ancestor->size > LONG_MAX)) {
92+
git_error_set(GIT_ERROR_MERGE, "failed to merge files");
93+
error = -1;
94+
goto done;
95+
}
96+
8997
if (ancestor) {
9098
xmparam.ancestor = (options.ancestor_label) ?
9199
options.ancestor_label : ancestor->path;
92100
ancestor_mmfile.ptr = (char *)ancestor->ptr;
93-
ancestor_mmfile.size = ancestor->size;
101+
ancestor_mmfile.size = (long)ancestor->size;
94102
}
95103

96104
xmparam.file1 = (options.our_label) ?
97105
options.our_label : ours->path;
98106
our_mmfile.ptr = (char *)ours->ptr;
99-
our_mmfile.size = ours->size;
107+
our_mmfile.size = (long)ours->size;
100108

101109
xmparam.file2 = (options.their_label) ?
102110
options.their_label : theirs->path;
103111
their_mmfile.ptr = (char *)theirs->ptr;
104-
their_mmfile.size = theirs->size;
112+
their_mmfile.size = (long)theirs->size;
105113

106114
if (options.favor == GIT_MERGE_FILE_FAVOR_OURS)
107115
xmparam.favor = XDL_MERGE_FAVOR_OURS;
@@ -115,6 +123,8 @@ static int merge_file__xdiff(
115123

116124
if (options.flags & GIT_MERGE_FILE_STYLE_DIFF3)
117125
xmparam.style = XDL_MERGE_DIFF3;
126+
if (options.flags & GIT_MERGE_FILE_STYLE_ZDIFF3)
127+
xmparam.style = XDL_MERGE_ZEALOUS_DIFF3;
118128

119129
if (options.flags & GIT_MERGE_FILE_IGNORE_WHITESPACE)
120130
xmparam.xpp.flags |= XDF_IGNORE_WHITESPACE;

src/patch_generate.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -750,18 +750,34 @@ git_diff_driver *git_patch_generated_driver(git_patch_generated *patch)
750750
return patch->ofile.driver;
751751
}
752752

753-
void git_patch_generated_old_data(
754-
char **ptr, size_t *len, git_patch_generated *patch)
753+
int git_patch_generated_old_data(
754+
char **ptr, long *len, git_patch_generated *patch)
755755
{
756+
if (patch->ofile.map.len > LONG_MAX ||
757+
patch->ofile.map.len > GIT_XDIFF_MAX_SIZE) {
758+
git_error_set(GIT_ERROR_INVALID, "files too large for diff");
759+
return -1;
760+
}
761+
756762
*ptr = patch->ofile.map.data;
757-
*len = patch->ofile.map.len;
763+
*len = (long)patch->ofile.map.len;
764+
765+
return 0;
758766
}
759767

760-
void git_patch_generated_new_data(
761-
char **ptr, size_t *len, git_patch_generated *patch)
768+
int git_patch_generated_new_data(
769+
char **ptr, long *len, git_patch_generated *patch)
762770
{
771+
if (patch->ofile.map.len > LONG_MAX ||
772+
patch->ofile.map.len > GIT_XDIFF_MAX_SIZE) {
773+
git_error_set(GIT_ERROR_INVALID, "files too large for diff");
774+
return -1;
775+
}
776+
763777
*ptr = patch->nfile.map.data;
764-
*len = patch->nfile.map.len;
778+
*len = (long)patch->nfile.map.len;
779+
780+
return 0;
765781
}
766782

767783
static int patch_generated_file_cb(

src/patch_generate.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ typedef struct git_patch_generated git_patch_generated;
3939

4040
extern git_diff_driver *git_patch_generated_driver(git_patch_generated *);
4141

42-
extern void git_patch_generated_old_data(
43-
char **, size_t *, git_patch_generated *);
44-
extern void git_patch_generated_new_data(
45-
char **, size_t *, git_patch_generated *);
42+
extern int git_patch_generated_old_data(
43+
char **, long *, git_patch_generated *);
44+
extern int git_patch_generated_new_data(
45+
char **, long *, git_patch_generated *);
4646
extern int git_patch_generated_from_diff(
4747
git_patch **, git_diff *, size_t);
4848

src/xdiff/git-xdiff.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (C) the libgit2 contributors. All rights reserved.
3+
*
4+
* This file is part of libgit2, distributed under the GNU GPL v2 with
5+
* a Linking Exception. For full terms see the included COPYING file.
6+
*/
7+
8+
/*
9+
* This file provides the necessary indirection between xdiff and
10+
* libgit2. libgit2-specific functionality should live here, so
11+
* that git and libgit2 can share a common xdiff implementation.
12+
*/
13+
14+
#ifndef INCLUDE_git_xdiff_h__
15+
#define INCLUDE_git_xdiff_h__
16+
17+
#include "regexp.h"
18+
19+
#define xdl_malloc(x) git__malloc(x)
20+
#define xdl_free(ptr) git__free(ptr)
21+
#define xdl_realloc(ptr, x) git__realloc(ptr, x)
22+
23+
#define XDL_BUG(msg) GIT_ASSERT(msg)
24+
25+
#define xdl_regex_t git_regexp
26+
#define xdl_regmatch_t git_regmatch
27+
28+
GIT_INLINE(int) xdl_regexec_buf(
29+
const xdl_regex_t *preg, const char *buf, size_t size,
30+
size_t nmatch, xdl_regmatch_t pmatch[], int eflags)
31+
{
32+
GIT_UNUSED(preg);
33+
GIT_UNUSED(buf);
34+
GIT_UNUSED(size);
35+
GIT_UNUSED(nmatch);
36+
GIT_UNUSED(pmatch);
37+
GIT_UNUSED(eflags);
38+
GIT_ASSERT("not implemented");
39+
return -1;
40+
}
41+
42+
#endif

0 commit comments

Comments
 (0)