10 static int obj_allocs
;
12 int track_object_refs
= 1;
14 static int find_object(const unsigned char *sha1
)
16 int first
= 0, last
= nr_objs
;
18 while (first
< last
) {
19 int next
= (first
+ last
) / 2;
20 struct object
*obj
= objs
[next
];
23 cmp
= memcmp(sha1
, obj
->sha1
, 20);
35 struct object
*lookup_object(const unsigned char *sha1
)
37 int pos
= find_object(sha1
);
43 void created_object(const unsigned char *sha1
, struct object
*obj
)
45 int pos
= find_object(sha1
);
48 memcpy(obj
->sha1
, sha1
, 20);
54 die("Inserting %s twice\n", sha1_to_hex(sha1
));
57 if (obj_allocs
== nr_objs
) {
58 obj_allocs
= alloc_nr(obj_allocs
);
59 objs
= xrealloc(objs
, obj_allocs
* sizeof(struct object
*));
62 /* Insert it into the right place */
63 memmove(objs
+ pos
+ 1, objs
+ pos
, (nr_objs
- pos
) *
64 sizeof(struct object
*));
70 struct object_refs
*alloc_object_refs(unsigned count
)
72 struct object_refs
*refs
;
73 size_t size
= sizeof(*refs
) + count
*sizeof(struct object
*);
76 memset(refs
, 0, size
);
81 static int compare_object_pointers(const void *a
, const void *b
)
83 const struct object
* const *pa
= a
;
84 const struct object
* const *pb
= b
;
93 void set_object_refs(struct object
*obj
, struct object_refs
*refs
)
97 /* Do not install empty list of references */
98 if (refs
->count
< 1) {
103 /* Sort the list and filter out duplicates */
104 qsort(refs
->ref
, refs
->count
, sizeof(refs
->ref
[0]),
105 compare_object_pointers
);
106 for (i
= j
= 1; i
< refs
->count
; i
++) {
107 if (refs
->ref
[i
] != refs
->ref
[i
- 1])
108 refs
->ref
[j
++] = refs
->ref
[i
];
110 if (j
< refs
->count
) {
111 /* Duplicates were found - reallocate list */
112 size_t size
= sizeof(*refs
) + j
*sizeof(struct object
*);
114 refs
= xrealloc(refs
, size
);
117 for (i
= 0; i
< refs
->count
; i
++)
118 refs
->ref
[i
]->used
= 1;
122 void mark_reachable(struct object
*obj
, unsigned int mask
)
124 if (!track_object_refs
)
125 die("cannot do reachability with object refs turned off");
126 /* If we've been here already, don't bother */
127 if (obj
->flags
& mask
)
131 const struct object_refs
*refs
= obj
->refs
;
133 for (i
= 0; i
< refs
->count
; i
++)
134 mark_reachable(refs
->ref
[i
], mask
);
138 struct object
*lookup_object_type(const unsigned char *sha1
, const char *type
)
141 return lookup_unknown_object(sha1
);
142 } else if (!strcmp(type
, blob_type
)) {
143 return &lookup_blob(sha1
)->object
;
144 } else if (!strcmp(type
, tree_type
)) {
145 return &lookup_tree(sha1
)->object
;
146 } else if (!strcmp(type
, commit_type
)) {
147 return &lookup_commit(sha1
)->object
;
148 } else if (!strcmp(type
, tag_type
)) {
149 return &lookup_tag(sha1
)->object
;
151 error("Unknown type %s", type
);
157 struct object object
;
158 struct commit commit
;
164 struct object
*lookup_unknown_object(const unsigned char *sha1
)
166 struct object
*obj
= lookup_object(sha1
);
168 union any_object
*ret
= xmalloc(sizeof(*ret
));
169 memset(ret
, 0, sizeof(*ret
));
170 created_object(sha1
, &ret
->object
);
171 ret
->object
.type
= NULL
;
177 struct object
*parse_object(const unsigned char *sha1
)
181 void *buffer
= read_sha1_file(sha1
, type
, &size
);
184 if (check_sha1_signature(sha1
, buffer
, size
, type
) < 0)
185 printf("sha1 mismatch %s\n", sha1_to_hex(sha1
));
186 if (!strcmp(type
, "blob")) {
187 struct blob
*blob
= lookup_blob(sha1
);
188 parse_blob_buffer(blob
, buffer
, size
);
190 } else if (!strcmp(type
, "tree")) {
191 struct tree
*tree
= lookup_tree(sha1
);
192 parse_tree_buffer(tree
, buffer
, size
);
194 } else if (!strcmp(type
, "commit")) {
195 struct commit
*commit
= lookup_commit(sha1
);
196 parse_commit_buffer(commit
, buffer
, size
);
197 if (!commit
->buffer
) {
198 commit
->buffer
= buffer
;
201 obj
= &commit
->object
;
202 } else if (!strcmp(type
, "tag")) {
203 struct tag
*tag
= lookup_tag(sha1
);
204 parse_tag_buffer(tag
, buffer
, size
);
215 struct object_list
*object_list_insert(struct object
*item
,
216 struct object_list
**list_p
)
218 struct object_list
*new_list
= xmalloc(sizeof(struct object_list
));
219 new_list
->item
= item
;
220 new_list
->next
= *list_p
;
225 void object_list_append(struct object
*item
,
226 struct object_list
**list_p
)
229 list_p
= &((*list_p
)->next
);
231 *list_p
= xmalloc(sizeof(struct object_list
));
232 (*list_p
)->next
= NULL
;
233 (*list_p
)->item
= item
;
236 unsigned object_list_length(struct object_list
*list
)
246 int object_list_contains(struct object_list
*list
, struct object
*obj
)
249 if (list
->item
== obj
)