Skip to content

Commit 9acf322

Browse files
author
Junio C Hamano
committed
Merge branch 'lt/diffgen' into next
* lt/diffgen: built-in diff: minimum tweaks builtin-diff: \No newline at end of file. Use a *real* built-in diff generator
2 parents 48d6e97 + 3ce8f08 commit 9acf322

File tree

15 files changed

+1864
-9
lines changed

15 files changed

+1864
-9
lines changed

Makefile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ PYMODULES = \
188188
gitMergeCommon.py
189189

190190
LIB_FILE=libgit.a
191+
XDIFF_LIB=xdiff/lib.a
191192

192193
LIB_H = \
193194
blob.h cache.h commit.h csum-file.h delta.h \
@@ -209,7 +210,7 @@ LIB_OBJS = \
209210
fetch-clone.o revision.o pager.o \
210211
$(DIFF_OBJS)
211212

212-
LIBS = $(LIB_FILE)
213+
LIBS = $(LIB_FILE) $(XDIFF_LIB)
213214
LIBS += -lz
214215

215216
#
@@ -544,12 +545,18 @@ init-db.o: init-db.c
544545
-DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c
545546

546547
$(LIB_OBJS): $(LIB_H)
547-
$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H)
548+
$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIBS)
548549
$(DIFF_OBJS): diffcore.h
549550

550551
$(LIB_FILE): $(LIB_OBJS)
551552
$(AR) rcs $@ $(LIB_OBJS)
552553

554+
XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o
555+
556+
$(XDIFF_LIB): $(XDIFF_OBJS)
557+
$(AR) rcs $@ $(XDIFF_OBJS)
558+
559+
553560
doc:
554561
$(MAKE) -C Documentation all
555562

diff.c

Lines changed: 104 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "quote.h"
99
#include "diff.h"
1010
#include "diffcore.h"
11+
#include "xdiff/xdiff.h"
1112

1213
static const char *diff_opts = "-pu";
1314

@@ -178,6 +179,70 @@ static void emit_rewrite_diff(const char *name_a,
178179
copy_file('+', temp[1].name);
179180
}
180181

182+
static int fill_mmfile(mmfile_t *mf, const char *file)
183+
{
184+
int fd = open(file, O_RDONLY);
185+
struct stat st;
186+
char *buf;
187+
unsigned long size;
188+
189+
mf->ptr = NULL;
190+
mf->size = 0;
191+
if (fd < 0)
192+
return 0;
193+
fstat(fd, &st);
194+
size = st.st_size;
195+
buf = xmalloc(size);
196+
mf->ptr = buf;
197+
mf->size = size;
198+
while (size) {
199+
int retval = read(fd, buf, size);
200+
if (retval < 0) {
201+
if (errno == EINTR || errno == EAGAIN)
202+
continue;
203+
break;
204+
}
205+
if (!retval)
206+
break;
207+
buf += retval;
208+
size -= retval;
209+
}
210+
mf->size -= size;
211+
close(fd);
212+
return 0;
213+
}
214+
215+
struct emit_callback {
216+
const char **label_path;
217+
};
218+
219+
static int fn_out(void *priv, mmbuffer_t *mb, int nbuf)
220+
{
221+
int i;
222+
struct emit_callback *ecbdata = priv;
223+
224+
if (ecbdata->label_path[0]) {
225+
printf("--- %s\n", ecbdata->label_path[0]);
226+
printf("+++ %s\n", ecbdata->label_path[1]);
227+
ecbdata->label_path[0] = ecbdata->label_path[1] = NULL;
228+
}
229+
for (i = 0; i < nbuf; i++)
230+
if (!fwrite(mb[i].ptr, mb[i].size, 1, stdout))
231+
return -1;
232+
return 0;
233+
}
234+
235+
#define FIRST_FEW_BYTES 8000
236+
static int mmfile_is_binary(mmfile_t *mf)
237+
{
238+
long sz = mf->size;
239+
if (FIRST_FEW_BYTES < sz)
240+
sz = FIRST_FEW_BYTES;
241+
if (memchr(mf->ptr, 0, sz))
242+
return 1;
243+
return 0;
244+
}
245+
181246
static const char *builtin_diff(const char *name_a,
182247
const char *name_b,
183248
struct diff_tempfile *temp,
@@ -186,6 +251,7 @@ static const char *builtin_diff(const char *name_a,
186251
const char **args)
187252
{
188253
int i, next_at, cmd_size;
254+
mmfile_t mf1, mf2;
189255
const char *const diff_cmd = "diff -L%s -L%s";
190256
const char *const diff_arg = "-- %s %s||:"; /* "||:" is to return 0 */
191257
const char *input_name_sq[2];
@@ -255,12 +321,44 @@ static const char *builtin_diff(const char *name_a,
255321
}
256322
}
257323

258-
/* This is disgusting */
259-
*args++ = "sh";
260-
*args++ = "-c";
261-
*args++ = cmd;
262-
*args = NULL;
263-
return "/bin/sh";
324+
/* Un-quote the paths */
325+
if (label_path[0][0] != '/')
326+
label_path[0] = quote_two("a/", name_a);
327+
if (label_path[1][0] != '/')
328+
label_path[1] = quote_two("b/", name_b);
329+
330+
if (fill_mmfile(&mf1, temp[0].name) < 0 ||
331+
fill_mmfile(&mf2, temp[1].name) < 0)
332+
die("unable to read files to diff");
333+
334+
if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2))
335+
printf("Binary files %s and %s differ\n",
336+
label_path[0], label_path[1]);
337+
else {
338+
/* Crazy xdl interfaces.. */
339+
const char *diffopts = getenv("GIT_DIFF_OPTS");
340+
xpparam_t xpp;
341+
xdemitconf_t xecfg;
342+
xdemitcb_t ecb;
343+
struct emit_callback ecbdata;
344+
345+
ecbdata.label_path = label_path;
346+
xpp.flags = XDF_NEED_MINIMAL;
347+
xecfg.ctxlen = 3;
348+
if (!diffopts)
349+
;
350+
else if (!strncmp(diffopts, "--unified=", 10))
351+
xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
352+
else if (!strncmp(diffopts, "-u", 2))
353+
xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
354+
ecb.outf = fn_out;
355+
ecb.priv = &ecbdata;
356+
xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
357+
}
358+
359+
free(mf1.ptr);
360+
free(mf2.ptr);
361+
return NULL;
264362
}
265363

