X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=object.c;h=427e14cae2deb42138a439f7b2d69d3e06bb9417;hb=f98d863d2122e1b8781dfb9889df98876a26f315;hp=c410e97c8f378bd6c680efa48c82c3d3f7907103;hpb=85c1f337be49eaa9a22e42a1c9958deef5ab57c3;p=git.git diff --git a/object.c b/object.c index c410e97c..427e14ca 100644 --- a/object.c +++ b/object.c @@ -9,6 +9,8 @@ struct object **objs; int nr_objs; static int obj_allocs; +int track_object_refs = 1; + static int find_object(const unsigned char *sha1) { int first = 0, last = nr_objs; @@ -65,41 +67,74 @@ void created_object(const unsigned char *sha1, struct object *obj) nr_objs++; } -void add_ref(struct object *refer, struct object *target) +struct object_refs *alloc_object_refs(unsigned count) +{ + struct object_refs *refs; + size_t size = sizeof(*refs) + count*sizeof(struct object *); + + refs = xmalloc(size); + memset(refs, 0, size); + refs->count = count; + return refs; +} + +static int compare_object_pointers(const void *a, const void *b) { - struct object_list **pp = &refer->refs; - struct object_list *p; - - while ((p = *pp) != NULL) { - if (p->item == target) - return; - pp = &p->next; + const struct object * const *pa = a; + const struct object * const *pb = b; + return *pa - *pb; +} + +void set_object_refs(struct object *obj, struct object_refs *refs) +{ + unsigned int i, j; + + /* Do not install empty list of references */ + if (refs->count < 1) { + free(refs); + return; + } + + /* 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); } - target->used = 1; - p = xmalloc(sizeof(*p)); - p->item = target; - p->next = NULL; - *pp = p; + for (i = 0; i < refs->count; i++) + refs->ref[i]->used = 1; + obj->refs = refs; } void mark_reachable(struct object *obj, unsigned int mask) { - struct object_list *p = obj->refs; - + 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; - while (p) { - mark_reachable(p->item, mask); - p = p->next; + 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); } } struct object *lookup_object_type(const unsigned char *sha1, const char *type) { - if (!strcmp(type, blob_type)) { + if (!type) { + return lookup_unknown_object(sha1); + } else if (!strcmp(type, blob_type)) { return &lookup_blob(sha1)->object; } else if (!strcmp(type, tree_type)) { return &lookup_tree(sha1)->object; @@ -113,6 +148,27 @@ struct object *lookup_object_type(const unsigned char *sha1, const char *type) } } +union any_object { + struct object object; + struct commit commit; + struct tree tree; + struct blob blob; + struct tag tag; +}; + +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)); + created_object(sha1, &ret->object); + ret->object.type = NULL; + return &ret->object; + } + return obj; +} + struct object *parse_object(const unsigned char *sha1) { unsigned long size; @@ -150,3 +206,44 @@ struct object *parse_object(const unsigned char *sha1) } return NULL; } + +struct object_list *object_list_insert(struct object *item, + struct object_list **list_p) +{ + struct object_list *new_list = xmalloc(sizeof(struct object_list)); + new_list->item = item; + new_list->next = *list_p; + *list_p = new_list; + return new_list; +} + +void object_list_append(struct object *item, + struct object_list **list_p) +{ + while (*list_p) { + list_p = &((*list_p)->next); + } + *list_p = xmalloc(sizeof(struct object_list)); + (*list_p)->next = NULL; + (*list_p)->item = item; +} + +unsigned object_list_length(struct object_list *list) +{ + unsigned ret = 0; + while (list) { + list = list->next; + ret++; + } + return ret; +} + +int object_list_contains(struct object_list *list, struct object *obj) +{ + while (list) { + if (list->item == obj) + return 1; + list = list->next; + } + return 0; +}