]>
Commit | Line | Data |
---|---|---|
8f1d2e6f | 1 | #include "cache.h" |
175785e5 | 2 | #include "object.h" |
e9eefa67 DB |
3 | #include "blob.h" |
4 | #include "tree.h" | |
5 | #include "commit.h" | |
e9eefa67 | 6 | #include "tag.h" |
175785e5 DB |
7 | |
8 | struct object **objs; | |
070879ca JS |
9 | static int nr_objs; |
10 | int obj_allocs; | |
175785e5 | 11 | |
885a86ab LT |
12 | const char *type_names[] = { |
13 | "none", "blob", "tree", "commit", "bad" | |
14 | }; | |
15 | ||
070879ca JS |
16 | static int hashtable_index(const unsigned char *sha1) |
17 | { | |
2b796360 JH |
18 | unsigned int i; |
19 | memcpy(&i, sha1, sizeof(unsigned int)); | |
070879ca JS |
20 | return (int)(i % obj_allocs); |
21 | } | |
22 | ||
5d6ccf5c | 23 | static int find_object(const unsigned char *sha1) |
175785e5 | 24 | { |
2b796360 | 25 | int i; |
175785e5 | 26 | |
070879ca JS |
27 | if (!objs) |
28 | return -1; | |
175785e5 | 29 | |
2b796360 | 30 | i = hashtable_index(sha1); |
070879ca JS |
31 | while (objs[i]) { |
32 | if (memcmp(sha1, objs[i]->sha1, 20) == 0) | |
33 | return i; | |
34 | i++; | |
35 | if (i == obj_allocs) | |
36 | i = 0; | |
37 | } | |
38 | return -1 - i; | |
175785e5 DB |
39 | } |
40 | ||
5d6ccf5c | 41 | struct object *lookup_object(const unsigned char *sha1) |
175785e5 DB |
42 | { |
43 | int pos = find_object(sha1); | |
44 | if (pos >= 0) | |
45 | return objs[pos]; | |
46 | return NULL; | |
47 | } | |
48 | ||
5d6ccf5c | 49 | void created_object(const unsigned char *sha1, struct object *obj) |
175785e5 | 50 | { |
070879ca | 51 | int pos; |
175785e5 DB |
52 | |
53 | obj->parsed = 0; | |
54 | memcpy(obj->sha1, sha1, 20); | |
885a86ab | 55 | obj->type = TYPE_NONE; |
175785e5 DB |
56 | obj->used = 0; |
57 | ||
070879ca JS |
58 | if (obj_allocs - 1 <= nr_objs * 2) { |
59 | int i, count = obj_allocs; | |
60 | obj_allocs = (obj_allocs < 32 ? 32 : 2 * obj_allocs); | |
812666c8 | 61 | objs = xrealloc(objs, obj_allocs * sizeof(struct object *)); |
070879ca JS |
62 | memset(objs + count, 0, (obj_allocs - count) |
63 | * sizeof(struct object *)); | |
d7ee090d | 64 | for (i = 0; i < obj_allocs; i++) |
070879ca JS |
65 | if (objs[i]) { |
66 | int j = find_object(objs[i]->sha1); | |
67 | if (j != i) { | |
68 | j = -1 - j; | |
69 | objs[j] = objs[i]; | |
70 | objs[i] = NULL; | |
71 | } | |
72 | } | |
175785e5 DB |
73 | } |
74 | ||
070879ca JS |
75 | pos = find_object(sha1); |
76 | if (pos >= 0) | |
77 | die("Inserting %s twice\n", sha1_to_hex(sha1)); | |
78 | pos = -pos-1; | |
175785e5 DB |
79 | |
80 | objs[pos] = obj; | |
81 | nr_objs++; | |
82 | } | |
83 | ||
89e4202f DB |
84 | struct object *lookup_object_type(const unsigned char *sha1, const char *type) |
85 | { | |
66e481b0 DB |
86 | if (!type) { |
87 | return lookup_unknown_object(sha1); | |
88 | } else if (!strcmp(type, blob_type)) { | |
89e4202f DB |
89 | return &lookup_blob(sha1)->object; |
90 | } else if (!strcmp(type, tree_type)) { | |
91 | return &lookup_tree(sha1)->object; | |
92 | } else if (!strcmp(type, commit_type)) { | |
93 | return &lookup_commit(sha1)->object; | |
94 | } else if (!strcmp(type, tag_type)) { | |
95 | return &lookup_tag(sha1)->object; | |
96 | } else { | |
97 | error("Unknown type %s", type); | |
98 | return NULL; | |
99 | } | |
100 | } | |
101 | ||
66e481b0 DB |
102 | union any_object { |
103 | struct object object; | |
104 | struct commit commit; | |
105 | struct tree tree; | |
106 | struct blob blob; | |
107 | struct tag tag; | |
108 | }; | |
109 | ||
110 | struct object *lookup_unknown_object(const unsigned char *sha1) | |
111 | { | |
112 | struct object *obj = lookup_object(sha1); | |
113 | if (!obj) { | |
90321c10 | 114 | union any_object *ret = xcalloc(1, sizeof(*ret)); |
66e481b0 | 115 | created_object(sha1, &ret->object); |
885a86ab | 116 | ret->object.type = TYPE_NONE; |
66e481b0 DB |
117 | return &ret->object; |
118 | } | |
119 | return obj; | |
120 | } | |
121 | ||
5d6ccf5c | 122 | struct object *parse_object(const unsigned char *sha1) |
e9eefa67 | 123 | { |
c4584ae3 JH |
124 | unsigned long size; |
125 | char type[20]; | |
126 | void *buffer = read_sha1_file(sha1, type, &size); | |
127 | if (buffer) { | |
bd2c39f5 | 128 | struct object *obj; |
c4584ae3 | 129 | if (check_sha1_signature(sha1, buffer, size, type) < 0) |
e9eefa67 | 130 | printf("sha1 mismatch %s\n", sha1_to_hex(sha1)); |
8e440259 | 131 | if (!strcmp(type, blob_type)) { |
bd2c39f5 NP |
132 | struct blob *blob = lookup_blob(sha1); |
133 | parse_blob_buffer(blob, buffer, size); | |
134 | obj = &blob->object; | |
8e440259 | 135 | } else if (!strcmp(type, tree_type)) { |
bd2c39f5 | 136 | struct tree *tree = lookup_tree(sha1); |
bd2c39f5 | 137 | obj = &tree->object; |
136f2e54 LT |
138 | if (!tree->object.parsed) { |
139 | parse_tree_buffer(tree, buffer, size); | |
140 | buffer = NULL; | |
141 | } | |
8e440259 | 142 | } else if (!strcmp(type, commit_type)) { |
bd2c39f5 NP |
143 | struct commit *commit = lookup_commit(sha1); |
144 | parse_commit_buffer(commit, buffer, size); | |
bd1e17e2 LT |
145 | if (!commit->buffer) { |
146 | commit->buffer = buffer; | |
147 | buffer = NULL; | |
148 | } | |
bd2c39f5 | 149 | obj = &commit->object; |
8e440259 | 150 | } else if (!strcmp(type, tag_type)) { |
bd2c39f5 NP |
151 | struct tag *tag = lookup_tag(sha1); |
152 | parse_tag_buffer(tag, buffer, size); | |
153 | obj = &tag->object; | |
e9eefa67 | 154 | } else { |
bd2c39f5 | 155 | obj = NULL; |
e9eefa67 | 156 | } |
bd2c39f5 NP |
157 | free(buffer); |
158 | return obj; | |
e9eefa67 DB |
159 | } |
160 | return NULL; | |
161 | } | |
66e481b0 DB |
162 | |
163 | struct object_list *object_list_insert(struct object *item, | |
164 | struct object_list **list_p) | |
165 | { | |
166 | struct object_list *new_list = xmalloc(sizeof(struct object_list)); | |
167 | new_list->item = item; | |
168 | new_list->next = *list_p; | |
169 | *list_p = new_list; | |
170 | return new_list; | |
171 | } | |
172 | ||
680bab3d DB |
173 | void object_list_append(struct object *item, |
174 | struct object_list **list_p) | |
175 | { | |
176 | while (*list_p) { | |
177 | list_p = &((*list_p)->next); | |
178 | } | |
179 | *list_p = xmalloc(sizeof(struct object_list)); | |
180 | (*list_p)->next = NULL; | |
181 | (*list_p)->item = item; | |
182 | } | |
183 | ||
66e481b0 DB |
184 | unsigned object_list_length(struct object_list *list) |
185 | { | |
186 | unsigned ret = 0; | |
187 | while (list) { | |
188 | list = list->next; | |
189 | ret++; | |
190 | } | |
191 | return ret; | |
192 | } | |
193 | ||
194 | int object_list_contains(struct object_list *list, struct object *obj) | |
195 | { | |
196 | while (list) { | |
197 | if (list->item == obj) | |
198 | return 1; | |
199 | list = list->next; | |
200 | } | |
201 | return 0; | |
202 | } |