2 * Generic reference iterator infrastructure. See refs-internal.h for
3 * documentation about the design and use of reference iterators.
8 #include "refs/refs-internal.h"
11 int ref_iterator_advance(struct ref_iterator *ref_iterator)
13 return ref_iterator->vtable->advance(ref_iterator);
16 int ref_iterator_peel(struct ref_iterator *ref_iterator,
17 struct object_id *peeled)
19 return ref_iterator->vtable->peel(ref_iterator, peeled);
22 int ref_iterator_abort(struct ref_iterator *ref_iterator)
24 return ref_iterator->vtable->abort(ref_iterator);
27 void base_ref_iterator_init(struct ref_iterator *iter,
28 struct ref_iterator_vtable *vtable)
30 iter->vtable = vtable;
36 void base_ref_iterator_free(struct ref_iterator *iter)
38 /* Help make use-after-free bugs fail quickly: */
43 struct empty_ref_iterator {
44 struct ref_iterator base;
47 static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator)
49 return ref_iterator_abort(ref_iterator);
52 static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator,
53 struct object_id *peeled)
55 die("BUG: peel called for empty iterator");
58 static int empty_ref_iterator_abort(struct ref_iterator *ref_iterator)
60 base_ref_iterator_free(ref_iterator);
64 static struct ref_iterator_vtable empty_ref_iterator_vtable = {
65 empty_ref_iterator_advance,
66 empty_ref_iterator_peel,
67 empty_ref_iterator_abort
70 struct ref_iterator *empty_ref_iterator_begin(void)
72 struct empty_ref_iterator *iter = xcalloc(1, sizeof(*iter));
73 struct ref_iterator *ref_iterator = &iter->base;
75 base_ref_iterator_init(ref_iterator, &empty_ref_iterator_vtable);
79 int is_empty_ref_iterator(struct ref_iterator *ref_iterator)
81 return ref_iterator->vtable == &empty_ref_iterator_vtable;
84 struct merge_ref_iterator {
85 struct ref_iterator base;
87 struct ref_iterator *iter0, *iter1;
89 ref_iterator_select_fn *select;
93 * A pointer to iter0 or iter1 (whichever is supplying the
94 * current value), or NULL if advance has not yet been called.
96 struct ref_iterator **current;
99 static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
101 struct merge_ref_iterator *iter =
102 (struct merge_ref_iterator *)ref_iterator;
105 if (!iter->current) {
106 /* Initialize: advance both iterators to their first entries */
107 if ((ok = ref_iterator_advance(iter->iter0)) != ITER_OK) {
109 if (ok == ITER_ERROR)
112 if ((ok = ref_iterator_advance(iter->iter1)) != ITER_OK) {
114 if (ok == ITER_ERROR)
119 * Advance the current iterator past the just-used
122 if ((ok = ref_iterator_advance(*iter->current)) != ITER_OK) {
123 *iter->current = NULL;
124 if (ok == ITER_ERROR)
129 /* Loop until we find an entry that we can yield. */
131 struct ref_iterator **secondary;
132 enum iterator_selection selection =
133 iter->select(iter->iter0, iter->iter1, iter->cb_data);
135 if (selection == ITER_SELECT_DONE) {
136 return ref_iterator_abort(ref_iterator);
137 } else if (selection == ITER_SELECT_ERROR) {
138 ref_iterator_abort(ref_iterator);
142 if ((selection & ITER_CURRENT_SELECTION_MASK) == 0) {
143 iter->current = &iter->iter0;
144 secondary = &iter->iter1;
146 iter->current = &iter->iter1;
147 secondary = &iter->iter0;
150 if (selection & ITER_SKIP_SECONDARY) {
151 if ((ok = ref_iterator_advance(*secondary)) != ITER_OK) {
153 if (ok == ITER_ERROR)
158 if (selection & ITER_YIELD_CURRENT) {
159 iter->base.refname = (*iter->current)->refname;
160 iter->base.oid = (*iter->current)->oid;
161 iter->base.flags = (*iter->current)->flags;
167 ref_iterator_abort(ref_iterator);
171 static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator,
172 struct object_id *peeled)
174 struct merge_ref_iterator *iter =
175 (struct merge_ref_iterator *)ref_iterator;
177 if (!iter->current) {
178 die("BUG: peel called before advance for merge iterator");
180 return ref_iterator_peel(*iter->current, peeled);
183 static int merge_ref_iterator_abort(struct ref_iterator *ref_iterator)
185 struct merge_ref_iterator *iter =
186 (struct merge_ref_iterator *)ref_iterator;
190 if (ref_iterator_abort(iter->iter0) != ITER_DONE)
194 if (ref_iterator_abort(iter->iter1) != ITER_DONE)
197 base_ref_iterator_free(ref_iterator);
201 static struct ref_iterator_vtable merge_ref_iterator_vtable = {
202 merge_ref_iterator_advance,
203 merge_ref_iterator_peel,
204 merge_ref_iterator_abort
207 struct ref_iterator *merge_ref_iterator_begin(
208 struct ref_iterator *iter0, struct ref_iterator *iter1,
209 ref_iterator_select_fn *select, void *cb_data)
211 struct merge_ref_iterator *iter = xcalloc(1, sizeof(*iter));
212 struct ref_iterator *ref_iterator = &iter->base;
215 * We can't do the same kind of is_empty_ref_iterator()-style
216 * optimization here as overlay_ref_iterator_begin() does,
217 * because we don't know the semantics of the select function.
218 * It might, for example, implement "intersect" by passing
219 * references through only if they exist in both iterators.
222 base_ref_iterator_init(ref_iterator, &merge_ref_iterator_vtable);
225 iter->select = select;
226 iter->cb_data = cb_data;
227 iter->current = NULL;
232 * A ref_iterator_select_fn that overlays the items from front on top
233 * of those from back (like loose refs over packed refs). See
234 * overlay_ref_iterator_begin().
236 static enum iterator_selection overlay_iterator_select(
237 struct ref_iterator *front, struct ref_iterator *back,
243 return front ? ITER_SELECT_0 : ITER_SELECT_DONE;
245 return ITER_SELECT_1;
247 cmp = strcmp(front->refname, back->refname);
250 return ITER_SELECT_0;
252 return ITER_SELECT_1;
254 return ITER_SELECT_0_SKIP_1;
257 struct ref_iterator *overlay_ref_iterator_begin(
258 struct ref_iterator *front, struct ref_iterator *back)
261 * Optimization: if one of the iterators is empty, return the
262 * other one rather than incurring the overhead of wrapping
265 if (is_empty_ref_iterator(front)) {
266 ref_iterator_abort(front);
268 } else if (is_empty_ref_iterator(back)) {
269 ref_iterator_abort(back);
273 return merge_ref_iterator_begin(front, back,
274 overlay_iterator_select, NULL);
277 struct prefix_ref_iterator {
278 struct ref_iterator base;
280 struct ref_iterator *iter0;
285 static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
287 struct prefix_ref_iterator *iter =
288 (struct prefix_ref_iterator *)ref_iterator;
291 while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
292 if (!starts_with(iter->iter0->refname, iter->prefix))
295 iter->base.refname = iter->iter0->refname + iter->trim;
296 iter->base.oid = iter->iter0->oid;
297 iter->base.flags = iter->iter0->flags;
302 if (ref_iterator_abort(ref_iterator) != ITER_DONE)
307 static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator,
308 struct object_id *peeled)
310 struct prefix_ref_iterator *iter =
311 (struct prefix_ref_iterator *)ref_iterator;
313 return ref_iterator_peel(iter->iter0, peeled);
316 static int prefix_ref_iterator_abort(struct ref_iterator *ref_iterator)
318 struct prefix_ref_iterator *iter =
319 (struct prefix_ref_iterator *)ref_iterator;
323 ok = ref_iterator_abort(iter->iter0);
325 base_ref_iterator_free(ref_iterator);
329 static struct ref_iterator_vtable prefix_ref_iterator_vtable = {
330 prefix_ref_iterator_advance,
331 prefix_ref_iterator_peel,
332 prefix_ref_iterator_abort
335 struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
339 struct prefix_ref_iterator *iter;
340 struct ref_iterator *ref_iterator;
342 if (!*prefix && !trim)
343 return iter0; /* optimization: no need to wrap iterator */
345 iter = xcalloc(1, sizeof(*iter));
346 ref_iterator = &iter->base;
348 base_ref_iterator_init(ref_iterator, &prefix_ref_iterator_vtable);
351 iter->prefix = xstrdup(prefix);
357 struct ref_iterator *current_ref_iter = NULL;
359 int do_for_each_ref_iterator(struct ref_iterator *iter,
360 each_ref_fn fn, void *cb_data)
363 struct ref_iterator *old_ref_iter = current_ref_iter;
365 current_ref_iter = iter;
366 while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
367 retval = fn(iter->refname, iter->oid, iter->flags, cb_data);
370 * If ref_iterator_abort() returns ITER_ERROR,
371 * we ignore that error in deference to the
372 * callback function's return value.
374 ref_iterator_abort(iter);
380 current_ref_iter = old_ref_iter;
381 if (ok == ITER_ERROR)