X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=object.c;h=b5d8ed467d1c10c2f2dd596717159f7ee48a8007;hb=5f468c4805c785115cd9c5f6a8f299f23a9034f5;hp=1577f74281be776082fecebdf8947bcb8c7c6802;hpb=90768daaa006516c7ae69ed89d7c2e67243dfac1;p=git.git diff --git a/object.c b/object.c index 1577f7428..b5d8ed467 100644 --- a/object.c +++ b/object.c @@ -5,134 +5,99 @@ #include "commit.h" #include "tag.h" -struct object **objs; -int nr_objs; -static int obj_allocs; +static struct object **obj_hash; +static int nr_objs, obj_hash_size; -int track_object_refs = 1; - -static int find_object(const unsigned char *sha1) +unsigned int get_max_object_index(void) { - int first = 0, last = nr_objs; - - while (first < last) { - int next = (first + last) / 2; - struct object *obj = objs[next]; - int cmp; - - cmp = memcmp(sha1, obj->sha1, 20); - if (!cmp) - return next; - if (cmp < 0) { - last = next; - continue; - } - first = next+1; - } - return -first-1; + return obj_hash_size; } -struct object *lookup_object(const unsigned char *sha1) +struct object *get_indexed_object(unsigned int idx) { - int pos = find_object(sha1); - if (pos >= 0) - return objs[pos]; - return NULL; + return obj_hash[idx]; } -void created_object(const unsigned char *sha1, struct object *obj) -{ - int pos = find_object(sha1); - - obj->parsed = 0; - memcpy(obj->sha1, sha1, 20); - obj->type = NULL; - obj->refs = NULL; - obj->used = 0; - - if (pos >= 0) - die("Inserting %s twice\n", sha1_to_hex(sha1)); - pos = -pos-1; - - if (obj_allocs == nr_objs) { - obj_allocs = alloc_nr(obj_allocs); - objs = xrealloc(objs, obj_allocs * sizeof(struct object *)); - } - - /* Insert it into the right place */ - memmove(objs + pos + 1, objs + pos, (nr_objs - pos) * - sizeof(struct object *)); +const char *type_names[] = { + "none", "commit", "tree", "blob", "tag", + "bad type 5", "bad type 6", "delta", "bad", +}; - objs[pos] = obj; - nr_objs++; +static unsigned int hash_obj(struct object *obj, unsigned int n) +{ + unsigned int hash = *(unsigned int *)obj->sha1; + return hash % n; } -struct object_refs *alloc_object_refs(unsigned count) +static void insert_obj_hash(struct object *obj, struct object **hash, unsigned int size) { - struct object_refs *refs; - size_t size = sizeof(*refs) + count*sizeof(struct object *); + int j = hash_obj(obj, size); - refs = xmalloc(size); - memset(refs, 0, size); - refs->count = count; - return refs; + while (hash[j]) { + j++; + if (j >= size) + j = 0; + } + hash[j] = obj; } -static int compare_object_pointers(const void *a, const void *b) +static int hashtable_index(const unsigned char *sha1) { - const struct object * const *pa = a; - const struct object * const *pb = b; - if (*pa == *pb) - return 0; - else if (*pa < *pb) - return -1; - else - return 1; + unsigned int i; + memcpy(&i, sha1, sizeof(unsigned int)); + return (int)(i % obj_hash_size); } -void set_object_refs(struct object *obj, struct object_refs *refs) +struct object *lookup_object(const unsigned char *sha1) { - unsigned int i, j; + int i; + struct object *obj; - /* Do not install empty list of references */ - if (refs->count < 1) { - free(refs); - return; - } + if (!obj_hash) + return NULL; - /* Sort the list and filter out duplicates */ - qsort(refs->ref, refs->count, sizeof(refs->ref[0]), - compare_object_pointers); - for (i = j = 1; i < refs->count; i++) { - if (refs->ref[i] != refs->ref[i - 1]) - refs->ref[j++] = refs->ref[i]; - } - if (j < refs->count) { - /* Duplicates were found - reallocate list */ - size_t size = sizeof(*refs) + j*sizeof(struct object *); - refs->count = j; - refs = xrealloc(refs, size); + i = hashtable_index(sha1); + while ((obj = obj_hash[i]) != NULL) { + if (!memcmp(sha1, obj->sha1, 20)) + break; + i++; + if (i == obj_hash_size) + i = 0; } - - for (i = 0; i < refs->count; i++) - refs->ref[i]->used = 1; - obj->refs = refs; + return obj; } -void mark_reachable(struct object *obj, unsigned int mask) +static void grow_object_hash(void) { - if (!track_object_refs) - die("cannot do reachability with object refs turned off"); - /* If we've been here already, don't bother */ - if (obj->flags & mask) - return; - obj->flags |= mask; - if (obj->refs) { - const struct object_refs *refs = obj->refs; - unsigned i; - for (i = 0; i < refs->count; i++) - mark_reachable(refs->ref[i], mask); + int i; + int new_hash_size = obj_hash_size < 32 ? 32 : 2 * obj_hash_size; + struct object **new_hash; + + new_hash = calloc(new_hash_size, sizeof(struct object *)); + for (i = 0; i < obj_hash_size; i++) { + struct object *obj = obj_hash[i]; + if (!obj) + continue; + insert_obj_hash(obj, new_hash, new_hash_size); } + free(obj_hash); + obj_hash = new_hash; + obj_hash_size = new_hash_size; +} + +void created_object(const unsigned char *sha1, struct object *obj) +{ + obj->parsed = 0; + obj->used = 0; + obj->type = OBJ_NONE; + obj->flags = 0; + memcpy(obj->sha1, sha1, 20); + + if (obj_hash_size - 1 <= nr_objs * 2) + grow_object_hash(); + + insert_obj_hash(obj, obj_hash, obj_hash_size); + nr_objs++; } struct object *lookup_object_type(const unsigned char *sha1, const char *type) @@ -165,10 +130,9 @@ struct object *lookup_unknown_object(const unsigned char *sha1) { struct object *obj = lookup_object(sha1); if (!obj) { - union any_object *ret = xmalloc(sizeof(*ret)); - memset(ret, 0, sizeof(*ret)); + union any_object *ret = xcalloc(1, sizeof(*ret)); created_object(sha1, &ret->object); - ret->object.type = NULL; + ret->object.type = OBJ_NONE; return &ret->object; } return obj; @@ -183,15 +147,18 @@ struct object *parse_object(const unsigned char *sha1) struct object *obj; if (check_sha1_signature(sha1, buffer, size, type) < 0) printf("sha1 mismatch %s\n", sha1_to_hex(sha1)); - if (!strcmp(type, "blob")) { + if (!strcmp(type, blob_type)) { struct blob *blob = lookup_blob(sha1); parse_blob_buffer(blob, buffer, size); obj = &blob->object; - } else if (!strcmp(type, "tree")) { + } else if (!strcmp(type, tree_type)) { struct tree *tree = lookup_tree(sha1); - parse_tree_buffer(tree, buffer, size); obj = &tree->object; - } else if (!strcmp(type, "commit")) { + if (!tree->object.parsed) { + parse_tree_buffer(tree, buffer, size); + buffer = NULL; + } + } else if (!strcmp(type, commit_type)) { struct commit *commit = lookup_commit(sha1); parse_commit_buffer(commit, buffer, size); if (!commit->buffer) { @@ -199,7 +166,7 @@ struct object *parse_object(const unsigned char *sha1) buffer = NULL; } obj = &commit->object; - } else if (!strcmp(type, "tag")) { + } else if (!strcmp(type, tag_type)) { struct tag *tag = lookup_tag(sha1); parse_tag_buffer(tag, buffer, size); obj = &tag->object; @@ -252,3 +219,20 @@ int object_list_contains(struct object_list *list, struct object *obj) } return 0; } + +void add_object_array(struct object *obj, const char *name, struct object_array *array) +{ + unsigned nr = array->nr; + unsigned alloc = array->alloc; + struct object_array_entry *objects = array->objects; + + if (nr >= alloc) { + alloc = (alloc + 32) * 2; + objects = xrealloc(objects, alloc * sizeof(*objects)); + array->alloc = alloc; + array->objects = objects; + } + objects[nr].item = obj; + objects[nr].name = name; + array->nr = ++nr; +}