blob: 5345671569e9500ad31124dacf9525739687d9be [file] [log] [blame]
Linus Torvalds3e4339e2006-06-18 11:45:02 -07001#include "cache.h"
2#include "object.h"
Linus Torvaldsa59b2762007-04-16 16:03:15 -07003#include "decorate.h"
Linus Torvalds3e4339e2006-06-18 11:45:02 -07004
5int track_object_refs = 0;
6
Linus Torvaldsa59b2762007-04-16 16:03:15 -07007static struct decoration ref_decorate;
Linus Torvalds3e4339e2006-06-18 11:45:02 -07008
Linus Torvaldsa59b2762007-04-16 16:03:15 -07009struct object_refs *lookup_object_refs(struct object *base)
Linus Torvalds3e4339e2006-06-18 11:45:02 -070010{
Linus Torvaldsa59b2762007-04-16 16:03:15 -070011 return lookup_decoration(&ref_decorate, base);
Linus Torvalds3e4339e2006-06-18 11:45:02 -070012}
13
Linus Torvaldsa59b2762007-04-16 16:03:15 -070014static void add_object_refs(struct object *obj, struct object_refs *refs)
Linus Torvalds5fdc8492006-06-21 11:01:12 -070015{
Linus Torvaldsa59b2762007-04-16 16:03:15 -070016 if (add_decoration(&ref_decorate, obj, refs))
17 die("object %s tried to add refs twice!", sha1_to_hex(obj->sha1));
Linus Torvalds3e4339e2006-06-18 11:45:02 -070018}
19
20struct object_refs *alloc_object_refs(unsigned count)
21{
22 struct object_refs *refs;
23 size_t size = sizeof(*refs) + count*sizeof(struct object *);
24
25 refs = xcalloc(1, size);
26 refs->count = count;
27 return refs;
28}
29
30static int compare_object_pointers(const void *a, const void *b)
31{
32 const struct object * const *pa = a;
33 const struct object * const *pb = b;
34 if (*pa == *pb)
35 return 0;
36 else if (*pa < *pb)
37 return -1;
38 else
39 return 1;
40}
41
42void set_object_refs(struct object *obj, struct object_refs *refs)
43{
44 unsigned int i, j;
45
46 /* Do not install empty list of references */
47 if (refs->count < 1) {
48 free(refs);
49 return;
50 }
51
52 /* Sort the list and filter out duplicates */
53 qsort(refs->ref, refs->count, sizeof(refs->ref[0]),
54 compare_object_pointers);
55 for (i = j = 1; i < refs->count; i++) {
56 if (refs->ref[i] != refs->ref[i - 1])
57 refs->ref[j++] = refs->ref[i];
58 }
59 if (j < refs->count) {
60 /* Duplicates were found - reallocate list */
61 size_t size = sizeof(*refs) + j*sizeof(struct object *);
62 refs->count = j;
63 refs = xrealloc(refs, size);
64 }
65
66 for (i = 0; i < refs->count; i++)
67 refs->ref[i]->used = 1;
68 add_object_refs(obj, refs);
69}
70
71void mark_reachable(struct object *obj, unsigned int mask)
72{
73 const struct object_refs *refs;
74
75 if (!track_object_refs)
76 die("cannot do reachability with object refs turned off");
Linus Torvalds3e4339e2006-06-18 11:45:02 -070077 /* If we've been here already, don't bother */
78 if (obj->flags & mask)
79 return;
80 obj->flags |= mask;
81 refs = lookup_object_refs(obj);
82 if (refs) {
83 unsigned i;
84 for (i = 0; i < refs->count; i++)
85 mark_reachable(refs->ref[i], mask);
86 }
87}