Commit 1458fb56 by Edward Thomson

xdiff: include new xdiff from git

Update to the xdiff used in git v2.35.0, with updates to our build
configuration to ignore the sort of warnings that we normally care
about (signed/unsigned mismatch, unused, etc.)

Any git-specific abstraction bits are now redefined for our use in
`git-xdiff.h`.  It is a (wildly optimistic) hope that we can use that
indirection layer to standardize on a shared xdiff implementation.
parent 12c2eef7
...@@ -206,7 +206,17 @@ endif() ...@@ -206,7 +206,17 @@ endif()
# errors for the xdiff sources until we've sorted them out # errors for the xdiff sources until we've sorted them out
if(MSVC) if(MSVC)
set_source_files_properties(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS -WX-) set_source_files_properties(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xdiff/xemit.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xdiff/xhistogram.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xdiff/xmerge.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xdiff/xutils.c PROPERTIES COMPILE_FLAGS -WX-) set_source_files_properties(xdiff/xutils.c PROPERTIES COMPILE_FLAGS -WX-)
set_source_files_properties(xdiff/xpatience.c PROPERTIES COMPILE_FLAGS -WX-)
else()
set_source_files_properties(xdiff/xdiffi.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
set_source_files_properties(xdiff/xemit.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter")
set_source_files_properties(xdiff/xhistogram.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
set_source_files_properties(xdiff/xutils.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
set_source_files_properties(xdiff/xpatience.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare")
endif() endif()
# Determine architecture of the machine # Determine architecture of the machine
......
...@@ -393,7 +393,7 @@ static void fill_origin_blob(git_blame__origin *o, mmfile_t *file) ...@@ -393,7 +393,7 @@ static void fill_origin_blob(git_blame__origin *o, mmfile_t *file)
memset(file, 0, sizeof(*file)); memset(file, 0, sizeof(*file));
if (o->blob) { if (o->blob) {
file->ptr = (char*)git_blob_rawcontent(o->blob); file->ptr = (char*)git_blob_rawcontent(o->blob);
file->size = (size_t)git_blob_rawsize(o->blob); file->size = (long)git_blob_rawsize(o->blob);
} }
} }
......
...@@ -218,14 +218,9 @@ static int git_xdiff(git_patch_generated_output *output, git_patch_generated *pa ...@@ -218,14 +218,9 @@ static int git_xdiff(git_patch_generated_output *output, git_patch_generated *pa
* updates are needed to xo->params.flags * updates are needed to xo->params.flags
*/ */
git_patch_generated_old_data(&info.xd_old_data.ptr, &info.xd_old_data.size, patch); if (git_patch_generated_old_data(&info.xd_old_data.ptr, &info.xd_old_data.size, patch) < 0 ||
git_patch_generated_new_data(&info.xd_new_data.ptr, &info.xd_new_data.size, patch); git_patch_generated_new_data(&info.xd_new_data.ptr, &info.xd_new_data.size, patch) < 0)
if (info.xd_old_data.size > GIT_XDIFF_MAX_SIZE ||
info.xd_new_data.size > GIT_XDIFF_MAX_SIZE) {
git_error_set(GIT_ERROR_INVALID, "files too large for diff");
return -1; return -1;
}
xdl_diff(&info.xd_old_data, &info.xd_new_data, xdl_diff(&info.xd_old_data, &info.xd_new_data,
&xo->params, &xo->config, &xo->callback); &xo->params, &xo->config, &xo->callback);
...@@ -261,5 +256,5 @@ void git_xdiff_init(git_xdiff_output *xo, const git_diff_options *opts) ...@@ -261,5 +256,5 @@ void git_xdiff_init(git_xdiff_output *xo, const git_diff_options *opts)
if (flags & GIT_DIFF_IGNORE_BLANK_LINES) if (flags & GIT_DIFF_IGNORE_BLANK_LINES)
xo->params.flags |= XDF_IGNORE_BLANK_LINES; xo->params.flags |= XDF_IGNORE_BLANK_LINES;
xo->callback.outf = git_xdiff_cb; xo->callback.out_line = git_xdiff_cb;
} }
...@@ -86,22 +86,30 @@ static int merge_file__xdiff( ...@@ -86,22 +86,30 @@ static int merge_file__xdiff(
memset(&xmparam, 0x0, sizeof(xmparam_t)); memset(&xmparam, 0x0, sizeof(xmparam_t));
if (ours->size > LONG_MAX ||
theirs->size > LONG_MAX ||
(ancestor && ancestor->size > LONG_MAX)) {
git_error_set(GIT_ERROR_MERGE, "failed to merge files");
error = -1;
goto done;
}
if (ancestor) { if (ancestor) {
xmparam.ancestor = (options.ancestor_label) ? xmparam.ancestor = (options.ancestor_label) ?
options.ancestor_label : ancestor->path; options.ancestor_label : ancestor->path;
ancestor_mmfile.ptr = (char *)ancestor->ptr; ancestor_mmfile.ptr = (char *)ancestor->ptr;
ancestor_mmfile.size = ancestor->size; ancestor_mmfile.size = (long)ancestor->size;
} }
xmparam.file1 = (options.our_label) ? xmparam.file1 = (options.our_label) ?
options.our_label : ours->path; options.our_label : ours->path;
our_mmfile.ptr = (char *)ours->ptr; our_mmfile.ptr = (char *)ours->ptr;
our_mmfile.size = ours->size; our_mmfile.size = (long)ours->size;
xmparam.file2 = (options.their_label) ? xmparam.file2 = (options.their_label) ?
options.their_label : theirs->path; options.their_label : theirs->path;
their_mmfile.ptr = (char *)theirs->ptr; their_mmfile.ptr = (char *)theirs->ptr;
their_mmfile.size = theirs->size; their_mmfile.size = (long)theirs->size;
if (options.favor == GIT_MERGE_FILE_FAVOR_OURS) if (options.favor == GIT_MERGE_FILE_FAVOR_OURS)
xmparam.favor = XDL_MERGE_FAVOR_OURS; xmparam.favor = XDL_MERGE_FAVOR_OURS;
......
...@@ -750,18 +750,34 @@ git_diff_driver *git_patch_generated_driver(git_patch_generated *patch) ...@@ -750,18 +750,34 @@ git_diff_driver *git_patch_generated_driver(git_patch_generated *patch)
return patch->ofile.driver; return patch->ofile.driver;
} }
void git_patch_generated_old_data( int git_patch_generated_old_data(
char **ptr, size_t *len, git_patch_generated *patch) char **ptr, long *len, git_patch_generated *patch)
{ {
if (patch->ofile.map.len > LONG_MAX ||
patch->ofile.map.len > GIT_XDIFF_MAX_SIZE) {
git_error_set(GIT_ERROR_INVALID, "files too large for diff");
return -1;
}
*ptr = patch->ofile.map.data; *ptr = patch->ofile.map.data;
*len = patch->ofile.map.len; *len = (long)patch->ofile.map.len;
return 0;
} }
void git_patch_generated_new_data( int git_patch_generated_new_data(
char **ptr, size_t *len, git_patch_generated *patch) char **ptr, long *len, git_patch_generated *patch)
{ {
if (patch->ofile.map.len > LONG_MAX ||
patch->ofile.map.len > GIT_XDIFF_MAX_SIZE) {
git_error_set(GIT_ERROR_INVALID, "files too large for diff");
return -1;
}
*ptr = patch->nfile.map.data; *ptr = patch->nfile.map.data;
*len = patch->nfile.map.len; *len = (long)patch->nfile.map.len;
return 0;
} }
static int patch_generated_file_cb( static int patch_generated_file_cb(
......
...@@ -39,10 +39,10 @@ typedef struct git_patch_generated git_patch_generated; ...@@ -39,10 +39,10 @@ typedef struct git_patch_generated git_patch_generated;
extern git_diff_driver *git_patch_generated_driver(git_patch_generated *); extern git_diff_driver *git_patch_generated_driver(git_patch_generated *);
extern void git_patch_generated_old_data( extern int git_patch_generated_old_data(
char **, size_t *, git_patch_generated *); char **, long *, git_patch_generated *);
extern void git_patch_generated_new_data( extern int git_patch_generated_new_data(
char **, size_t *, git_patch_generated *); char **, long *, git_patch_generated *);
extern int git_patch_generated_from_diff( extern int git_patch_generated_from_diff(
git_patch **, git_diff *, size_t); git_patch **, git_diff *, size_t);
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
/*
* This file provides the necessary indirection between xdiff and
* libgit2. libgit2-specific functionality should live here, so
* that git and libgit2 can share a common xdiff implementation.
*/
#ifndef INCLUDE_git_xdiff_h__
#define INCLUDE_git_xdiff_h__
#include "regexp.h"
#define xdl_malloc(x) git__malloc(x)
#define xdl_free(ptr) git__free(ptr)
#define xdl_realloc(ptr, x) git__realloc(ptr, x)
#define XDL_BUG(msg) GIT_ASSERT(msg)
#define xdl_regex_t git_regexp
#define xdl_regmatch_t git_regmatch
GIT_INLINE(int) xdl_regexec_buf(
const xdl_regex_t *preg, const char *buf, size_t size,
size_t nmatch, xdl_regmatch_t pmatch[], int eflags)
{
GIT_UNUSED(preg);
GIT_UNUSED(buf);
GIT_UNUSED(size);
GIT_UNUSED(nmatch);
GIT_UNUSED(pmatch);
GIT_UNUSED(eflags);
GIT_ASSERT("not implemented");
return -1;
}
#endif
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
#if !defined(XDIFF_H) #if !defined(XDIFF_H)
#define XDIFF_H #define XDIFF_H
#include "git-xdiff.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* #ifdef __cplusplus */ #endif /* #ifdef __cplusplus */
...@@ -50,16 +52,9 @@ extern "C" { ...@@ -50,16 +52,9 @@ extern "C" {
/* xdemitconf_t.flags */ /* xdemitconf_t.flags */
#define XDL_EMIT_FUNCNAMES (1 << 0) #define XDL_EMIT_FUNCNAMES (1 << 0)
#define XDL_EMIT_NO_HUNK_HDR (1 << 1)
#define XDL_EMIT_FUNCCONTEXT (1 << 2) #define XDL_EMIT_FUNCCONTEXT (1 << 2)
#define XDL_MMB_READONLY (1 << 0)
#define XDL_MMF_ATOMIC (1 << 0)
#define XDL_BDOP_INS 1
#define XDL_BDOP_CPY 2
#define XDL_BDOP_INSB 3
/* merge simplification levels */ /* merge simplification levels */
#define XDL_MERGE_MINIMAL 0 #define XDL_MERGE_MINIMAL 0
#define XDL_MERGE_EAGER 1 #define XDL_MERGE_EAGER 1
...@@ -73,20 +68,25 @@ extern "C" { ...@@ -73,20 +68,25 @@ extern "C" {
/* merge output styles */ /* merge output styles */
#define XDL_MERGE_DIFF3 1 #define XDL_MERGE_DIFF3 1
#define XDL_MERGE_ZEALOUS_DIFF3 2
typedef struct s_mmfile { typedef struct s_mmfile {
char *ptr; char *ptr;
size_t size; long size;
} mmfile_t; } mmfile_t;
typedef struct s_mmbuffer { typedef struct s_mmbuffer {
char *ptr; char *ptr;
size_t size; long size;
} mmbuffer_t; } mmbuffer_t;
typedef struct s_xpparam { typedef struct s_xpparam {
unsigned long flags; unsigned long flags;
/* -I<regex> */
xdl_regex_t **ignore_regex;
size_t ignore_regex_nr;
/* See Documentation/diff-options.txt. */ /* See Documentation/diff-options.txt. */
char **anchors; char **anchors;
size_t anchors_nr; size_t anchors_nr;
...@@ -94,7 +94,11 @@ typedef struct s_xpparam { ...@@ -94,7 +94,11 @@ typedef struct s_xpparam {
typedef struct s_xdemitcb { typedef struct s_xdemitcb {
void *priv; void *priv;
int (*outf)(void *, mmbuffer_t *, int); int (*out_hunk)(void *,
long old_begin, long old_nr,
long new_begin, long new_nr,
const char *func, long funclen);
int (*out_line)(void *, mmbuffer_t *, int);
} xdemitcb_t; } xdemitcb_t;
typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long buffer_size, void *priv); typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long buffer_size, void *priv);
...@@ -117,10 +121,6 @@ typedef struct s_bdiffparam { ...@@ -117,10 +121,6 @@ typedef struct s_bdiffparam {
} bdiffparam_t; } bdiffparam_t;
#define xdl_malloc(x) git__malloc(x)
#define xdl_free(ptr) git__free(ptr)
#define xdl_realloc(ptr,x) git__realloc(ptr,x)
void *xdl_mmfile_first(mmfile_t *mmf, long *size); void *xdl_mmfile_first(mmfile_t *mmf, long *size);
long xdl_mmfile_size(mmfile_t *mmf); long xdl_mmfile_size(mmfile_t *mmf);
......
...@@ -31,7 +31,7 @@ static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec) { ...@@ -31,7 +31,7 @@ static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec) {
static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb) { static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb) {
long size, psize = (long)strlen(pre); long size, psize = strlen(pre);
char const *rec; char const *rec;
size = xdl_get_rec(xdf, ri, &rec); size = xdl_get_rec(xdf, ri, &rec);
...@@ -81,7 +81,7 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg) ...@@ -81,7 +81,7 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
} else if (distance < max_ignorable && xch->ignore) { } else if (distance < max_ignorable && xch->ignore) {
ignored += xch->chg2; ignored += xch->chg2;
} else if (lxch != xchp && } else if (lxch != xchp &&
xch->i1 + ignored - (lxch->i1 + lxch->chg1) > (unsigned long)max_common) { xch->i1 + ignored - (lxch->i1 + lxch->chg1) > max_common) {
break; break;
} else if (!xch->ignore) { } else if (!xch->ignore) {
lxch = xch; lxch = xch;
...@@ -97,8 +97,6 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg) ...@@ -97,8 +97,6 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
static long def_ff(const char *rec, long len, char *buf, long sz, void *priv) static long def_ff(const char *rec, long len, char *buf, long sz, void *priv)
{ {
(void)priv;
if (len > 0 && if (len > 0 &&
(isalpha((unsigned char)*rec) || /* identifier? */ (isalpha((unsigned char)*rec) || /* identifier? */
*rec == '_' || /* also identifier? */ *rec == '_' || /* also identifier? */
...@@ -174,10 +172,12 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, ...@@ -174,10 +172,12 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
struct func_line func_line = { 0 }; struct func_line func_line = { 0 };
for (xch = xscr; xch; xch = xche->next) { for (xch = xscr; xch; xch = xche->next) {
xdchange_t *xchp = xch;
xche = xdl_get_hunk(&xch, xecfg); xche = xdl_get_hunk(&xch, xecfg);
if (!xch) if (!xch)
break; break;
pre_context_calculation:
s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0); s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0);
s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0); s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0);
...@@ -212,8 +212,23 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, ...@@ -212,8 +212,23 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
if (fs1 < 0) if (fs1 < 0)
fs1 = 0; fs1 = 0;
if (fs1 < s1) { if (fs1 < s1) {
s2 -= s1 - fs1; s2 = XDL_MAX(s2 - (s1 - fs1), 0);
s1 = fs1; s1 = fs1;
/*
* Did we extend context upwards into an
* ignored change?
*/
while (xchp != xch &&
xchp->i1 + xchp->chg1 <= s1 &&
xchp->i2 + xchp->chg2 <= s2)
xchp = xchp->next;
/* If so, show it after all. */
if (xchp != xch) {
xch = xchp;
goto pre_context_calculation;
}
} }
} }
...@@ -234,7 +249,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, ...@@ -234,7 +249,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
if (fe1 < 0) if (fe1 < 0)
fe1 = xe->xdf1.nrec; fe1 = xe->xdf1.nrec;
if (fe1 > e1) { if (fe1 > e1) {
e2 += fe1 - e1; e2 = XDL_MIN(e2 + (fe1 - e1), xe->xdf2.nrec);
e1 = fe1; e1 = fe1;
} }
...@@ -263,7 +278,8 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, ...@@ -263,7 +278,8 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
s1 - 1, funclineprev); s1 - 1, funclineprev);
funclineprev = s1 - 1; funclineprev = s1 - 1;
} }
if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2, if (!(xecfg->flags & XDL_EMIT_NO_HUNK_HDR) &&
xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2,
func_line.buf, func_line.len, ecb) < 0) func_line.buf, func_line.len, ecb) < 0)
return -1; return -1;
......
...@@ -42,8 +42,6 @@ ...@@ -42,8 +42,6 @@
*/ */
#include "xinclude.h" #include "xinclude.h"
#include "xtypes.h"
#include "xdiff.h"
#define MAX_PTR UINT_MAX #define MAX_PTR UINT_MAX
#define MAX_CNT UINT_MAX #define MAX_CNT UINT_MAX
...@@ -90,27 +88,21 @@ struct region { ...@@ -90,27 +88,21 @@ struct region {
#define REC(env, s, l) \ #define REC(env, s, l) \
(env->xdf##s.recs[l - 1]) (env->xdf##s.recs[l - 1])
static int cmp_recs(xpparam_t const *xpp, static int cmp_recs(xrecord_t *r1, xrecord_t *r2)
xrecord_t *r1, xrecord_t *r2)
{ {
return r1->ha == r2->ha && return r1->ha == r2->ha;
xdl_recmatch(r1->ptr, r1->size, r2->ptr, r2->size,
xpp->flags);
}
#define CMP_ENV(xpp, env, s1, l1, s2, l2) \ }
(cmp_recs(xpp, REC(env, s1, l1), REC(env, s2, l2)))
#define CMP(i, s1, l1, s2, l2) \ #define CMP(i, s1, l1, s2, l2) \
(cmp_recs(i->xpp, REC(i->env, s1, l1), REC(i->env, s2, l2))) (cmp_recs(REC(i->env, s1, l1), REC(i->env, s2, l2)))
#define TABLE_HASH(index, side, line) \ #define TABLE_HASH(index, side, line) \
XDL_HASHLONG((REC(index->env, side, line))->ha, index->table_bits) XDL_HASHLONG((REC(index->env, side, line))->ha, index->table_bits)
static int scanA(struct histindex *index, unsigned int line1, unsigned int count1) static int scanA(struct histindex *index, int line1, int count1)
{ {
unsigned int ptr; unsigned int ptr, tbl_idx;
unsigned int tbl_idx;
unsigned int chain_len; unsigned int chain_len;
struct record **rec_chain, *rec; struct record **rec_chain, *rec;
...@@ -161,10 +153,8 @@ continue_scan: ...@@ -161,10 +153,8 @@ continue_scan:
return 0; return 0;
} }
static int try_lcs( static int try_lcs(struct histindex *index, struct region *lcs, int b_ptr,
struct histindex *index, struct region *lcs, unsigned int b_ptr, int line1, int count1, int line2, int count2)
unsigned int line1, unsigned int count1,
unsigned int line2, unsigned int count2)
{ {
unsigned int b_next = b_ptr + 1; unsigned int b_next = b_ptr + 1;
struct record *rec = index->records[TABLE_HASH(index, 2, b_ptr)]; struct record *rec = index->records[TABLE_HASH(index, 2, b_ptr)];
...@@ -236,59 +226,33 @@ static int try_lcs( ...@@ -236,59 +226,33 @@ static int try_lcs(
return b_next; return b_next;
} }
static int find_lcs( static int fall_back_to_classic_diff(xpparam_t const *xpp, xdfenv_t *env,
struct histindex *index, struct region *lcs, int line1, int count1, int line2, int count2)
unsigned int line1, unsigned int count1,
unsigned int line2, unsigned int count2)
{ {
unsigned int b_ptr; xpparam_t xpparam;
if (scanA(index, line1, count1))
return -1;
index->cnt = index->max_chain_length + 1;
for (b_ptr = line2; b_ptr <= LINE_END(2); ) memset(&xpparam, 0, sizeof(xpparam));
b_ptr = try_lcs(index, lcs, b_ptr, line1, count1, line2, count2); xpparam.flags = xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;
return index->has_common && index->max_chain_length < index->cnt; return xdl_fall_back_diff(env, &xpparam,
line1, count1, line2, count2);
} }
static int fall_back_to_classic_diff(struct histindex *index, static inline void free_index(struct histindex *index)
int line1, int count1, int line2, int count2)
{ {
xpparam_t xpp; xdl_free(index->records);
xpp.flags = index->xpp->flags & ~XDF_DIFF_ALGORITHM_MASK; xdl_free(index->line_map);
xdl_free(index->next_ptrs);
return xdl_fall_back_diff(index->env, &xpp, xdl_cha_free(&index->rcha);
line1, count1, line2, count2);
} }
static int histogram_diff( static int find_lcs(xpparam_t const *xpp, xdfenv_t *env,
xpparam_t const *xpp, xdfenv_t *env, struct region *lcs,
unsigned int line1, unsigned int count1, int line1, int count1, int line2, int count2)
unsigned int line2, unsigned int count2)
{ {
int b_ptr;
int sz, ret = -1;
struct histindex index; struct histindex index;
struct region lcs;
size_t sz;
int result = -1;
if (count1 <= 0 && count2 <= 0)
return 0;
if (LINE_END(1) >= MAX_PTR)
return -1;
if (!count1) {
while(count2--)
env->xdf2.rchg[line2++ - 1] = 1;
return 0;
} else if (!count2) {
while(count1--)
env->xdf1.rchg[line1++ - 1] = 1;
return 0;
}
memset(&index, 0, sizeof(index)); memset(&index, 0, sizeof(index));
...@@ -302,8 +266,7 @@ static int histogram_diff( ...@@ -302,8 +266,7 @@ static int histogram_diff(
index.table_bits = xdl_hashbits(count1); index.table_bits = xdl_hashbits(count1);
sz = index.records_size = 1 << index.table_bits; sz = index.records_size = 1 << index.table_bits;
GIT_ERROR_CHECK_ALLOC_MULTIPLY(&sz, sz, sizeof(struct record *)); sz *= sizeof(struct record *);
if (!(index.records = (struct record **) xdl_malloc(sz))) if (!(index.records = (struct record **) xdl_malloc(sz)))
goto cleanup; goto cleanup;
memset(index.records, 0, sz); memset(index.records, 0, sz);
...@@ -327,9 +290,55 @@ static int histogram_diff( ...@@ -327,9 +290,55 @@ static int histogram_diff(
index.ptr_shift = line1; index.ptr_shift = line1;
index.max_chain_length = 64; index.max_chain_length = 64;
if (scanA(&index, line1, count1))
goto cleanup;
index.cnt = index.max_chain_length + 1;
for (b_ptr = line2; b_ptr <= LINE_END(2); )
b_ptr = try_lcs(&index, lcs, b_ptr, line1, count1, line2, count2);
if (index.has_common && index.max_chain_length < index.cnt)
ret = 1;
else
ret = 0;
cleanup:
free_index(&index);
return ret;
}
static int histogram_diff(xpparam_t const *xpp, xdfenv_t *env,
int line1, int count1, int line2, int count2)
{
struct region lcs;
int lcs_found;
int result;
redo:
result = -1;
if (count1 <= 0 && count2 <= 0)
return 0;
if (LINE_END(1) >= MAX_PTR)
return -1;
if (!count1) {
while(count2--)
env->xdf2.rchg[line2++ - 1] = 1;
return 0;
} else if (!count2) {
while(count1--)
env->xdf1.rchg[line1++ - 1] = 1;
return 0;
}
memset(&lcs, 0, sizeof(lcs)); memset(&lcs, 0, sizeof(lcs));
if (find_lcs(&index, &lcs, line1, count1, line2, count2)) lcs_found = find_lcs(xpp, env, &lcs, line1, count1, line2, count2);
result = fall_back_to_classic_diff(&index, line1, count1, line2, count2); if (lcs_found < 0)
goto out;
else if (lcs_found)
result = fall_back_to_classic_diff(xpp, env, line1, count1, line2, count2);
else { else {
if (lcs.begin1 == 0 && lcs.begin2 == 0) { if (lcs.begin1 == 0 && lcs.begin2 == 0) {
while (count1--) while (count1--)
...@@ -342,21 +351,21 @@ static int histogram_diff( ...@@ -342,21 +351,21 @@ static int histogram_diff(
line1, lcs.begin1 - line1, line1, lcs.begin1 - line1,
line2, lcs.begin2 - line2); line2, lcs.begin2 - line2);
if (result) if (result)
goto cleanup; goto out;
result = histogram_diff(xpp, env, /*
lcs.end1 + 1, LINE_END(1) - lcs.end1, * result = histogram_diff(xpp, env,
lcs.end2 + 1, LINE_END(2) - lcs.end2); * lcs.end1 + 1, LINE_END(1) - lcs.end1,
if (result) * lcs.end2 + 1, LINE_END(2) - lcs.end2);
goto cleanup; * but let's optimize tail recursion ourself:
*/
count1 = LINE_END(1) - lcs.end1;
line1 = lcs.end1 + 1;
count2 = LINE_END(2) - lcs.end2;
line2 = lcs.end2 + 1;
goto redo;
} }
} }
out:
cleanup:
xdl_free(index.records);
xdl_free(index.line_map);
xdl_free(index.next_ptrs);
xdl_cha_free(&index.rcha);
return result; return result;
} }
......
...@@ -23,17 +23,7 @@ ...@@ -23,17 +23,7 @@
#if !defined(XINCLUDE_H) #if !defined(XINCLUDE_H)
#define XINCLUDE_H #define XINCLUDE_H
#include <ctype.h> #include "git-xdiff.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#ifdef _WIN32
#else
#include <unistd.h>
#endif
#include "xmacros.h" #include "xmacros.h"
#include "xdiff.h" #include "xdiff.h"
#include "xtypes.h" #include "xtypes.h"
...@@ -42,6 +32,5 @@ ...@@ -42,6 +32,5 @@
#include "xdiffi.h" #include "xdiffi.h"
#include "xemit.h" #include "xemit.h"
#include "common.h"
#endif /* #if !defined(XINCLUDE_H) */ #endif /* #if !defined(XINCLUDE_H) */
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
* *
*/ */
#include "xinclude.h" #include "xinclude.h"
#include "xtypes.h"
#include "xdiff.h"
/* /*
* The basic idea of patience diff is to find lines that are unique in * The basic idea of patience diff is to find lines that are unique in
...@@ -78,7 +76,7 @@ struct hashmap { ...@@ -78,7 +76,7 @@ struct hashmap {
static int is_anchor(xpparam_t const *xpp, const char *line) static int is_anchor(xpparam_t const *xpp, const char *line)
{ {
unsigned long i; int i;
for (i = 0; i < xpp->anchors_nr; i++) { for (i = 0; i < xpp->anchors_nr; i++) {
if (!strncmp(line, xpp->anchors[i], strlen(xpp->anchors[i]))) if (!strncmp(line, xpp->anchors[i], strlen(xpp->anchors[i])))
return 1; return 1;
...@@ -92,7 +90,7 @@ static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map, ...@@ -92,7 +90,7 @@ static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map,
{ {
xrecord_t **records = pass == 1 ? xrecord_t **records = pass == 1 ?
map->env->xdf1.recs : map->env->xdf2.recs; map->env->xdf1.recs : map->env->xdf2.recs;
xrecord_t *record = records[line - 1], *other; xrecord_t *record = records[line - 1];
/* /*
* After xdl_prepare_env() (or more precisely, due to * After xdl_prepare_env() (or more precisely, due to
* xdl_classify_record()), the "ha" member of the records (AKA lines) * xdl_classify_record()), the "ha" member of the records (AKA lines)
...@@ -106,11 +104,7 @@ static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map, ...@@ -106,11 +104,7 @@ static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map,
int index = (int)((record->ha << 1) % map->alloc); int index = (int)((record->ha << 1) % map->alloc);
while (map->entries[index].line1) { while (map->entries[index].line1) {
other = map->env->xdf1.recs[map->entries[index].line1 - 1]; if (map->entries[index].hash != record->ha) {
if (map->entries[index].hash != record->ha ||
!xdl_recmatch(record->ptr, record->size,
other->ptr, other->size,
map->xpp->flags)) {
if (++index >= map->alloc) if (++index >= map->alloc)
index = 0; index = 0;
continue; continue;
...@@ -217,9 +211,6 @@ static struct entry *find_longest_common_sequence(struct hashmap *map) ...@@ -217,9 +211,6 @@ static struct entry *find_longest_common_sequence(struct hashmap *map)
*/ */
int anchor_i = -1; int anchor_i = -1;
if (!sequence)
return NULL;
for (entry = map->first; entry; entry = entry->next) { for (entry = map->first; entry; entry = entry->next) {
if (!entry->line2 || entry->line2 == NON_UNIQUE) if (!entry->line2 || entry->line2 == NON_UNIQUE)
continue; continue;
...@@ -258,8 +249,7 @@ static int match(struct hashmap *map, int line1, int line2) ...@@ -258,8 +249,7 @@ static int match(struct hashmap *map, int line1, int line2)
{ {
xrecord_t *record1 = map->env->xdf1.recs[line1 - 1]; xrecord_t *record1 = map->env->xdf1.recs[line1 - 1];
xrecord_t *record2 = map->env->xdf2.recs[line2 - 1]; xrecord_t *record2 = map->env->xdf2.recs[line2 - 1];
return xdl_recmatch(record1->ptr, record1->size, return record1->ha == record2->ha;
record2->ptr, record2->size, map->xpp->flags);
} }
static int patience_diff(mmfile_t *file1, mmfile_t *file2, static int patience_diff(mmfile_t *file1, mmfile_t *file2,
...@@ -294,9 +284,6 @@ static int walk_common_sequence(struct hashmap *map, struct entry *first, ...@@ -294,9 +284,6 @@ static int walk_common_sequence(struct hashmap *map, struct entry *first,
/* Recurse */ /* Recurse */
if (next1 > line1 || next2 > line2) { if (next1 > line1 || next2 > line2) {
struct hashmap submap;
memset(&submap, 0, sizeof(submap));
if (patience_diff(map->file1, map->file2, if (patience_diff(map->file1, map->file2,
map->xpp, map->env, map->xpp, map->env,
line1, next1 - line1, line1, next1 - line1,
...@@ -323,6 +310,8 @@ static int fall_back_to_classic_diff(struct hashmap *map, ...@@ -323,6 +310,8 @@ static int fall_back_to_classic_diff(struct hashmap *map,
int line1, int count1, int line2, int count2) int line1, int count1, int line2, int count2)
{ {
xpparam_t xpp; xpparam_t xpp;
memset(&xpp, 0, sizeof(xpp));
xpp.flags = map->xpp->flags & ~XDF_DIFF_ALGORITHM_MASK; xpp.flags = map->xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;
return xdl_fall_back_diff(map->env, &xpp, return xdl_fall_back_diff(map->env, &xpp,
......
...@@ -181,15 +181,11 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_ ...@@ -181,15 +181,11 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
if (!(recs = (xrecord_t **) xdl_malloc(narec * sizeof(xrecord_t *)))) if (!(recs = (xrecord_t **) xdl_malloc(narec * sizeof(xrecord_t *))))
goto abort; goto abort;
if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF) hbits = xdl_hashbits((unsigned int) narec);
hbits = hsize = 0; hsize = 1 << hbits;
else { if (!(rhash = (xrecord_t **) xdl_malloc(hsize * sizeof(xrecord_t *))))
hbits = xdl_hashbits((unsigned int) narec); goto abort;
hsize = 1 << hbits; memset(rhash, 0, hsize * sizeof(xrecord_t *));
if (!(rhash = (xrecord_t **) xdl_malloc(hsize * sizeof(xrecord_t *))))
goto abort;
memset(rhash, 0, hsize * sizeof(xrecord_t *));
}
nrec = 0; nrec = 0;
if ((cur = blk = xdl_mmfile_first(mf, &bsize)) != NULL) { if ((cur = blk = xdl_mmfile_first(mf, &bsize)) != NULL) {
...@@ -208,9 +204,7 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_ ...@@ -208,9 +204,7 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
crec->size = (long) (cur - prev); crec->size = (long) (cur - prev);
crec->ha = hav; crec->ha = hav;
recs[nrec++] = crec; recs[nrec++] = crec;
if (xdl_classify_record(pass, cf, rhash, hbits, crec) < 0)
if ((XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF) &&
xdl_classify_record(pass, cf, rhash, hbits, crec) < 0)
goto abort; goto abort;
} }
} }
...@@ -219,10 +213,13 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_ ...@@ -219,10 +213,13 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
goto abort; goto abort;
memset(rchg, 0, (nrec + 2) * sizeof(char)); memset(rchg, 0, (nrec + 2) * sizeof(char));
if (!(rindex = (long *) xdl_malloc((nrec + 1) * sizeof(long)))) if ((XDF_DIFF_ALG(xpp->flags) != XDF_PATIENCE_DIFF) &&
goto abort; (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF)) {
if (!(ha = (unsigned long *) xdl_malloc((nrec + 1) * sizeof(unsigned long)))) if (!(rindex = xdl_malloc((nrec + 1) * sizeof(*rindex))))
goto abort; goto abort;
if (!(ha = xdl_malloc((nrec + 1) * sizeof(*ha))))
goto abort;
}
xdf->nrec = nrec; xdf->nrec = nrec;
xdf->recs = recs; xdf->recs = recs;
...@@ -279,8 +276,7 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, ...@@ -279,8 +276,7 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
enl1 = xdl_guess_lines(mf1, sample) + 1; enl1 = xdl_guess_lines(mf1, sample) + 1;
enl2 = xdl_guess_lines(mf2, sample) + 1; enl2 = xdl_guess_lines(mf2, sample) + 1;
if (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF && if (xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0)
xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0)
return -1; return -1;
if (xdl_prepare_ctx(1, mf1, enl1, xpp, &cf, &xe->xdf1) < 0) { if (xdl_prepare_ctx(1, mf1, enl1, xpp, &cf, &xe->xdf1) < 0) {
...@@ -305,8 +301,7 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, ...@@ -305,8 +301,7 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
return -1; return -1;
} }
if (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF) xdl_free_classifier(&cf);
xdl_free_classifier(&cf);
return 0; return 0;
} }
......
...@@ -23,8 +23,6 @@ ...@@ -23,8 +23,6 @@
#include "xinclude.h" #include "xinclude.h"
long xdl_bogosqrt(long n) { long xdl_bogosqrt(long n) {
long i; long i;
...@@ -52,7 +50,7 @@ int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize, ...@@ -52,7 +50,7 @@ int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize,
mb[2].size = strlen(mb[2].ptr); mb[2].size = strlen(mb[2].ptr);
i++; i++;
} }
if (ecb->outf(ecb->priv, mb, i) < 0) { if (ecb->out_line(ecb->priv, mb, i) < 0) {
return -1; return -1;
} }
...@@ -342,8 +340,9 @@ int xdl_num_out(char *out, long val) { ...@@ -342,8 +340,9 @@ int xdl_num_out(char *out, long val) {
return str - out; return str - out;
} }
int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, static int xdl_format_hunk_hdr(long s1, long c1, long s2, long c2,
const char *func, long funclen, xdemitcb_t *ecb) { const char *func, long funclen,
xdemitcb_t *ecb) {
int nb = 0; int nb = 0;
mmbuffer_t mb; mmbuffer_t mb;
char buf[128]; char buf[128];
...@@ -376,7 +375,7 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, ...@@ -376,7 +375,7 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
nb += 3; nb += 3;
if (func && funclen) { if (func && funclen) {
buf[nb++] = ' '; buf[nb++] = ' ';
if (funclen > (long)(sizeof(buf) - nb - 1)) if (funclen > sizeof(buf) - nb - 1)
funclen = sizeof(buf) - nb - 1; funclen = sizeof(buf) - nb - 1;
memcpy(buf + nb, func, funclen); memcpy(buf + nb, func, funclen);
nb += funclen; nb += funclen;
...@@ -385,9 +384,21 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, ...@@ -385,9 +384,21 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
mb.ptr = buf; mb.ptr = buf;
mb.size = nb; mb.size = nb;
if (ecb->outf(ecb->priv, &mb, 1) < 0) if (ecb->out_line(ecb->priv, &mb, 1) < 0)
return -1; return -1;
return 0;
}
int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
const char *func, long funclen,
xdemitcb_t *ecb) {
if (!ecb->out_hunk)
return xdl_format_hunk_hdr(s1, c1, s2, c2, func, funclen, ecb);
if (ecb->out_hunk(ecb->priv,
c1 ? s1 : s1 - 1, c1,
c2 ? s2 : s2 - 1, c2,
func, funclen) < 0)
return -1;
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment