X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=diffcore-pickaxe.c;h=380a837b5b136ae88d374ae8a7326c87597107fc;hb=50c94032844bb184cdeff7779be3b6a23e04d312;hp=ea03b9107eb2e85dd4a4c5ad93ac08dfe7e1c9f0;hpb=6d1cdadbeeb03f40250526e29b1f1a91582911d8;p=git.git diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c index ea03b9107..380a837b5 100644 --- a/diffcore-pickaxe.c +++ b/diffcore-pickaxe.c @@ -6,6 +6,47 @@ #include "diff.h" #include "diffcore.h" #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); + +static void pickaxe(struct diff_queue_struct *q, struct diff_options *o, + regex_t *regexp, kwset_t kws, pickaxe_fn fn) +{ + int i; + struct diff_queue_struct outq; + + DIFF_QUEUE_CLEAR(&outq); + + if (o->pickaxe_opts & DIFF_PICKAXE_ALL) { + /* 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)) + return; /* do not munge the queue */ + } + + /* + * Otherwise we will clear the whole queue by copying + * the empty outq at the end of this function, but + * first clear the current entries in the queue. + */ + for (i = 0; i < q->nr; i++) + diff_free_filepair(q->queue[i]); + } else { + /* 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)) + diff_q(&outq, p); + else + diff_free_filepair(p); + } + } + + free(q->queue); + *q = outq; +} struct diffgrep_cb { regex_t *regexp; @@ -44,7 +85,8 @@ static void fill_one(struct diff_filespec *one, } } -static int diff_grep(struct diff_filepair *p, regex_t *regexp, struct diff_options *o) +static int diff_grep(struct diff_filepair *p, struct diff_options *o, + regex_t *regexp, kwset_t kws) { regmatch_t regmatch; struct userdiff_driver *textconv_one = NULL; @@ -94,12 +136,8 @@ static int diff_grep(struct diff_filepair *p, regex_t *regexp, struct diff_optio static void diffcore_pickaxe_grep(struct diff_options *o) { - struct diff_queue_struct *q = &diff_queued_diff; - int i, has_changes, err; + int err; regex_t regex; - struct diff_queue_struct outq; - outq.queue = NULL; - outq.nr = outq.alloc = 0; err = regcomp(®ex, o->pickaxe, REG_EXTENDED | REG_NEWLINE); if (err) { @@ -109,51 +147,21 @@ static void diffcore_pickaxe_grep(struct diff_options *o) die("invalid log-grep regex: %s", errbuf); } - if (o->pickaxe_opts & DIFF_PICKAXE_ALL) { - /* Showing the whole changeset if needle exists */ - for (i = has_changes = 0; !has_changes && i < q->nr; i++) { - struct diff_filepair *p = q->queue[i]; - if (diff_grep(p, ®ex, o)) - has_changes++; - } - if (has_changes) - return; /* do not munge the queue */ - - /* - * Otherwise we will clear the whole queue by copying - * the empty outq at the end of this function, but - * first clear the current entries in the queue. - */ - for (i = 0; i < q->nr; i++) - diff_free_filepair(q->queue[i]); - } else { - /* Showing only the filepairs that has the needle */ - for (i = 0; i < q->nr; i++) { - struct diff_filepair *p = q->queue[i]; - if (diff_grep(p, ®ex, o)) - diff_q(&outq, p); - else - diff_free_filepair(p); - } - } + pickaxe(&diff_queued_diff, o, ®ex, NULL, diff_grep); regfree(®ex); - - free(q->queue); - *q = outq; return; } -static unsigned int contains(struct diff_filespec *one, - const char *needle, unsigned long len, - regex_t *regexp) +static unsigned int contains(struct diff_filespec *one, struct diff_options *o, + regex_t *regexp, kwset_t kws) { unsigned int cnt; unsigned long sz; const char *data; - if (diff_populate_filespec(one, 0)) + if (!o->pickaxe[0]) return 0; - if (!len) + if (diff_populate_filespec(one, 0)) return 0; sz = one->size; @@ -175,11 +183,15 @@ static unsigned int contains(struct diff_filespec *one, } else { /* Classic exact string match */ while (sz) { - const char *found = memmem(data, sz, needle, len); - if (!found) + struct kwsmatch kwsm; + size_t offset = kwsexec(kws, data, sz, &kwsm); + const char *found; + if (offset == -1) break; - sz -= found - data + len; - data = found + len; + else + found = data + offset; + sz -= found - data + kwsm.size[0]; + data = found + kwsm.size[0]; cnt++; } } @@ -187,16 +199,31 @@ static unsigned int contains(struct diff_filespec *one, return cnt; } +static int has_changes(struct diff_filepair *p, struct diff_options *o, + regex_t *regexp, kwset_t kws) +{ + if (!DIFF_FILE_VALID(p->one)) { + if (!DIFF_FILE_VALID(p->two)) + return 0; /* ignore unmerged */ + /* created */ + return contains(p->two, o, regexp, kws) != 0; + } + if (!DIFF_FILE_VALID(p->two)) + return contains(p->one, o, regexp, kws) != 0; + if (!diff_unmodified_pair(p)) { + return contains(p->one, o, regexp, kws) != + contains(p->two, o, regexp, kws); + } + return 0; +} + static void diffcore_pickaxe_count(struct diff_options *o) { const char *needle = o->pickaxe; int opts = o->pickaxe_opts; - struct diff_queue_struct *q = &diff_queued_diff; unsigned long len = strlen(needle); - int i, has_changes; regex_t regex, *regexp = NULL; - struct diff_queue_struct outq; - DIFF_QUEUE_CLEAR(&outq); + kwset_t kws = NULL; if (opts & DIFF_PICKAXE_REGEX) { int err; @@ -209,71 +236,18 @@ static void diffcore_pickaxe_count(struct diff_options *o) die("invalid pickaxe regex: %s", errbuf); } regexp = ®ex; + } else { + kws = kwsalloc(NULL); + kwsincr(kws, needle, len); + kwsprep(kws); } - if (opts & DIFF_PICKAXE_ALL) { - /* Showing the whole changeset if needle exists */ - for (i = has_changes = 0; !has_changes && i < q->nr; i++) { - struct diff_filepair *p = q->queue[i]; - if (!DIFF_FILE_VALID(p->one)) { - if (!DIFF_FILE_VALID(p->two)) - continue; /* ignore unmerged */ - /* created */ - if (contains(p->two, needle, len, regexp)) - has_changes++; - } - else if (!DIFF_FILE_VALID(p->two)) { - if (contains(p->one, needle, len, regexp)) - has_changes++; - } - else if (!diff_unmodified_pair(p) && - contains(p->one, needle, len, regexp) != - contains(p->two, needle, len, regexp)) - has_changes++; - } - if (has_changes) - return; /* not munge the queue */ - - /* otherwise we will clear the whole queue - * by copying the empty outq at the end of this - * function, but first clear the current entries - * in the queue. - */ - for (i = 0; i < q->nr; i++) - diff_free_filepair(q->queue[i]); - } - else - /* Showing only the filepairs that has the needle */ - for (i = 0; i < q->nr; i++) { - struct diff_filepair *p = q->queue[i]; - has_changes = 0; - if (!DIFF_FILE_VALID(p->one)) { - if (!DIFF_FILE_VALID(p->two)) - ; /* ignore unmerged */ - /* created */ - else if (contains(p->two, needle, len, regexp)) - has_changes = 1; - } - else if (!DIFF_FILE_VALID(p->two)) { - if (contains(p->one, needle, len, regexp)) - has_changes = 1; - } - else if (!diff_unmodified_pair(p) && - contains(p->one, needle, len, regexp) != - contains(p->two, needle, len, regexp)) - has_changes = 1; - - if (has_changes) - diff_q(&outq, p); - else - diff_free_filepair(p); - } + pickaxe(&diff_queued_diff, o, regexp, kws, has_changes); if (opts & DIFF_PICKAXE_REGEX) regfree(®ex); - - free(q->queue); - *q = outq; + else + kwsfree(kws); return; }