2 * Generic reference iterator infrastructure. See refs-internal.h for
3 * documentation about the design and use of reference iterators.
6 #include "git-compat-util.h"
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 UNUSED
,
53 struct object_id
*peeled UNUSED
)
55 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 .advance
= empty_ref_iterator_advance
,
66 .peel
= empty_ref_iterator_peel
,
67 .abort
= 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 enum iterator_selection
ref_iterator_select(struct ref_iterator
*iter_worktree
,
100 struct ref_iterator
*iter_common
,
101 void *cb_data UNUSED
)
103 if (iter_worktree
&& !iter_common
) {
105 * Return the worktree ref if there are no more common refs.
107 return ITER_SELECT_0
;
108 } else if (iter_common
) {
110 * In case we have pending worktree and common refs we need to
111 * yield them based on their lexicographical order. Worktree
112 * refs that have the same name as common refs shadow the
116 int cmp
= strcmp(iter_worktree
->refname
,
117 iter_common
->refname
);
119 return ITER_SELECT_0
;
121 return ITER_SELECT_0_SKIP_1
;
125 * We now know that the lexicographically-next ref is a common
126 * ref. When the common ref is a shared one we return it.
128 if (parse_worktree_ref(iter_common
->refname
, NULL
, NULL
,
129 NULL
) == REF_WORKTREE_SHARED
)
130 return ITER_SELECT_1
;
133 * Otherwise, if the common ref is a per-worktree ref we skip
134 * it because it would belong to the main worktree, not ours.
142 static int merge_ref_iterator_advance(struct ref_iterator
*ref_iterator
)
144 struct merge_ref_iterator
*iter
=
145 (struct merge_ref_iterator
*)ref_iterator
;
148 if (!iter
->current
) {
149 /* Initialize: advance both iterators to their first entries */
150 if ((ok
= ref_iterator_advance(iter
->iter0
)) != ITER_OK
) {
152 if (ok
== ITER_ERROR
)
155 if ((ok
= ref_iterator_advance(iter
->iter1
)) != ITER_OK
) {
157 if (ok
== ITER_ERROR
)
162 * Advance the current iterator past the just-used
165 if ((ok
= ref_iterator_advance(*iter
->current
)) != ITER_OK
) {
166 *iter
->current
= NULL
;
167 if (ok
== ITER_ERROR
)
172 /* Loop until we find an entry that we can yield. */
174 struct ref_iterator
**secondary
;
175 enum iterator_selection selection
=
176 iter
->select(iter
->iter0
, iter
->iter1
, iter
->cb_data
);
178 if (selection
== ITER_SELECT_DONE
) {
179 return ref_iterator_abort(ref_iterator
);
180 } else if (selection
== ITER_SELECT_ERROR
) {
181 ref_iterator_abort(ref_iterator
);
185 if ((selection
& ITER_CURRENT_SELECTION_MASK
) == 0) {
186 iter
->current
= &iter
->iter0
;
187 secondary
= &iter
->iter1
;
189 iter
->current
= &iter
->iter1
;
190 secondary
= &iter
->iter0
;
193 if (selection
& ITER_SKIP_SECONDARY
) {
194 if ((ok
= ref_iterator_advance(*secondary
)) != ITER_OK
) {
196 if (ok
== ITER_ERROR
)
201 if (selection
& ITER_YIELD_CURRENT
) {
202 iter
->base
.refname
= (*iter
->current
)->refname
;
203 iter
->base
.oid
= (*iter
->current
)->oid
;
204 iter
->base
.flags
= (*iter
->current
)->flags
;
210 ref_iterator_abort(ref_iterator
);
214 static int merge_ref_iterator_peel(struct ref_iterator
*ref_iterator
,
215 struct object_id
*peeled
)
217 struct merge_ref_iterator
*iter
=
218 (struct merge_ref_iterator
*)ref_iterator
;
220 if (!iter
->current
) {
221 BUG("peel called before advance for merge iterator");
223 return ref_iterator_peel(*iter
->current
, peeled
);
226 static int merge_ref_iterator_abort(struct ref_iterator
*ref_iterator
)
228 struct merge_ref_iterator
*iter
=
229 (struct merge_ref_iterator
*)ref_iterator
;
233 if (ref_iterator_abort(iter
->iter0
) != ITER_DONE
)
237 if (ref_iterator_abort(iter
->iter1
) != ITER_DONE
)
240 base_ref_iterator_free(ref_iterator
);
244 static struct ref_iterator_vtable merge_ref_iterator_vtable
= {
245 .advance
= merge_ref_iterator_advance
,
246 .peel
= merge_ref_iterator_peel
,
247 .abort
= merge_ref_iterator_abort
,
250 struct ref_iterator
*merge_ref_iterator_begin(
251 struct ref_iterator
*iter0
, struct ref_iterator
*iter1
,
252 ref_iterator_select_fn
*select
, void *cb_data
)
254 struct merge_ref_iterator
*iter
= xcalloc(1, sizeof(*iter
));
255 struct ref_iterator
*ref_iterator
= &iter
->base
;
258 * We can't do the same kind of is_empty_ref_iterator()-style
259 * optimization here as overlay_ref_iterator_begin() does,
260 * because we don't know the semantics of the select function.
261 * It might, for example, implement "intersect" by passing
262 * references through only if they exist in both iterators.
265 base_ref_iterator_init(ref_iterator
, &merge_ref_iterator_vtable
);
268 iter
->select
= select
;
269 iter
->cb_data
= cb_data
;
270 iter
->current
= NULL
;
275 * A ref_iterator_select_fn that overlays the items from front on top
276 * of those from back (like loose refs over packed refs). See
277 * overlay_ref_iterator_begin().
279 static enum iterator_selection
overlay_iterator_select(
280 struct ref_iterator
*front
, struct ref_iterator
*back
,
281 void *cb_data UNUSED
)
286 return front
? ITER_SELECT_0
: ITER_SELECT_DONE
;
288 return ITER_SELECT_1
;
290 cmp
= strcmp(front
->refname
, back
->refname
);
293 return ITER_SELECT_0
;
295 return ITER_SELECT_1
;
297 return ITER_SELECT_0_SKIP_1
;
300 struct ref_iterator
*overlay_ref_iterator_begin(
301 struct ref_iterator
*front
, struct ref_iterator
*back
)
304 * Optimization: if one of the iterators is empty, return the
305 * other one rather than incurring the overhead of wrapping
308 if (is_empty_ref_iterator(front
)) {
309 ref_iterator_abort(front
);
311 } else if (is_empty_ref_iterator(back
)) {
312 ref_iterator_abort(back
);
316 return merge_ref_iterator_begin(front
, back
, overlay_iterator_select
, NULL
);
319 struct prefix_ref_iterator
{
320 struct ref_iterator base
;
322 struct ref_iterator
*iter0
;
327 /* Return -1, 0, 1 if refname is before, inside, or after the prefix. */
328 static int compare_prefix(const char *refname
, const char *prefix
)
331 if (*refname
!= *prefix
)
332 return ((unsigned char)*refname
< (unsigned char)*prefix
) ? -1 : +1;
341 static int prefix_ref_iterator_advance(struct ref_iterator
*ref_iterator
)
343 struct prefix_ref_iterator
*iter
=
344 (struct prefix_ref_iterator
*)ref_iterator
;
347 while ((ok
= ref_iterator_advance(iter
->iter0
)) == ITER_OK
) {
348 int cmp
= compare_prefix(iter
->iter0
->refname
, iter
->prefix
);
355 * As the source iterator is ordered, we
356 * can stop the iteration as soon as we see a
357 * refname that comes after the prefix:
359 ok
= ref_iterator_abort(iter
->iter0
);
365 * It is nonsense to trim off characters that
366 * you haven't already checked for via a
367 * prefix check, whether via this
368 * `prefix_ref_iterator` or upstream in
369 * `iter0`). So if there wouldn't be at least
370 * one character left in the refname after
371 * trimming, report it as a bug:
373 if (strlen(iter
->iter0
->refname
) <= iter
->trim
)
374 BUG("attempt to trim too many characters");
375 iter
->base
.refname
= iter
->iter0
->refname
+ iter
->trim
;
377 iter
->base
.refname
= iter
->iter0
->refname
;
380 iter
->base
.oid
= iter
->iter0
->oid
;
381 iter
->base
.flags
= iter
->iter0
->flags
;
386 if (ref_iterator_abort(ref_iterator
) != ITER_DONE
)
391 static int prefix_ref_iterator_peel(struct ref_iterator
*ref_iterator
,
392 struct object_id
*peeled
)
394 struct prefix_ref_iterator
*iter
=
395 (struct prefix_ref_iterator
*)ref_iterator
;
397 return ref_iterator_peel(iter
->iter0
, peeled
);
400 static int prefix_ref_iterator_abort(struct ref_iterator
*ref_iterator
)
402 struct prefix_ref_iterator
*iter
=
403 (struct prefix_ref_iterator
*)ref_iterator
;
407 ok
= ref_iterator_abort(iter
->iter0
);
409 base_ref_iterator_free(ref_iterator
);
413 static struct ref_iterator_vtable prefix_ref_iterator_vtable
= {
414 .advance
= prefix_ref_iterator_advance
,
415 .peel
= prefix_ref_iterator_peel
,
416 .abort
= prefix_ref_iterator_abort
,
419 struct ref_iterator
*prefix_ref_iterator_begin(struct ref_iterator
*iter0
,
423 struct prefix_ref_iterator
*iter
;
424 struct ref_iterator
*ref_iterator
;
426 if (!*prefix
&& !trim
)
427 return iter0
; /* optimization: no need to wrap iterator */
429 CALLOC_ARRAY(iter
, 1);
430 ref_iterator
= &iter
->base
;
432 base_ref_iterator_init(ref_iterator
, &prefix_ref_iterator_vtable
);
435 iter
->prefix
= xstrdup(prefix
);
441 struct ref_iterator
*current_ref_iter
= NULL
;
443 int do_for_each_repo_ref_iterator(struct repository
*r
, struct ref_iterator
*iter
,
444 each_repo_ref_fn fn
, void *cb_data
)
447 struct ref_iterator
*old_ref_iter
= current_ref_iter
;
449 current_ref_iter
= iter
;
450 while ((ok
= ref_iterator_advance(iter
)) == ITER_OK
) {
451 retval
= fn(r
, iter
->refname
, iter
->oid
, iter
->flags
, cb_data
);
454 * If ref_iterator_abort() returns ITER_ERROR,
455 * we ignore that error in deference to the
456 * callback function's return value.
458 ref_iterator_abort(iter
);
464 current_ref_iter
= old_ref_iter
;
465 if (ok
== ITER_ERROR
)