[PATCH] Parse tags for absent objects
[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 *lookup_object_type(const unsigned char *sha1, const char *type)
102 {
103         if (!strcmp(type, blob_type)) {
104                 return &lookup_blob(sha1)->object;
105         } else if (!strcmp(type, tree_type)) {
106                 return &lookup_tree(sha1)->object;
107         } else if (!strcmp(type, commit_type)) {
108                 return &lookup_commit(sha1)->object;
109         } else if (!strcmp(type, tag_type)) {
110                 return &lookup_tag(sha1)->object;
111         } else {
112                 error("Unknown type %s", type);
113                 return NULL;
114         }
115 }
116
117 struct object *parse_object(const unsigned char *sha1)
118 {
119         unsigned long mapsize;
120         void *map = map_sha1_file(sha1, &mapsize);
121         if (map) {
122                 int is_delta;
123                 struct object *obj;
124                 char type[100];
125                 unsigned long size;
126                 void *buffer = unpack_sha1_file(map, mapsize, type, &size);
127                 munmap(map, mapsize);
128                 if (!buffer)
129                         return NULL;
130                 is_delta = !strcmp(type, "delta");
131                 if (!is_delta && check_sha1_signature(sha1, buffer, size, type) < 0)
132                         printf("sha1 mismatch %s\n", sha1_to_hex(sha1));
133                 if (is_delta) {
134                         struct delta *delta = lookup_delta(sha1);
135                         parse_delta_buffer(delta, buffer, size);
136                         obj = (struct object *) delta;
137                 } else if (!strcmp(type, "blob")) {
138                         struct blob *blob = lookup_blob(sha1);
139                         parse_blob_buffer(blob, buffer, size);
140                         obj = &blob->object;
141                 } else if (!strcmp(type, "tree")) {
142                         struct tree *tree = lookup_tree(sha1);
143                         parse_tree_buffer(tree, buffer, size);
144                         obj = &tree->object;
145                 } else if (!strcmp(type, "commit")) {
146                         struct commit *commit = lookup_commit(sha1);
147                         parse_commit_buffer(commit, buffer, size);
148                         if (!commit->buffer) {
149                                 commit->buffer = buffer;
150                                 buffer = NULL;
151                         }
152                         obj = &commit->object;
153                 } else if (!strcmp(type, "tag")) {
154                         struct tag *tag = lookup_tag(sha1);
155                         parse_tag_buffer(tag, buffer, size);
156                         obj = &tag->object;
157                 } else {
158                         obj = NULL;
159                 }
160                 free(buffer);
161                 return obj;
162         }
163         return NULL;
164 }