X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=diffcore-pickaxe.c;h=cfcce315babb0edb7ad7be7f2ab2437aaf41eb9d;hb=7612a1efdb0c0806b43db10ce784707aae874340;hp=ef9c5c1d217ff2efc1ba9e43052601e2fc18ac22;hpb=f0c6b2a2fd98b51f1f2655ea69ace9763da28e79;p=git.git diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c index ef9c5c1d..cfcce315 100644 --- a/diffcore-pickaxe.c +++ b/diffcore-pickaxe.c @@ -4,21 +4,47 @@ #include "cache.h" #include "diff.h" #include "diffcore.h" -#include "delta.h" -static int contains(struct diff_filespec *one, - const char *needle, unsigned long len) +#include + +static unsigned int contains(struct diff_filespec *one, + const char *needle, unsigned long len, + regex_t *regexp) { + unsigned int cnt; unsigned long offset, sz; const char *data; if (diff_populate_filespec(one, 0)) return 0; + sz = one->size; data = one->data; - for (offset = 0; offset + len <= sz; offset++) - if (!strncmp(needle, data + offset, len)) - return 1; - return 0; + cnt = 0; + + if (regexp) { + regmatch_t regmatch; + int flags = 0; + + while (*data && !regexec(regexp, data, 1, ®match, flags)) { + flags |= REG_NOTBOL; + data += regmatch.rm_so; + if (*data) data++; + cnt++; + } + + } else { /* Classic exact string match */ + /* Yes, I've heard of strstr(), but the thing is *data may + * not be NUL terminated. Sue me. + */ + for (offset = 0; offset + len <= sz; offset++) { + /* we count non-overlapping occurrences of needle */ + if (!memcmp(needle, data + offset, len)) { + offset += len - 1; + cnt++; + } + } + } + return cnt; } void diffcore_pickaxe(const char *needle, int opts) @@ -26,10 +52,24 @@ void diffcore_pickaxe(const char *needle, int 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; outq.queue = NULL; outq.nr = outq.alloc = 0; + if (opts & DIFF_PICKAXE_REGEX) { + int err; + err = regcomp(®ex, needle, REG_EXTENDED | REG_NEWLINE); + if (err) { + /* The POSIX.2 people are surely sick */ + char errbuf[1024]; + regerror(err, ®ex, errbuf, 1024); + regfree(®ex); + die("invalid pickaxe regex: %s", errbuf); + } + regexp = ®ex; + } + if (opts & DIFF_PICKAXE_ALL) { /* Showing the whole changeset if needle exists */ for (i = has_changes = 0; !has_changes && i < q->nr; i++) { @@ -38,16 +78,16 @@ void diffcore_pickaxe(const char *needle, int opts) if (!DIFF_FILE_VALID(p->two)) continue; /* ignore unmerged */ /* created */ - if (contains(p->two, needle, len)) + if (contains(p->two, needle, len, regexp)) has_changes++; } else if (!DIFF_FILE_VALID(p->two)) { - if (contains(p->one, needle, len)) + if (contains(p->one, needle, len, regexp)) has_changes++; } else if (!diff_unmodified_pair(p) && - contains(p->one, needle, len) != - contains(p->two, needle, len)) + contains(p->one, needle, len, regexp) != + contains(p->two, needle, len, regexp)) has_changes++; } if (has_changes) @@ -70,16 +110,16 @@ void diffcore_pickaxe(const char *needle, int opts) if (!DIFF_FILE_VALID(p->two)) ; /* ignore unmerged */ /* created */ - else if (contains(p->two, needle, len)) + else if (contains(p->two, needle, len, regexp)) has_changes = 1; } else if (!DIFF_FILE_VALID(p->two)) { - if (contains(p->one, needle, len)) + if (contains(p->one, needle, len, regexp)) has_changes = 1; } else if (!diff_unmodified_pair(p) && - contains(p->one, needle, len) != - contains(p->two, needle, len)) + contains(p->one, needle, len, regexp) != + contains(p->two, needle, len, regexp)) has_changes = 1; if (has_changes) @@ -88,6 +128,10 @@ void diffcore_pickaxe(const char *needle, int opts) diff_free_filepair(p); } + if (opts & DIFF_PICKAXE_REGEX) { + regfree(®ex); + } + free(q->queue); *q = outq; return;