Merge branch 'rs/pickaxe'
* rs/pickaxe: pickaxe: factor out pickaxe pickaxe: give diff_grep the same signature as has_changes pickaxe: pass diff_options to contains and has_changes pickaxe: factor out has_changes pickaxe: plug regex/kws leak pickaxe: plug regex leak pickaxe: plug diff filespec leak with empty needle
This commit is contained in:
commit
662384c499
@ -8,6 +8,46 @@
|
||||
#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;
|
||||
int hit;
|
||||
@ -45,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;
|
||||
@ -95,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) {
|
||||
@ -110,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,
|
||||
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;
|
||||
@ -176,14 +183,15 @@ static unsigned int contains(struct diff_filespec *one,
|
||||
|
||||
} else { /* Classic exact string match */
|
||||
while (sz) {
|
||||
size_t offset = kwsexec(kws, data, sz, NULL);
|
||||
struct kwsmatch kwsm;
|
||||
size_t offset = kwsexec(kws, data, sz, &kwsm);
|
||||
const char *found;
|
||||
if (offset == -1)
|
||||
break;
|
||||
else
|
||||
found = data + offset;
|
||||
sz -= found - data + len;
|
||||
data = found + len;
|
||||
sz -= found - data + kwsm.size[0];
|
||||
data = found + kwsm.size[0];
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
@ -191,17 +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;
|
||||
kwset_t kws = NULL;
|
||||
struct diff_queue_struct outq;
|
||||
DIFF_QUEUE_CLEAR(&outq);
|
||||
|
||||
if (opts & DIFF_PICKAXE_REGEX) {
|
||||
int err;
|
||||
@ -220,72 +242,12 @@ static void diffcore_pickaxe_count(struct diff_options *o)
|
||||
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, kws))
|
||||
has_changes++;
|
||||
}
|
||||
else if (!DIFF_FILE_VALID(p->two)) {
|
||||
if (contains(p->one, needle, len, regexp, kws))
|
||||
has_changes++;
|
||||
}
|
||||
else if (!diff_unmodified_pair(p) &&
|
||||
contains(p->one, needle, len, regexp, kws) !=
|
||||
contains(p->two, needle, len, regexp, kws))
|
||||
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,
|
||||
kws))
|
||||
has_changes = 1;
|
||||
}
|
||||
else if (!DIFF_FILE_VALID(p->two)) {
|
||||
if (contains(p->one, needle, len, regexp, kws))
|
||||
has_changes = 1;
|
||||
}
|
||||
else if (!diff_unmodified_pair(p) &&
|
||||
contains(p->one, needle, len, regexp, kws) !=
|
||||
contains(p->two, needle, len, regexp, kws))
|
||||
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);
|
||||
else
|
||||
kwsfree(kws);
|
||||
|
||||
free(q->queue);
|
||||
*q = outq;
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user