git-repack: avoid redirecting stderr into git-pack-objects
[git] / object.c
1 #include "cache.h"
2 #include "object.h"
3 #include "blob.h"
4 #include "tree.h"
5 #include "commit.h"
6 #include "tag.h"
7
8 static struct object **obj_hash;
9 static int nr_objs, obj_hash_size;
10
11 unsigned int get_max_object_index(void)
12 {
13         return obj_hash_size;
14 }
15
16 struct object *get_indexed_object(unsigned int idx)
17 {
18         return obj_hash[idx];
19 }
20
21 const char *type_names[] = {
22         "none", "blob", "tree", "commit", "bad"
23 };
24
25 static unsigned int hash_obj(struct object *obj, unsigned int n)
26 {
27         unsigned int hash = *(unsigned int *)obj->sha1;
28         return hash % n;
29 }
30
31 static void insert_obj_hash(struct object *obj, struct object **hash, unsigned int size)
32 {
33         int j = hash_obj(obj, size);
34
35         while (hash[j]) {
36                 j++;
37                 if (j >= size)
38                         j = 0;
39         }
40         hash[j] = obj;
41 }
42
43 static int hashtable_index(const unsigned char *sha1)
44 {
45         unsigned int i;
46         memcpy(&i, sha1, sizeof(unsigned int));
47         return (int)(i % obj_hash_size);
48 }
49
50 struct object *lookup_object(const unsigned char *sha1)
51 {
52         int i;
53         struct object *obj;
54
55         if (!obj_hash)
56                 return NULL;
57
58         i = hashtable_index(sha1);
59         while ((obj = obj_hash[i]) != NULL) {
60                 if (!memcmp(sha1, obj->sha1, 20))
61                         break;
62                 i++;
63                 if (i == obj_hash_size)
64                         i = 0;
65         }
66         return obj;
67 }
68
69 static void grow_object_hash(void)
70 {
71         int i;
72         int new_hash_size = obj_hash_size < 32 ? 32 : 2 * obj_hash_size;
73         struct object **new_hash;
74
75         new_hash = calloc(new_hash_size, sizeof(struct object *));
76         for (i = 0; i < obj_hash_size; i++) {
77                 struct object *obj = obj_hash[i];
78                 if (!obj)
79                         continue;
80                 insert_obj_hash(obj, new_hash, new_hash_size);
81         }
82         free(obj_hash);
83         obj_hash = new_hash;
84         obj_hash_size = new_hash_size;
85 }
86
87 void created_object(const unsigned char *sha1, struct object *obj)
88 {
89         obj->parsed = 0;
90         obj->used = 0;
91         obj->type = TYPE_NONE;
92         obj->flags = 0;
93         memcpy(obj->sha1, sha1, 20);
94
95         if (obj_hash_size - 1 <= nr_objs * 2)
96                 grow_object_hash();
97
98         insert_obj_hash(obj, obj_hash, obj_hash_size);
99         nr_objs++;
100 }
101
102 struct object *lookup_object_type(const unsigned char *sha1, const char *type)
103 {
104         if (!type) {
105                 return lookup_unknown_object(sha1);
106         } else if (!strcmp(type, blob_type)) {
107                 return &lookup_blob(sha1)->object;
108         } else if (!strcmp(type, tree_type)) {
109                 return &lookup_tree(sha1)->object;
110         } else if (!strcmp(type, commit_type)) {
111                 return &lookup_commit(sha1)->object;
112         } else if (!strcmp(type, tag_type)) {
113                 return &lookup_tag(sha1)->object;
114         } else {
115                 error("Unknown type %s", type);
116                 return NULL;
117         }
118 }
119
120 union any_object {
121         struct object object;
122         struct commit commit;
123         struct tree tree;
124         struct blob blob;
125         struct tag tag;
126 };
127
128 struct object *lookup_unknown_object(const unsigned char *sha1)
129 {
130         struct object *obj = lookup_object(sha1);
131         if (!obj) {
132                 union any_object *ret = xcalloc(1, sizeof(*ret));
133                 created_object(sha1, &ret->object);
134                 ret->object.type = TYPE_NONE;
135                 return &ret->object;
136         }
137         return obj;
138 }
139
140 struct object *parse_object(const unsigned char *sha1)
141 {
142         unsigned long size;
143         char type[20];
144         void *buffer = read_sha1_file(sha1, type, &size);
145         if (buffer) {
146                 struct object *obj;
147                 if (check_sha1_signature(sha1, buffer, size, type) < 0)
148                         printf("sha1 mismatch %s\n", sha1_to_hex(sha1));
149                 if (!strcmp(type, blob_type)) {
150                         struct blob *blob = lookup_blob(sha1);
151                         parse_blob_buffer(blob, buffer, size);
152                         obj = &blob->object;
153                 } else if (!strcmp(type, tree_type)) {
154                         struct tree *tree = lookup_tree(sha1);
155                         obj = &tree->object;
156                         if (!tree->object.parsed) {
157                                 parse_tree_buffer(tree, buffer, size);
158                                 buffer = NULL;
159                         }
160                 } else if (!strcmp(type, commit_type)) {
161                         struct commit *commit = lookup_commit(sha1);
162                         parse_commit_buffer(commit, buffer, size);
163                         if (!commit->buffer) {
164                                 commit->buffer = buffer;
165                                 buffer = NULL;
166                         }
167                         obj = &commit->object;
168                 } else if (!strcmp(type, tag_type)) {
169                         struct tag *tag = lookup_tag(sha1);
170                         parse_tag_buffer(tag, buffer, size);
171                         obj = &tag->object;
172                 } else {
173                         obj = NULL;
174                 }
175                 free(buffer);
176                 return obj;
177         }
178         return NULL;
179 }
180
181 struct object_list *object_list_insert(struct object *item,
182                                        struct object_list **list_p)
183 {
184         struct object_list *new_list = xmalloc(sizeof(struct object_list));
185         new_list->item = item;
186         new_list->next = *list_p;
187         *list_p = new_list;
188         return new_list;
189 }
190
191 void object_list_append(struct object *item,
192                         struct object_list **list_p)
193 {
194         while (*list_p) {
195                 list_p = &((*list_p)->next);
196         }
197         *list_p = xmalloc(sizeof(struct object_list));
198         (*list_p)->next = NULL;
199         (*list_p)->item = item;
200 }
201
202 unsigned object_list_length(struct object_list *list)
203 {
204         unsigned ret = 0;
205         while (list) {
206                 list = list->next;
207                 ret++;
208         }
209         return ret;
210 }
211
212 int object_list_contains(struct object_list *list, struct object *obj)
213 {
214         while (list) {
215                 if (list->item == obj)
216                         return 1;
217                 list = list->next;
218         }
219         return 0;
220 }
221
222 void add_object_array(struct object *obj, const char *name, struct object_array *array)
223 {
224         unsigned nr = array->nr;
225         unsigned alloc = array->alloc;
226         struct object_array_entry *objects = array->objects;
227
228         if (nr >= alloc) {
229                 alloc = (alloc + 32) * 2;
230                 objects = xrealloc(objects, alloc * sizeof(*objects));
231                 array->alloc = alloc;
232                 array->objects = objects;
233         }
234         objects[nr].item = obj;
235         objects[nr].name = name;
236         array->nr = ++nr;
237 }