struct git_istream *open_istream(const unsigned char *sha1, enum object_type *type, unsigned long *size, struct stream_filter *filter) { struct git_istream *st; struct object_info oi = {0}; const unsigned char *real = lookup_replace_object(sha1); enum input_source src = istream_source(real, type, &oi); if (src < 0) return NULL; st = xmalloc(sizeof(*st)); if (open_istream_tbl[src](st, &oi, real, type)) { if (open_istream_incore(st, &oi, real, type)) { free(st); return NULL; } } if (filter) { /* Add "&& !is_null_stream_filter(filter)" for performance */ struct git_istream *nst = attach_stream_filter(st, filter); if (!nst) close_istream(st); st = nst; } *size = st->size; return st; }
/* * We refuse to tag something we can't verify. Just because. */ static int verify_object(const struct object_id *oid, const char *expected_type) { int ret = -1; enum object_type type; unsigned long size; void *buffer = read_object_file(oid, &type, &size); const struct object_id *repl = lookup_replace_object(the_repository, oid); if (buffer) { if (type == type_from_string(expected_type)) ret = check_object_signature(repl, buffer, size, expected_type); free(buffer); } return ret; }
struct object *parse_object(const struct object_id *oid) { unsigned long size; enum object_type type; int eaten; const struct object_id *repl = lookup_replace_object(the_repository, oid); void *buffer; struct object *obj; obj = lookup_object(oid->hash); if (obj && obj->parsed) return obj; if ((obj && obj->type == OBJ_BLOB && has_object_file(oid)) || (!obj && has_object_file(oid) && oid_object_info(the_repository, oid, NULL) == OBJ_BLOB)) { if (check_object_signature(repl, NULL, 0, NULL) < 0) { error("sha1 mismatch %s", oid_to_hex(oid)); return NULL; } parse_blob_buffer(lookup_blob(oid), NULL, 0); return lookup_object(oid->hash); } buffer = read_object_file(oid, &type, &size); if (buffer) { if (check_object_signature(repl, buffer, size, type_name(type)) < 0) { free(buffer); error("sha1 mismatch %s", oid_to_hex(repl)); return NULL; } obj = parse_object_buffer(oid, type, size, buffer, &eaten); if (!eaten) free(buffer); return obj; } return NULL; }
static void verify_one(struct repository *r, struct index_state *istate, struct cache_tree *it, struct strbuf *path) { int i, pos, len = path->len; struct strbuf tree_buf = STRBUF_INIT; struct object_id new_oid; for (i = 0; i < it->subtree_nr; i++) { strbuf_addf(path, "%s/", it->down[i]->name); verify_one(r, istate, it->down[i]->cache_tree, path); strbuf_setlen(path, len); } if (it->entry_count < 0 || /* no verification on tests (t7003) that replace trees */ lookup_replace_object(r, &it->oid) != &it->oid) return; if (path->len) { pos = index_name_pos(istate, path->buf, path->len); pos = -pos - 1; } else { pos = 0; } i = 0; while (i < it->entry_count) { struct cache_entry *ce = istate->cache[pos + i]; const char *slash; struct cache_tree_sub *sub = NULL; const struct object_id *oid; const char *name; unsigned mode; int entlen; if (ce->ce_flags & (CE_STAGEMASK | CE_INTENT_TO_ADD | CE_REMOVE)) BUG("%s with flags 0x%x should not be in cache-tree", ce->name, ce->ce_flags); name = ce->name + path->len; slash = strchr(name, '/'); if (slash) { entlen = slash - name; sub = find_subtree(it, ce->name + path->len, entlen, 0); if (!sub || sub->cache_tree->entry_count < 0) BUG("bad subtree '%.*s'", entlen, name); oid = &sub->cache_tree->oid; mode = S_IFDIR; i += sub->cache_tree->entry_count; } else { oid = &ce->oid; mode = ce->ce_mode; entlen = ce_namelen(ce) - path->len; i++; } strbuf_addf(&tree_buf, "%o %.*s%c", mode, entlen, name, '\0'); strbuf_add(&tree_buf, oid->hash, the_hash_algo->rawsz); } hash_object_file(tree_buf.buf, tree_buf.len, tree_type, &new_oid); if (!oideq(&new_oid, &it->oid)) BUG("cache-tree for path %.*s does not match. " "Expected %s got %s", len, path->buf, oid_to_hex(&new_oid), oid_to_hex(&it->oid)); strbuf_setlen(path, len); strbuf_release(&tree_buf); }