Teach diff about -b and -w flags
This adds -b (--ignore-space-change) and -w (--ignore-all-space) flags to diff. The main part of the patch is teaching libxdiff about it. [jc: renamed xdl_line_match() to xdl_recmatch() since the former is used for different purposes in xpatchi.c which is in the parts of the upstream source we do not use.] Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
cda8ab59bb
commit
0d21efa51c
13
diff.c
13
diff.c
@ -678,7 +678,7 @@ static void builtin_diff(const char *name_a,
|
|||||||
memset(&ecbdata, 0, sizeof(ecbdata));
|
memset(&ecbdata, 0, sizeof(ecbdata));
|
||||||
ecbdata.label_path = lbl;
|
ecbdata.label_path = lbl;
|
||||||
ecbdata.color_diff = o->color_diff;
|
ecbdata.color_diff = o->color_diff;
|
||||||
xpp.flags = XDF_NEED_MINIMAL;
|
xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
|
||||||
xecfg.ctxlen = o->context;
|
xecfg.ctxlen = o->context;
|
||||||
xecfg.flags = XDL_EMIT_FUNCNAMES;
|
xecfg.flags = XDL_EMIT_FUNCNAMES;
|
||||||
if (!diffopts)
|
if (!diffopts)
|
||||||
@ -703,6 +703,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
|
|||||||
struct diff_filespec *one,
|
struct diff_filespec *one,
|
||||||
struct diff_filespec *two,
|
struct diff_filespec *two,
|
||||||
struct diffstat_t *diffstat,
|
struct diffstat_t *diffstat,
|
||||||
|
struct diff_options *o,
|
||||||
int complete_rewrite)
|
int complete_rewrite)
|
||||||
{
|
{
|
||||||
mmfile_t mf1, mf2;
|
mmfile_t mf1, mf2;
|
||||||
@ -732,7 +733,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
|
|||||||
xdemitconf_t xecfg;
|
xdemitconf_t xecfg;
|
||||||
xdemitcb_t ecb;
|
xdemitcb_t ecb;
|
||||||
|
|
||||||
xpp.flags = XDF_NEED_MINIMAL;
|
xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
|
||||||
xecfg.ctxlen = 0;
|
xecfg.ctxlen = 0;
|
||||||
xecfg.flags = 0;
|
xecfg.flags = 0;
|
||||||
ecb.outf = xdiff_outf;
|
ecb.outf = xdiff_outf;
|
||||||
@ -1317,7 +1318,7 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
|
|||||||
|
|
||||||
if (DIFF_PAIR_UNMERGED(p)) {
|
if (DIFF_PAIR_UNMERGED(p)) {
|
||||||
/* unmerged */
|
/* unmerged */
|
||||||
builtin_diffstat(p->one->path, NULL, NULL, NULL, diffstat, 0);
|
builtin_diffstat(p->one->path, NULL, NULL, NULL, diffstat, o, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1329,7 +1330,7 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
|
|||||||
|
|
||||||
if (p->status == DIFF_STATUS_MODIFIED && p->score)
|
if (p->status == DIFF_STATUS_MODIFIED && p->score)
|
||||||
complete_rewrite = 1;
|
complete_rewrite = 1;
|
||||||
builtin_diffstat(name, other, p->one, p->two, diffstat, complete_rewrite);
|
builtin_diffstat(name, other, p->one, p->two, diffstat, o, complete_rewrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
|
static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
|
||||||
@ -1534,6 +1535,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
|||||||
}
|
}
|
||||||
else if (!strcmp(arg, "--color"))
|
else if (!strcmp(arg, "--color"))
|
||||||
options->color_diff = 1;
|
options->color_diff = 1;
|
||||||
|
else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space"))
|
||||||
|
options->xdl_opts |= XDF_IGNORE_WHITESPACE;
|
||||||
|
else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
|
||||||
|
options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
1
diff.h
1
diff.h
@ -46,6 +46,7 @@ struct diff_options {
|
|||||||
int setup;
|
int setup;
|
||||||
int abbrev;
|
int abbrev;
|
||||||
const char *stat_sep;
|
const char *stat_sep;
|
||||||
|
long xdl_opts;
|
||||||
|
|
||||||
int nr_paths;
|
int nr_paths;
|
||||||
const char **paths;
|
const char **paths;
|
||||||
|
@ -29,6 +29,9 @@ extern "C" {
|
|||||||
|
|
||||||
|
|
||||||
#define XDF_NEED_MINIMAL (1 << 1)
|
#define XDF_NEED_MINIMAL (1 << 1)
|
||||||
|
#define XDF_IGNORE_WHITESPACE (1 << 2)
|
||||||
|
#define XDF_IGNORE_WHITESPACE_CHANGE (1 << 3)
|
||||||
|
#define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE)
|
||||||
|
|
||||||
#define XDL_PATCH_NORMAL '-'
|
#define XDL_PATCH_NORMAL '-'
|
||||||
#define XDL_PATCH_REVERSE '+'
|
#define XDL_PATCH_REVERSE '+'
|
||||||
|
@ -45,7 +45,7 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
|
|||||||
long *kvdf, long *kvdb, int need_min, xdpsplit_t *spl,
|
long *kvdf, long *kvdb, int need_min, xdpsplit_t *spl,
|
||||||
xdalgoenv_t *xenv);
|
xdalgoenv_t *xenv);
|
||||||
static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1, long chg2);
|
static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1, long chg2);
|
||||||
static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo);
|
static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -397,7 +397,7 @@ static xdchange_t *xdl_add_change(xdchange_t *xscr, long i1, long i2, long chg1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo) {
|
static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
|
||||||
long ix, ixo, ixs, ixref, grpsiz, nrec = xdf->nrec;
|
long ix, ixo, ixs, ixref, grpsiz, nrec = xdf->nrec;
|
||||||
char *rchg = xdf->rchg, *rchgo = xdfo->rchg;
|
char *rchg = xdf->rchg, *rchgo = xdfo->rchg;
|
||||||
xrecord_t **recs = xdf->recs;
|
xrecord_t **recs = xdf->recs;
|
||||||
@ -440,7 +440,7 @@ static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo) {
|
|||||||
* the group.
|
* the group.
|
||||||
*/
|
*/
|
||||||
while (ixs > 0 && recs[ixs - 1]->ha == recs[ix - 1]->ha &&
|
while (ixs > 0 && recs[ixs - 1]->ha == recs[ix - 1]->ha &&
|
||||||
XDL_RECMATCH(recs[ixs - 1], recs[ix - 1])) {
|
xdl_recmatch(recs[ixs - 1]->ptr, recs[ixs - 1]->size, recs[ix - 1]->ptr, recs[ix - 1]->size, flags)) {
|
||||||
rchg[--ixs] = 1;
|
rchg[--ixs] = 1;
|
||||||
rchg[--ix] = 0;
|
rchg[--ix] = 0;
|
||||||
|
|
||||||
@ -468,7 +468,7 @@ static int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo) {
|
|||||||
* the group.
|
* the group.
|
||||||
*/
|
*/
|
||||||
while (ix < nrec && recs[ixs]->ha == recs[ix]->ha &&
|
while (ix < nrec && recs[ixs]->ha == recs[ix]->ha &&
|
||||||
XDL_RECMATCH(recs[ixs], recs[ix])) {
|
xdl_recmatch(recs[ixs]->ptr, recs[ixs]->size, recs[ix]->ptr, recs[ix]->size, flags)) {
|
||||||
rchg[ixs++] = 0;
|
rchg[ixs++] = 0;
|
||||||
rchg[ix++] = 1;
|
rchg[ix++] = 1;
|
||||||
|
|
||||||
@ -546,8 +546,8 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
|||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (xdl_change_compact(&xe.xdf1, &xe.xdf2) < 0 ||
|
if (xdl_change_compact(&xe.xdf1, &xe.xdf2, xpp->flags) < 0 ||
|
||||||
xdl_change_compact(&xe.xdf2, &xe.xdf1) < 0 ||
|
xdl_change_compact(&xe.xdf2, &xe.xdf1, xpp->flags) < 0 ||
|
||||||
xdl_build_script(&xe, &xscr) < 0) {
|
xdl_build_script(&xe, &xscr) < 0) {
|
||||||
|
|
||||||
xdl_free_env(&xe);
|
xdl_free_env(&xe);
|
||||||
|
@ -55,6 +55,5 @@ void xdl_free_script(xdchange_t *xscr);
|
|||||||
int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
|
int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
|
||||||
xdemitconf_t const *xecfg);
|
xdemitconf_t const *xecfg);
|
||||||
|
|
||||||
|
|
||||||
#endif /* #if !defined(XDIFFI_H) */
|
#endif /* #if !defined(XDIFFI_H) */
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#define XDL_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
|
#define XDL_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
|
||||||
#define XDL_HASHLONG(v, b) (((unsigned long)(v) * GR_PRIME) >> ((CHAR_BIT * sizeof(unsigned long)) - (b)))
|
#define XDL_HASHLONG(v, b) (((unsigned long)(v) * GR_PRIME) >> ((CHAR_BIT * sizeof(unsigned long)) - (b)))
|
||||||
#define XDL_PTRFREE(p) do { if (p) { xdl_free(p); (p) = NULL; } } while (0)
|
#define XDL_PTRFREE(p) do { if (p) { xdl_free(p); (p) = NULL; } } while (0)
|
||||||
#define XDL_RECMATCH(r1, r2) ((r1)->size == (r2)->size && memcmp((r1)->ptr, (r2)->ptr, (r1)->size) == 0)
|
|
||||||
#define XDL_LE32_PUT(p, v) \
|
#define XDL_LE32_PUT(p, v) \
|
||||||
do { \
|
do { \
|
||||||
unsigned char *__p = (unsigned char *) (p); \
|
unsigned char *__p = (unsigned char *) (p); \
|
||||||
|
@ -43,12 +43,13 @@ typedef struct s_xdlclassifier {
|
|||||||
xdlclass_t **rchash;
|
xdlclass_t **rchash;
|
||||||
chastore_t ncha;
|
chastore_t ncha;
|
||||||
long count;
|
long count;
|
||||||
|
long flags;
|
||||||
} xdlclassifier_t;
|
} xdlclassifier_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int xdl_init_classifier(xdlclassifier_t *cf, long size);
|
static int xdl_init_classifier(xdlclassifier_t *cf, long size, long flags);
|
||||||
static void xdl_free_classifier(xdlclassifier_t *cf);
|
static void xdl_free_classifier(xdlclassifier_t *cf);
|
||||||
static int xdl_classify_record(xdlclassifier_t *cf, xrecord_t **rhash, unsigned int hbits,
|
static int xdl_classify_record(xdlclassifier_t *cf, xrecord_t **rhash, unsigned int hbits,
|
||||||
xrecord_t *rec);
|
xrecord_t *rec);
|
||||||
@ -63,9 +64,11 @@ static int xdl_optimize_ctxs(xdfile_t *xdf1, xdfile_t *xdf2);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int xdl_init_classifier(xdlclassifier_t *cf, long size) {
|
static int xdl_init_classifier(xdlclassifier_t *cf, long size, long flags) {
|
||||||
long i;
|
long i;
|
||||||
|
|
||||||
|
cf->flags = flags;
|
||||||
|
|
||||||
cf->hbits = xdl_hashbits((unsigned int) size);
|
cf->hbits = xdl_hashbits((unsigned int) size);
|
||||||
cf->hsize = 1 << cf->hbits;
|
cf->hsize = 1 << cf->hbits;
|
||||||
|
|
||||||
@ -103,8 +106,9 @@ static int xdl_classify_record(xdlclassifier_t *cf, xrecord_t **rhash, unsigned
|
|||||||
line = rec->ptr;
|
line = rec->ptr;
|
||||||
hi = (long) XDL_HASHLONG(rec->ha, cf->hbits);
|
hi = (long) XDL_HASHLONG(rec->ha, cf->hbits);
|
||||||
for (rcrec = cf->rchash[hi]; rcrec; rcrec = rcrec->next)
|
for (rcrec = cf->rchash[hi]; rcrec; rcrec = rcrec->next)
|
||||||
if (rcrec->ha == rec->ha && rcrec->size == rec->size &&
|
if (rcrec->ha == rec->ha &&
|
||||||
!memcmp(line, rcrec->line, rec->size))
|
xdl_recmatch(rcrec->line, rcrec->size,
|
||||||
|
rec->ptr, rec->size, cf->flags))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!rcrec) {
|
if (!rcrec) {
|
||||||
@ -173,7 +177,7 @@ static int xdl_prepare_ctx(mmfile_t *mf, long narec, xpparam_t const *xpp,
|
|||||||
top = blk + bsize;
|
top = blk + bsize;
|
||||||
}
|
}
|
||||||
prev = cur;
|
prev = cur;
|
||||||
hav = xdl_hash_record(&cur, top);
|
hav = xdl_hash_record(&cur, top, xpp->flags);
|
||||||
if (nrec >= narec) {
|
if (nrec >= narec) {
|
||||||
narec *= 2;
|
narec *= 2;
|
||||||
if (!(rrecs = (xrecord_t **) xdl_realloc(recs, narec * sizeof(xrecord_t *)))) {
|
if (!(rrecs = (xrecord_t **) xdl_realloc(recs, narec * sizeof(xrecord_t *)))) {
|
||||||
@ -268,7 +272,7 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
|
|||||||
enl1 = xdl_guess_lines(mf1) + 1;
|
enl1 = xdl_guess_lines(mf1) + 1;
|
||||||
enl2 = xdl_guess_lines(mf2) + 1;
|
enl2 = xdl_guess_lines(mf2) + 1;
|
||||||
|
|
||||||
if (xdl_init_classifier(&cf, enl1 + enl2 + 1) < 0) {
|
if (xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0) {
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -186,12 +186,61 @@ long xdl_guess_lines(mmfile_t *mf) {
|
|||||||
return nl + 1;
|
return nl + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
|
||||||
|
{
|
||||||
|
int i1, i2;
|
||||||
|
|
||||||
unsigned long xdl_hash_record(char const **data, char const *top) {
|
if (flags & XDF_IGNORE_WHITESPACE) {
|
||||||
|
for (i1 = i2 = 0; i1 < s1 && i2 < s2; i1++, i2++) {
|
||||||
|
if (isspace(l1[i1]))
|
||||||
|
while (isspace(l1[i1]) && i1 < s1)
|
||||||
|
i1++;
|
||||||
|
else if (isspace(l2[i2]))
|
||||||
|
while (isspace(l2[i2]) && i2 < s2)
|
||||||
|
i2++;
|
||||||
|
else if (l1[i1] != l2[i2])
|
||||||
|
return l2[i2] - l1[i1];
|
||||||
|
}
|
||||||
|
if (i1 >= s1)
|
||||||
|
return 1;
|
||||||
|
else if (i2 >= s2)
|
||||||
|
return -1;
|
||||||
|
} else if (flags & XDF_IGNORE_WHITESPACE_CHANGE) {
|
||||||
|
for (i1 = i2 = 0; i1 < s1 && i2 < s2; i1++, i2++) {
|
||||||
|
if (isspace(l1[i1])) {
|
||||||
|
if (!isspace(l2[i2]))
|
||||||
|
return -1;
|
||||||
|
while (isspace(l1[i1]) && i1 < s1)
|
||||||
|
i1++;
|
||||||
|
while (isspace(l2[i2]) && i2 < s2)
|
||||||
|
i2++;
|
||||||
|
} else if (l1[i1] != l2[i2])
|
||||||
|
return l2[i2] - l1[i1];
|
||||||
|
}
|
||||||
|
if (i1 >= s1)
|
||||||
|
return 1;
|
||||||
|
else if (i2 >= s2)
|
||||||
|
return -1;
|
||||||
|
} else
|
||||||
|
return s1 == s2 && !memcmp(l1, l2, s1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long xdl_hash_record(char const **data, char const *top, long flags) {
|
||||||
unsigned long ha = 5381;
|
unsigned long ha = 5381;
|
||||||
char const *ptr = *data;
|
char const *ptr = *data;
|
||||||
|
|
||||||
for (; ptr < top && *ptr != '\n'; ptr++) {
|
for (; ptr < top && *ptr != '\n'; ptr++) {
|
||||||
|
if (isspace(*ptr) && (flags & XDF_WHITESPACE_FLAGS)) {
|
||||||
|
while (ptr < top && isspace(*ptr) && ptr[1] != '\n')
|
||||||
|
ptr++;
|
||||||
|
if (flags & XDF_IGNORE_WHITESPACE_CHANGE) {
|
||||||
|
ha += (ha << 5);
|
||||||
|
ha ^= (unsigned long) ' ';
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
ha += (ha << 5);
|
ha += (ha << 5);
|
||||||
ha ^= (unsigned long) *ptr;
|
ha ^= (unsigned long) *ptr;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,8 @@ void *xdl_cha_alloc(chastore_t *cha);
|
|||||||
void *xdl_cha_first(chastore_t *cha);
|
void *xdl_cha_first(chastore_t *cha);
|
||||||
void *xdl_cha_next(chastore_t *cha);
|
void *xdl_cha_next(chastore_t *cha);
|
||||||
long xdl_guess_lines(mmfile_t *mf);
|
long xdl_guess_lines(mmfile_t *mf);
|
||||||
unsigned long xdl_hash_record(char const **data, char const *top);
|
int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags);
|
||||||
|
unsigned long xdl_hash_record(char const **data, char const *top, long flags);
|
||||||
unsigned int xdl_hashbits(unsigned int size);
|
unsigned int xdl_hashbits(unsigned int size);
|
||||||
int xdl_num_out(char *out, long val);
|
int xdl_num_out(char *out, long val);
|
||||||
long xdl_atol(char const *str, char const **next);
|
long xdl_atol(char const *str, char const **next);
|
||||||
|
Loading…
Reference in New Issue
Block a user