reachable: use traverse_commit_list instead of custom walk

To find the set of reachable objects, we add a bunch of possible sources to our rev_info, call prepare_revision_walk, and then launch into a custom walker that handles each object top. This is a subset of what traverse_commit_list does, so we can just reuse that code (it can also handle more complex cases like UNINTERESTING commits and pathspecs, but we don't use those features). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Oct 15, 2014 at 18:37 UTC 5f78a431ab222189b11a9233a5902db61aa32976
1 file changed +17 -113
reachable.c
+17 -113
@@ -8,6 +8,7 @@
8 #include "reachable.h"
9 #include "cache-tree.h"
10 #include "progress.h"
11 +#include "list-objects.h"
12
13 struct connectivity_progress {
14 struct progress *progress;
@@ -21,118 +22,6 @@ static void update_progress(struct connectivity_progress *cp)
22 display_progress(cp->progress, cp->count);
23 }
24
24 -static void process_blob(struct blob *blob,
25 - struct object_array *p,
26 - struct name_path *path,
27 - const char *name,
28 - struct connectivity_progress *cp)
29 -{
30 - struct object *obj = &blob->object;
31 -
32 - if (!blob)
33 - die("bad blob object");
34 - if (obj->flags & SEEN)
35 - return;
36 - obj->flags |= SEEN;
37 - update_progress(cp);
38 - /* Nothing to do, really .. The blob lookup was the important part */
39 -}
40 -
41 -static void process_gitlink(const unsigned char *sha1,
42 - struct object_array *p,
43 - struct name_path *path,
44 - const char *name)
45 -{
46 - /* I don't think we want to recurse into this, really. */
47 -}
48 -
49 -static void process_tree(struct tree *tree,
50 - struct object_array *p,
51 - struct name_path *path,
52 - const char *name,
53 - struct connectivity_progress *cp)
54 -{
55 - struct object *obj = &tree->object;
56 - struct tree_desc desc;
57 - struct name_entry entry;
58 - struct name_path me;
59 -
60 - if (!tree)
61 - die("bad tree object");
62 - if (obj->flags & SEEN)
63 - return;
64 - obj->flags |= SEEN;
65 - update_progress(cp);
66 - if (parse_tree(tree) < 0)
67 - die("bad tree object %s", sha1_to_hex(obj->sha1));
68 - add_object(obj, p, path, name);
69 - me.up = path;
70 - me.elem = name;
71 - me.elem_len = strlen(name);
72 -
73 - init_tree_desc(&desc, tree->buffer, tree->size);
74 -
75 - while (tree_entry(&desc, &entry)) {
76 - if (S_ISDIR(entry.mode))
77 - process_tree(lookup_tree(entry.sha1), p, &me, entry.path, cp);
78 - else if (S_ISGITLINK(entry.mode))
79 - process_gitlink(entry.sha1, p, &me, entry.path);
80 - else
81 - process_blob(lookup_blob(entry.sha1), p, &me, entry.path, cp);
82 - }
83 - free_tree_buffer(tree);
84 -}
85 -
86 -static void process_tag(struct tag *tag, struct object_array *p,
87 - const char *name, struct connectivity_progress *cp)
88 -{
89 - struct object *obj = &tag->object;
90 -
91 - if (obj->flags & SEEN)
92 - return;
93 - obj->flags |= SEEN;
94 - update_progress(cp);
95 -
96 - if (parse_tag(tag) < 0)
97 - die("bad tag object %s", sha1_to_hex(obj->sha1));
98 - if (tag->tagged)
99 - add_object(tag->tagged, p, NULL, name);
100 -}
101 -
102 -static void walk_commit_list(struct rev_info *revs,
103 - struct connectivity_progress *cp)
104 -{
105 - int i;
106 - struct commit *commit;
107 - struct object_array objects = OBJECT_ARRAY_INIT;
108 -
109 - /* Walk all commits, process their trees */
110 - while ((commit = get_revision(revs)) != NULL) {
111 - process_tree(commit->tree, &objects, NULL, "", cp);
112 - update_progress(cp);
113 - }
114 -
115 - /* Then walk all the pending objects, recursively processing them too */
116 - for (i = 0; i < revs->pending.nr; i++) {
117 - struct object_array_entry *pending = revs->pending.objects + i;
118 - struct object *obj = pending->item;
119 - const char *name = pending->name;
120 - if (obj->type == OBJ_TAG) {
121 - process_tag((struct tag *) obj, &objects, name, cp);
122 - continue;
123 - }
124 - if (obj->type == OBJ_TREE) {
125 - process_tree((struct tree *)obj, &objects, NULL, name, cp);
126 - continue;
127 - }
128 - if (obj->type == OBJ_BLOB) {
129 - process_blob((struct blob *)obj, &objects, NULL, name, cp);
130 - continue;
131 - }
132 - die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name);
133 - }
134 -}
135 -
25 static int add_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
26 const char *email, unsigned long timestamp, int tz,
27 const char *message, void *cb_data)
@@ -210,6 +99,21 @@ static void add_cache_refs(struct rev_info *revs)
99 add_cache_tree(active_cache_tree, revs);
100 }
101
102 +/*
103 + * The traversal will have already marked us as SEEN, so we
104 + * only need to handle any progress reporting here.
105 + */
106 +static void mark_object(struct object *obj, const struct name_path *path,
107 + const char *name, void *data)
108 +{
109 + update_progress(data);
110 +}
111 +
112 +static void mark_commit(struct commit *c, void *data)
113 +{
114 + mark_object(&c->object, NULL, NULL, data);
115 +}
116 +
117 void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
118 struct progress *progress)
119 {
@@ -245,6 +149,6 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
149 */
150 if (prepare_revision_walk(revs))
151 die("revision walk setup failed");
248 - walk_commit_list(revs, &cp);
152 + traverse_commit_list(revs, mark_commit, mark_object, &cp);
153 display_progress(cp.progress, cp.count);
154 }