[PATCH] Anal retentive 'const unsigned char *sha1'
[git.git] / object.c
1 #include "object.h"
2 #include "blob.h"
3 #include "tree.h"
4 #include "commit.h"
5 #include "cache.h"
6 #include "tag.h"
7 #include "delta.h"
8
9 struct object **objs;
10 int nr_objs;
11 static int obj_allocs;
12
13 static int find_object(const unsigned char *sha1)
14 {
15         int first = 0, last = nr_objs;
16
17         while (first < last) {
18                 int next = (first + last) / 2;
19                 struct object *obj = objs[next];
20                 int cmp;
21
22                 cmp = memcmp(sha1, obj->sha1, 20);
23                 if (!cmp)
24                         return next;
25                 if (cmp < 0) {
26                         last = next;
27                         continue;
28                 }
29                 first = next+1;
30         }
31         return -first-1;
32 }
33
34 struct object *lookup_object(const unsigned char *sha1)
35 {
36         int pos = find_object(sha1);
37         if (pos >= 0)
38                 return objs[pos];
39         return NULL;
40 }
41
42 void created_object(const unsigned char *sha1, struct object *obj)
43 {
44         int pos = find_object(sha1);
45
46         obj->parsed = 0;
47         memcpy(obj->sha1, sha1, 20);
48         obj->type = NULL;
49         obj->refs = NULL;
50         obj->used = 0;
51
52         if (pos >= 0)
53                 die("Inserting %s twice\n", sha1_to_hex(sha1));
54         pos = -pos-1;
55
56         if (obj_allocs == nr_objs) {
57                 obj_allocs = alloc_nr(obj_allocs);
58                 objs = xrealloc(objs, obj_allocs * sizeof(struct object *));
59         }
60
61         /* Insert it into the right place */
62         memmove(objs + pos + 1, objs + pos, (nr_objs - pos) * 
63                 sizeof(struct object *));
64
65         objs[pos] = obj;
66         nr_objs++;
67 }
68
69 void add_ref(struct object *refer, struct object *target)
70 {
71         struct object_list **pp = &refer->refs;
72         struct object_list *p;
73         
74         while ((p = *pp) != NULL) {
75                 if (p->item == target)
76                         return;
77                 pp = &p->next;
78         }
79
80         target->used = 1;
81         p = xmalloc(sizeof(*p));
82         p->item = target;
83         p->next = NULL;
84         *pp = p;
85 }
86
87 void mark_reachable(struct object *obj, unsigned int mask)
88 {
89         struct object_list *p = obj->refs;
90
91         /* If we've been here already, don't bother */
92         if (obj->flags & mask)
93                 return;
94         obj->flags |= mask;
95         while (p) {
96                 mark_reachable(p->item, mask);
97                 p = p->next;
98         }
99 }
100
101 struct object *parse_object(const unsigned char *sha1)
102 {
103         unsigned long mapsize;
104         void *map = map_sha1_file(sha1, &mapsize);
105         if (map) {
106                 int is_delta;
107                 struct object *obj;
108                 char type[100];
109                 unsigned long size;
110                 void *buffer = unpack_sha1_file(map, mapsize, type, &size);
111                 munmap(map, mapsize);
112                 if (!buffer)
113                         return NULL;
114                 is_delta = !strcmp(type, "delta");
115                 if (!is_delta && check_sha1_signature(sha1, buffer, size, type) < 0)
116                         printf("sha1 mismatch %s\n", sha1_to_hex(sha1));
117                 if (is_delta) {
118                         struct delta *delta = lookup_delta(sha1);
119                         parse_delta_buffer(delta, buffer, size);
120                         obj = (struct object *) delta;
121                 } else if (!strcmp(type, "blob")) {
122                         struct blob *blob = lookup_blob(sha1);
123                         parse_blob_buffer(blob, buffer, size);
124                         obj = &blob->object;
125                 } else if (!strcmp(type, "tree")) {
126                         struct tree *tree = lookup_tree(sha1);
127                         parse_tree_buffer(tree, buffer, size);
128                         obj = &tree->object;
129                 } else if (!strcmp(type, "commit")) {
130                         struct commit *commit = lookup_commit(sha1);
131                         parse_commit_buffer(commit, buffer, size);
132                         if (!commit->buffer) {
133                                 commit->buffer = buffer;
134                                 buffer = NULL;
135                         }
136                         obj = &commit->object;
137                 } else if (!strcmp(type, "tag")) {
138                         struct tag *tag = lookup_tag(sha1);
139                         parse_tag_buffer(tag, buffer, size);
140                         obj = &tag->object;
141                 } else {
142                         obj = NULL;
143                 }
144                 free(buffer);
145                 return obj;
146         }
147         return NULL;
148 }