|  | #include "object.h" | 
|  | #include "blob.h" | 
|  | #include "tree.h" | 
|  | #include "commit.h" | 
|  | #include "cache.h" | 
|  | #include "tag.h" | 
|  | #include "delta.h" | 
|  |  | 
|  | struct object **objs; | 
|  | int nr_objs; | 
|  | static int obj_allocs; | 
|  |  | 
|  | static int find_object(unsigned char *sha1) | 
|  | { | 
|  | 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; | 
|  | } | 
|  |  | 
|  | struct object *lookup_object(unsigned char *sha1) | 
|  | { | 
|  | int pos = find_object(sha1); | 
|  | if (pos >= 0) | 
|  | return objs[pos]; | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | void created_object(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 *)); | 
|  |  | 
|  | objs[pos] = obj; | 
|  | nr_objs++; | 
|  | } | 
|  |  | 
|  | void add_ref(struct object *refer, struct object *target) | 
|  | { | 
|  | struct object_list **pp = &refer->refs; | 
|  | struct object_list *p; | 
|  |  | 
|  | while ((p = *pp) != NULL) { | 
|  | if (p->item == target) | 
|  | return; | 
|  | pp = &p->next; | 
|  | } | 
|  |  | 
|  | target->used = 1; | 
|  | p = xmalloc(sizeof(*p)); | 
|  | p->item = target; | 
|  | p->next = NULL; | 
|  | *pp = p; | 
|  | } | 
|  |  | 
|  | void mark_reachable(struct object *obj, unsigned int mask) | 
|  | { | 
|  | struct object_list *p = obj->refs; | 
|  |  | 
|  | /* 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; | 
|  | } | 
|  | } | 
|  |  | 
|  | struct object *parse_object(unsigned char *sha1) | 
|  | { | 
|  | unsigned long mapsize; | 
|  | void *map = map_sha1_file(sha1, &mapsize); | 
|  | if (map) { | 
|  | int is_delta; | 
|  | struct object *obj; | 
|  | char type[100]; | 
|  | unsigned long size; | 
|  | void *buffer = unpack_sha1_file(map, mapsize, type, &size); | 
|  | munmap(map, mapsize); | 
|  | if (!buffer) | 
|  | return NULL; | 
|  | is_delta = !strcmp(type, "delta"); | 
|  | if (!is_delta && check_sha1_signature(sha1, buffer, size, type) < 0) | 
|  | printf("sha1 mismatch %s\n", sha1_to_hex(sha1)); | 
|  | if (is_delta) { | 
|  | struct delta *delta = lookup_delta(sha1); | 
|  | parse_delta_buffer(delta, buffer, size); | 
|  | obj = (struct object *) delta; | 
|  | } else if (!strcmp(type, "blob")) { | 
|  | struct blob *blob = lookup_blob(sha1); | 
|  | parse_blob_buffer(blob, buffer, size); | 
|  | obj = &blob->object; | 
|  | } else if (!strcmp(type, "tree")) { | 
|  | struct tree *tree = lookup_tree(sha1); | 
|  | parse_tree_buffer(tree, buffer, size); | 
|  | obj = &tree->object; | 
|  | } else if (!strcmp(type, "commit")) { | 
|  | struct commit *commit = lookup_commit(sha1); | 
|  | parse_commit_buffer(commit, buffer, size); | 
|  | if (!commit->buffer) { | 
|  | commit->buffer = buffer; | 
|  | buffer = NULL; | 
|  | } | 
|  | obj = &commit->object; | 
|  | } else if (!strcmp(type, "tag")) { | 
|  | struct tag *tag = lookup_tag(sha1); | 
|  | parse_tag_buffer(tag, buffer, size); | 
|  | obj = &tag->object; | 
|  | } else { | 
|  | obj = NULL; | 
|  | } | 
|  | free(buffer); | 
|  | return obj; | 
|  | } | 
|  | return NULL; | 
|  | } |