Skip to content

Commit

Permalink
diffcore-pickaxe: unify code for log -S/-G
Browse files Browse the repository at this point in the history
The logic flow of has_changes() used for "log -S" and diff_grep()
used for "log -G" are essentially the same.  See if we have both
sides that could be different in any interesting way, slurp the
contents in core, possibly after applying textconv, inspect the
contents, clean-up and report the result.  The only difference
between the two is how "inspect" step works.

Unify this codeflow in a helper, pickaxe_match(), which takes a
callback function that implements the specific "inspect" step.

After removing the common scaffolding code from the existing
has_changes() and diff_grep(), they each becomes such a callback
function suitable for passing to pickaxe_match().

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Jeff King authored and Junio C Hamano committed Apr 5, 2013
1 parent 88ff684 commit 61690bf
Showing 1 changed file with 49 additions and 69 deletions.
118 changes: 49 additions & 69 deletions diffcore-pickaxe.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
#include "xdiff-interface.h"
#include "kwset.h"

typedef int (*pickaxe_fn)(struct diff_filepair *p, struct diff_options *o, regex_t *regexp, kwset_t kws);
typedef int (*pickaxe_fn)(mmfile_t *one, mmfile_t *two,
struct diff_options *o,
regex_t *regexp, kwset_t kws);

static int pickaxe_match(struct diff_filepair *p, struct diff_options *o,
regex_t *regexp, kwset_t kws, pickaxe_fn fn);

static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
regex_t *regexp, kwset_t kws, pickaxe_fn fn)
Expand All @@ -22,7 +27,7 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
/* Showing the whole changeset if needle exists */
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
if (fn(p, o, regexp, kws))
if (pickaxe_match(p, o, regexp, kws, fn))
return; /* do not munge the queue */
}

Expand All @@ -37,7 +42,7 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
/* Showing only the filepairs that has the needle */
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
if (fn(p, o, regexp, kws))
if (pickaxe_match(p, o, regexp, kws, fn))
diff_q(&outq, p);
else
diff_free_filepair(p);
Expand Down Expand Up @@ -74,64 +79,33 @@ static void diffgrep_consume(void *priv, char *line, unsigned long len)
line[len] = hold;
}

static int diff_grep(struct diff_filepair *p, struct diff_options *o,
static int diff_grep(mmfile_t *one, mmfile_t *two,
struct diff_options *o,
regex_t *regexp, kwset_t kws)
{
regmatch_t regmatch;
struct userdiff_driver *textconv_one = NULL;
struct userdiff_driver *textconv_two = NULL;
mmfile_t mf1, mf2;
int hit;
struct diffgrep_cb ecbdata;
xpparam_t xpp;
xdemitconf_t xecfg;

if (!o->pickaxe[0])
return 0;
if (!one)
return !regexec(regexp, two->ptr, 1, &regmatch, 0);
if (!two)
return !regexec(regexp, one->ptr, 1, &regmatch, 0);

if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
textconv_one = get_textconv(p->one);
textconv_two = get_textconv(p->two);
}

if (textconv_one == textconv_two && diff_unmodified_pair(p))
return 0;

mf1.size = fill_textconv(textconv_one, p->one, &mf1.ptr);
mf2.size = fill_textconv(textconv_two, p->two, &mf2.ptr);

if (!DIFF_FILE_VALID(p->one)) {
if (!DIFF_FILE_VALID(p->two))
hit = 0; /* ignore unmerged */
else
/* created "two" -- does it have what we are looking for? */
hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);
} else if (!DIFF_FILE_VALID(p->two)) {
/* removed "one" -- did it have what we are looking for? */
hit = !regexec(regexp, mf1.ptr, 1, &regmatch, 0);
} else {
/*
* We have both sides; need to run textual diff and see if
* the pattern appears on added/deleted lines.
*/
struct diffgrep_cb ecbdata;
xpparam_t xpp;
xdemitconf_t xecfg;

memset(&xpp, 0, sizeof(xpp));
memset(&xecfg, 0, sizeof(xecfg));
ecbdata.regexp = regexp;
ecbdata.hit = 0;
xecfg.ctxlen = o->context;
xecfg.interhunkctxlen = o->interhunkcontext;
xdi_diff_outf(&mf1, &mf2, diffgrep_consume, &ecbdata,
&xpp, &xecfg);
hit = ecbdata.hit;
}
if (textconv_one)
free(mf1.ptr);
if (textconv_two)
free(mf2.ptr);
diff_free_filespec_data(p->one);
diff_free_filespec_data(p->two);
return hit;
/*
* We have both sides; need to run textual diff and see if
* the pattern appears on added/deleted lines.
*/
memset(&xpp, 0, sizeof(xpp));
memset(&xecfg, 0, sizeof(xecfg));
ecbdata.regexp = regexp;
ecbdata.hit = 0;
xecfg.ctxlen = o->context;
xecfg.interhunkctxlen = o->interhunkcontext;
xdi_diff_outf(one, two, diffgrep_consume, &ecbdata,
&xpp, &xecfg);
return ecbdata.hit;
}

static void diffcore_pickaxe_grep(struct diff_options *o)
Expand Down Expand Up @@ -198,8 +172,19 @@ static unsigned int contains(mmfile_t *mf, struct diff_options *o,
return cnt;
}

static int has_changes(struct diff_filepair *p, struct diff_options *o,
static int has_changes(mmfile_t *one, mmfile_t *two,
struct diff_options *o,
regex_t *regexp, kwset_t kws)
{
if (!one)
return contains(two, o, regexp, kws) != 0;
if (!two)
return contains(one, o, regexp, kws) != 0;
return contains(one, o, regexp, kws) != contains(two, o, regexp, kws);
}

static int pickaxe_match(struct diff_filepair *p, struct diff_options *o,
regex_t *regexp, kwset_t kws, pickaxe_fn fn)
{
struct userdiff_driver *textconv_one = NULL;
struct userdiff_driver *textconv_two = NULL;
Expand All @@ -209,6 +194,10 @@ static int has_changes(struct diff_filepair *p, struct diff_options *o,
if (!o->pickaxe[0])
return 0;

/* ignore unmerged */
if (!DIFF_FILE_VALID(p->one) && !DIFF_FILE_VALID(p->two))
return 0;

if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
textconv_one = get_textconv(p->one);
textconv_two = get_textconv(p->two);
Expand All @@ -227,18 +216,9 @@ static int has_changes(struct diff_filepair *p, struct diff_options *o,
mf1.size = fill_textconv(textconv_one, p->one, &mf1.ptr);
mf2.size = fill_textconv(textconv_two, p->two, &mf2.ptr);

if (!DIFF_FILE_VALID(p->one)) {
if (!DIFF_FILE_VALID(p->two))
ret = 0; /* ignore unmerged */
else
/* created */
ret = contains(&mf2, o, regexp, kws) != 0;
}
else if (!DIFF_FILE_VALID(p->two)) /* removed */
ret = contains(&mf1, o, regexp, kws) != 0;
else
ret = contains(&mf1, o, regexp, kws) !=
contains(&mf2, o, regexp, kws);
ret = fn(DIFF_FILE_VALID(p->one) ? &mf1 : NULL,
DIFF_FILE_VALID(p->two) ? &mf2 : NULL,
o, regexp, kws);

if (textconv_one)
free(mf1.ptr);
Expand Down

0 comments on commit 61690bf

Please sign in to comment.