X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=object.c;h=cf5931a9423cb2ecdd9f34e6c33ed0b714ce61bf;hb=1e80e0449248edb77b0fb9853f4a3404a599e207;hp=72f6aa552f79edcd5f4f5c4a647ab62503365b1b;hpb=e8c80638abc99928dba9ac832589749a531e2e21;p=git.git diff --git a/object.c b/object.c index 72f6aa55..cf5931a9 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,35 +67,71 @@ 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; + if (*pa == *pb) + return 0; + else if (*pa < *pb) + return -1; + else + return 1; +} + +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; } - target->used = 1; - p = xmalloc(sizeof(*p)); - p->item = target; - p->next = NULL; - *pp = p; + /* 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); + } + + 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); } } @@ -184,6 +222,17 @@ struct object_list *object_list_insert(struct object *item, 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;