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 int fill_textconv_grep(struct userdiff_driver *driver, struct grep_source *gs) { struct diff_filespec *df; char *buf; size_t size; if (!driver || !driver->textconv) return grep_source_load(gs); /* * The textconv interface is intimately tied to diff_filespecs, so we * have to pretend to be one. If we could unify the grep_source * and diff_filespec structs, this mess could just go away. */ df = alloc_filespec(gs->path); switch (gs->type) { case GREP_SOURCE_SHA1: fill_filespec(df, gs->identifier, 1, 0100644); break; case GREP_SOURCE_FILE: fill_filespec(df, null_sha1, 0, 0100644); break; default: die("BUG: attempt to textconv something without a path?"); } /* * fill_textconv is not remotely thread-safe; it may load objects * behind the scenes, and it modifies the global diff tempfile * structure. */ grep_read_lock(); size = fill_textconv(driver, df, &buf); grep_read_unlock(); free_filespec(df); /* * The normal fill_textconv usage by the diff machinery would just keep * the textconv'd buf separate from the diff_filespec. But much of the * grep code passes around a grep_source and assumes that its "buf" * pointer is the beginning of the thing we are searching. So let's * install our textconv'd version into the grep_source, taking care not * to leak any existing buffer. */ grep_source_clear_data(gs); gs->buf = buf; gs->size = size; return 0; }