266364
struct diff_filespec *alloc_filespec(const char *path)

t/t4001-diff-rename.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ rename from path0
4949
rename to path1
5050
--- a/path0
5151
+++ b/path1
52-
@@ -8,7 +8,7 @@ Line 7
52+
@@ -8,7 +8,7 @@
5353
Line 8
5454
Line 9
5555
Line 10

xdiff/xdiff.h

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* LibXDiff by Davide Libenzi ( File Differential Library )
3+
* Copyright (C) 2003 Davide Libenzi
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 2.1 of the License, or (at your option) any later version.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18+
*
19+
* Davide Libenzi <davidel@xmailserver.org>
20+
*
21+
*/
22+
23+
#if !defined(XDIFF_H)
24+
#define XDIFF_H
25+
26+
#ifdef __cplusplus
27+
extern "C" {
28+
#endif /* #ifdef __cplusplus */
29+
30+
31+
#define XDF_NEED_MINIMAL (1 << 1)
32+
33+
#define XDL_PATCH_NORMAL '-'
34+
#define XDL_PATCH_REVERSE '+'
35+
#define XDL_PATCH_MODEMASK ((1 << 8) - 1)
36+
#define XDL_PATCH_IGNOREBSPACE (1 << 8)
37+
38+
#define XDL_MMB_READONLY (1 << 0)
39+
40+
#define XDL_MMF_ATOMIC (1 << 0)
41+
42+
#define XDL_BDOP_INS 1
43+
#define XDL_BDOP_CPY 2
44+
#define XDL_BDOP_INSB 3
45+
46+
47+
typedef struct s_mmfile {
48+
char *ptr;
49+
long size;
50+
} mmfile_t;
51+
52+
typedef struct s_mmbuffer {
53+
char *ptr;
54+
long size;
55+
} mmbuffer_t;
56+
57+
typedef struct s_xpparam {
58+
unsigned long flags;
59+
} xpparam_t;
60+
61+
typedef struct s_xdemitcb {
62+
void *priv;
63+
int (*outf)(void *, mmbuffer_t *, int);
64+
} xdemitcb_t;
65+
66+
typedef struct s_xdemitconf {
67+
long ctxlen;
68+
} xdemitconf_t;
69+
70+
typedef struct s_bdiffparam {
71+
long bsize;
72+
} bdiffparam_t;
73+
74+
75+
#define xdl_malloc(x) malloc(x)
76+
#define xdl_free(ptr) free(ptr)
77+
#define xdl_realloc(ptr,x) realloc(ptr,x)
78+
79+
void *xdl_mmfile_first(mmfile_t *mmf, long *size);
80+
void *xdl_mmfile_next(mmfile_t *mmf, long *size);
81+
long xdl_mmfile_size(mmfile_t *mmf);
82+
83+
int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
84+
xdemitconf_t const *xecfg, xdemitcb_t *ecb);
85+
86+
#ifdef __cplusplus
87+
}
88+
#endif /* #ifdef __cplusplus */
89+
90+
#endif /* #if !defined(XDIFF_H) */
91+

0 commit comments

Comments
 (0)