]>
Commit | Line | Data |
---|---|---|
3e4339e6 LT |
1 | #include "cache.h" |
2 | #include "object.h" | |
a59b276e | 3 | #include "decorate.h" |
3e4339e6 LT |
4 | |
5 | int track_object_refs = 0; | |
6 | ||
a59b276e | 7 | static struct decoration ref_decorate; |
3e4339e6 | 8 | |
a59b276e | 9 | struct object_refs *lookup_object_refs(struct object *base) |
3e4339e6 | 10 | { |
a59b276e | 11 | return lookup_decoration(&ref_decorate, base); |
3e4339e6 LT |
12 | } |
13 | ||
a59b276e | 14 | static void add_object_refs(struct object *obj, struct object_refs *refs) |
5fdc8499 | 15 | { |
a59b276e LT |
16 | if (add_decoration(&ref_decorate, obj, refs)) |
17 | die("object %s tried to add refs twice!", sha1_to_hex(obj->sha1)); | |
3e4339e6 LT |
18 | } |
19 | ||
20 | struct 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 | ||
30 | static 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 | ||
42 | void 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 | ||
71 | void 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"); | |
77 | /* 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 | } | |
88 | ||
89 |