static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec, struct object *obj, const char *name) { if (obj->type == OBJ_BLOB) return grep_sha1(opt, obj->sha1, name, 0, NULL); if (obj->type == OBJ_COMMIT || obj->type == OBJ_TREE) { struct tree_desc tree; void *data; unsigned long size; struct strbuf base; int hit, len; grep_read_lock(); data = read_object_with_reference(obj->sha1, tree_type, &size, NULL); grep_read_unlock(); if (!data) die(_("unable to read tree (%s)"), sha1_to_hex(obj->sha1)); len = name ? strlen(name) : 0; strbuf_init(&base, PATH_MAX + len + 1); if (len) { strbuf_add(&base, name, len); strbuf_addch(&base, ':'); } init_tree_desc(&tree, data, size); hit = grep_tree(opt, pathspec, &tree, &base, base.len, obj->type == OBJ_COMMIT); strbuf_release(&base); free(data); return hit; } die(_("unable to grep from object of type %s"), typename(obj->type)); }
static void *lock_and_read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size) { void *data; grep_read_lock(); data = read_sha1_file(sha1, type, size); grep_read_unlock(); return data; }
static void *lock_and_read_oid_file(const struct object_id *oid, enum object_type *type, unsigned long *size) { void *data; grep_read_lock(); data = read_sha1_file(oid->hash, type, size); grep_read_unlock(); return data; }
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; }
static int grep_source_load_sha1(struct grep_source *gs) { enum object_type type; grep_read_lock(); gs->buf = read_sha1_file(gs->identifier, &type, &gs->size); grep_read_unlock(); if (!gs->buf) return error(_("'%s': unable to read %s"), gs->name, sha1_to_hex(gs->identifier)); return 0; }
static int grep_submodule(struct grep_opt *opt, struct repository *superproject, const struct pathspec *pathspec, const struct object_id *oid, const char *filename, const char *path) { struct repository submodule; int hit; if (!is_submodule_active(superproject, path)) return 0; if (repo_submodule_init(&submodule, superproject, path)) return 0; repo_read_gitmodules(&submodule); /* * NEEDSWORK: This adds the submodule's object directory to the list of * alternates for the single in-memory object store. This has some bad * consequences for memory (processed objects will never be freed) and * performance (this increases the number of pack files git has to pay * attention to, to the sum of the number of pack files in all the * repositories processed so far). This can be removed once the object * store is no longer global and instead is a member of the repository * object. */ grep_read_lock(); add_to_alternates_memory(submodule.objectdir); grep_read_unlock(); if (oid) { struct object *object; struct tree_desc tree; void *data; unsigned long size; struct strbuf base = STRBUF_INIT; object = parse_object_or_die(oid, oid_to_hex(oid)); grep_read_lock(); data = read_object_with_reference(object->oid.hash, tree_type, &size, NULL); grep_read_unlock(); if (!data) die(_("unable to read tree (%s)"), oid_to_hex(&object->oid)); strbuf_addstr(&base, filename); strbuf_addch(&base, '/'); init_tree_desc(&tree, data, size); hit = grep_tree(opt, pathspec, &tree, &base, base.len, object->type == OBJ_COMMIT, &submodule); strbuf_release(&base); free(data); } else { hit = grep_cache(opt, &submodule, pathspec, 1); } repo_clear(&submodule); return hit; }