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;
32
iter->referent = NULL;
37
void base_ref_iterator_free(struct ref_iterator *iter)
44
struct empty_ref_iterator {
45
struct ref_iterator base;
48
static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator)
50
return ref_iterator_abort(ref_iterator);
53
static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
54
struct object_id *peeled UNUSED)
56
BUG("peel called for empty iterator");
59
static int empty_ref_iterator_abort(struct ref_iterator *ref_iterator)
61
base_ref_iterator_free(ref_iterator);
65
static struct ref_iterator_vtable empty_ref_iterator_vtable = {
66
.advance = empty_ref_iterator_advance,
67
.peel = empty_ref_iterator_peel,
68
.abort = empty_ref_iterator_abort,
71
struct ref_iterator *empty_ref_iterator_begin(void)
73
struct empty_ref_iterator *iter = xcalloc(1, sizeof(*iter));
74
struct ref_iterator *ref_iterator = &iter->base;
76
base_ref_iterator_init(ref_iterator, &empty_ref_iterator_vtable);
80
int is_empty_ref_iterator(struct ref_iterator *ref_iterator)
82
return ref_iterator->vtable == &empty_ref_iterator_vtable;
85
struct merge_ref_iterator {
86
struct ref_iterator base;
88
struct ref_iterator *iter0, *iter1;
90
ref_iterator_select_fn *select;
97
struct ref_iterator **current;
100
enum iterator_selection ref_iterator_select(struct ref_iterator *iter_worktree,
101
struct ref_iterator *iter_common,
102
void *cb_data UNUSED)
104
if (iter_worktree && !iter_common) {
108
return ITER_SELECT_0;
109
} else if (iter_common) {
117
int cmp = strcmp(iter_worktree->refname,
118
iter_common->refname);
120
return ITER_SELECT_0;
122
return ITER_SELECT_0_SKIP_1;
129
if (parse_worktree_ref(iter_common->refname, NULL, NULL,
130
NULL) == REF_WORKTREE_SHARED)
131
return ITER_SELECT_1;
143
static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
145
struct merge_ref_iterator *iter =
146
(struct merge_ref_iterator *)ref_iterator;
149
if (!iter->current) {
151
if ((ok = ref_iterator_advance(iter->iter0)) != ITER_OK) {
153
if (ok == ITER_ERROR)
156
if ((ok = ref_iterator_advance(iter->iter1)) != ITER_OK) {
158
if (ok == ITER_ERROR)
166
if ((ok = ref_iterator_advance(*iter->current)) != ITER_OK) {
167
*iter->current = NULL;
168
if (ok == ITER_ERROR)
175
struct ref_iterator **secondary;
176
enum iterator_selection selection =
177
iter->select(iter->iter0, iter->iter1, iter->cb_data);
179
if (selection == ITER_SELECT_DONE) {
180
return ref_iterator_abort(ref_iterator);
181
} else if (selection == ITER_SELECT_ERROR) {
182
ref_iterator_abort(ref_iterator);
186
if ((selection & ITER_CURRENT_SELECTION_MASK) == 0) {
187
iter->current = &iter->iter0;
188
secondary = &iter->iter1;
190
iter->current = &iter->iter1;
191
secondary = &iter->iter0;
194
if (selection & ITER_SKIP_SECONDARY) {
195
if ((ok = ref_iterator_advance(*secondary)) != ITER_OK) {
197
if (ok == ITER_ERROR)
202
if (selection & ITER_YIELD_CURRENT) {
203
iter->base.referent = (*iter->current)->referent;
204
iter->base.refname = (*iter->current)->refname;
205
iter->base.oid = (*iter->current)->oid;
206
iter->base.flags = (*iter->current)->flags;
212
ref_iterator_abort(ref_iterator);
216
static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator,
217
struct object_id *peeled)
219
struct merge_ref_iterator *iter =
220
(struct merge_ref_iterator *)ref_iterator;
222
if (!iter->current) {
223
BUG("peel called before advance for merge iterator");
225
return ref_iterator_peel(*iter->current, peeled);
228
static int merge_ref_iterator_abort(struct ref_iterator *ref_iterator)
230
struct merge_ref_iterator *iter =
231
(struct merge_ref_iterator *)ref_iterator;
235
if (ref_iterator_abort(iter->iter0) != ITER_DONE)
239
if (ref_iterator_abort(iter->iter1) != ITER_DONE)
242
base_ref_iterator_free(ref_iterator);
246
static struct ref_iterator_vtable merge_ref_iterator_vtable = {
247
.advance = merge_ref_iterator_advance,
248
.peel = merge_ref_iterator_peel,
249
.abort = merge_ref_iterator_abort,
252
struct ref_iterator *merge_ref_iterator_begin(
253
struct ref_iterator *iter0, struct ref_iterator *iter1,
254
ref_iterator_select_fn *select, void *cb_data)
256
struct merge_ref_iterator *iter = xcalloc(1, sizeof(*iter));
257
struct ref_iterator *ref_iterator = &iter->base;
267
base_ref_iterator_init(ref_iterator, &merge_ref_iterator_vtable);
270
iter->select = select;
271
iter->cb_data = cb_data;
272
iter->current = NULL;
281
static enum iterator_selection overlay_iterator_select(
282
struct ref_iterator *front, struct ref_iterator *back,
283
void *cb_data UNUSED)
288
return front ? ITER_SELECT_0 : ITER_SELECT_DONE;
290
return ITER_SELECT_1;
292
cmp = strcmp(front->refname, back->refname);
295
return ITER_SELECT_0;
297
return ITER_SELECT_1;
299
return ITER_SELECT_0_SKIP_1;
302
struct ref_iterator *overlay_ref_iterator_begin(
303
struct ref_iterator *front, struct ref_iterator *back)
310
if (is_empty_ref_iterator(front)) {
311
ref_iterator_abort(front);
313
} else if (is_empty_ref_iterator(back)) {
314
ref_iterator_abort(back);
318
return merge_ref_iterator_begin(front, back, overlay_iterator_select, NULL);
321
struct prefix_ref_iterator {
322
struct ref_iterator base;
324
struct ref_iterator *iter0;
330
static int compare_prefix(const char *refname, const char *prefix)
333
if (*refname != *prefix)
334
return ((unsigned char)*refname < (unsigned char)*prefix) ? -1 : +1;
343
static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
345
struct prefix_ref_iterator *iter =
346
(struct prefix_ref_iterator *)ref_iterator;
349
while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
350
int cmp = compare_prefix(iter->iter0->refname, iter->prefix);
361
ok = ref_iterator_abort(iter->iter0);
375
if (strlen(iter->iter0->refname) <= iter->trim)
376
BUG("attempt to trim too many characters");
377
iter->base.refname = iter->iter0->refname + iter->trim;
379
iter->base.refname = iter->iter0->refname;
382
iter->base.oid = iter->iter0->oid;
383
iter->base.flags = iter->iter0->flags;
388
if (ref_iterator_abort(ref_iterator) != ITER_DONE)
393
static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator,
394
struct object_id *peeled)
396
struct prefix_ref_iterator *iter =
397
(struct prefix_ref_iterator *)ref_iterator;
399
return ref_iterator_peel(iter->iter0, peeled);
402
static int prefix_ref_iterator_abort(struct ref_iterator *ref_iterator)
404
struct prefix_ref_iterator *iter =
405
(struct prefix_ref_iterator *)ref_iterator;
409
ok = ref_iterator_abort(iter->iter0);
411
base_ref_iterator_free(ref_iterator);
415
static struct ref_iterator_vtable prefix_ref_iterator_vtable = {
416
.advance = prefix_ref_iterator_advance,
417
.peel = prefix_ref_iterator_peel,
418
.abort = prefix_ref_iterator_abort,
421
struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
425
struct prefix_ref_iterator *iter;
426
struct ref_iterator *ref_iterator;
428
if (!*prefix && !trim)
431
CALLOC_ARRAY(iter, 1);
432
ref_iterator = &iter->base;
434
base_ref_iterator_init(ref_iterator, &prefix_ref_iterator_vtable);
437
iter->prefix = xstrdup(prefix);
443
struct ref_iterator *current_ref_iter = NULL;
445
int do_for_each_ref_iterator(struct ref_iterator *iter,
446
each_ref_fn fn, void *cb_data)
449
struct ref_iterator *old_ref_iter = current_ref_iter;
451
current_ref_iter = iter;
452
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
453
retval = fn(iter->refname, iter->referent, iter->oid, iter->flags, cb_data);
460
ref_iterator_abort(iter);
466
current_ref_iter = old_ref_iter;
467
if (ok == ITER_ERROR)