static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent) { struct diff_queue_struct *q = &diff_queued_diff; struct combine_diff_path *p; int i; if (!n) { struct combine_diff_path *list = NULL, **tail = &list; for (i = 0; i < q->nr; i++) { int len; const char *path; if (diff_unmodified_pair(q->queue[i])) continue; path = q->queue[i]->two->path; len = strlen(path); p = xmalloc(combine_diff_path_size(num_parent, len)); p->path = (char*) &(p->parent[num_parent]); memcpy(p->path, path, len); p->path[len] = 0; p->len = len; p->next = NULL; memset(p->parent, 0, sizeof(p->parent[0]) * num_parent); hashcpy(p->sha1, q->queue[i]->two->sha1); p->mode = q->queue[i]->two->mode; hashcpy(p->parent[n].sha1, q->queue[i]->one->sha1); p->parent[n].mode = q->queue[i]->one->mode; p->parent[n].status = q->queue[i]->status; *tail = p; tail = &p->next; } return list; } for (p = curr; p; p = p->next) { int found = 0; if (!p->len) continue; for (i = 0; i < q->nr; i++) { const char *path; int len; if (diff_unmodified_pair(q->queue[i])) continue; path = q->queue[i]->two->path; len = strlen(path); if (len == p->len && !memcmp(path, p->path, len)) { found = 1; hashcpy(p->parent[n].sha1, q->queue[i]->one->sha1); p->parent[n].mode = q->queue[i]->one->mode; p->parent[n].status = q->queue[i]->status; break; } } if (!found) p->len = 0; } return curr; }
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; mmfile_t mf1, mf2; int ret; /* ignore unmerged */ if (!DIFF_FILE_VALID(p->one) && !DIFF_FILE_VALID(p->two)) return 0; if (o->objfind) { return (DIFF_FILE_VALID(p->one) && oidset_contains(o->objfind, &p->one->oid)) || (DIFF_FILE_VALID(p->two) && oidset_contains(o->objfind, &p->two->oid)); } if (!o->pickaxe[0]) return 0; if (o->flags.allow_textconv) { textconv_one = get_textconv(o->repo->index, p->one); textconv_two = get_textconv(o->repo->index, p->two); } /* * If we have an unmodified pair, we know that the count will be the * same and don't even have to load the blobs. Unless textconv is in * play, _and_ we are using two different textconv filters (e.g., * because a pair is an exact rename with different textconv attributes * for each side, which might generate different content). */ if (textconv_one == textconv_two && diff_unmodified_pair(p)) return 0; mf1.size = fill_textconv(o->repo, textconv_one, p->one, &mf1.ptr); mf2.size = fill_textconv(o->repo, textconv_two, p->two, &mf2.ptr); 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); if (textconv_two) free(mf2.ptr); diff_free_filespec_data(p->one); diff_free_filespec_data(p->two); return ret; }
static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent) { struct diff_queue_struct *q = &diff_queued_diff; struct combine_diff_path *p, **tail = &curr; int i, cmp; if (!n) { for (i = 0; i < q->nr; i++) { int len; const char *path; if (diff_unmodified_pair(q->queue[i])) continue; path = q->queue[i]->two->path; len = strlen(path); p = xmalloc(combine_diff_path_size(num_parent, len)); p->path = (char *) &(p->parent[num_parent]); memcpy(p->path, path, len); p->path[len] = 0; p->next = NULL; memset(p->parent, 0, sizeof(p->parent[0]) * num_parent); hashcpy(p->sha1, q->queue[i]->two->sha1); p->mode = q->queue[i]->two->mode; hashcpy(p->parent[n].sha1, q->queue[i]->one->sha1); p->parent[n].mode = q->queue[i]->one->mode; p->parent[n].status = q->queue[i]->status; *tail = p; tail = &p->next; } return curr; } /* * paths in curr (linked list) and q->queue[] (array) are * both sorted in the tree order. */ i = 0; while ((p = *tail) != NULL) { cmp = ((i >= q->nr) ? -1 : strcmp(p->path, q->queue[i]->two->path)); if (cmp < 0) { /* p->path not in q->queue[]; drop it */ *tail = p->next; free(p); continue; } if (cmp > 0) { /* q->queue[i] not in p->path; skip it */ i++; continue; } hashcpy(p->parent[n].sha1, q->queue[i]->one->sha1); p->parent[n].mode = q->queue[i]->one->mode; p->parent[n].status = q->queue[i]->status; tail = &p->next; i++; } return curr; }
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++) { 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); } if (opts & DIFF_PICKAXE_REGEX) { regfree(®ex); } free(q->queue); *q = outq; return; }