diff options
Diffstat (limited to 'third_party/git/refs/iterator.c')
-rw-r--r-- | third_party/git/refs/iterator.c | 435 |
1 files changed, 0 insertions, 435 deletions
diff --git a/third_party/git/refs/iterator.c b/third_party/git/refs/iterator.c deleted file mode 100644 index 629e00a122a7..000000000000 --- a/third_party/git/refs/iterator.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Generic reference iterator infrastructure. See refs-internal.h for - * documentation about the design and use of reference iterators. - */ - -#include "cache.h" -#include "refs.h" -#include "refs/refs-internal.h" -#include "iterator.h" - -int ref_iterator_advance(struct ref_iterator *ref_iterator) -{ - return ref_iterator->vtable->advance(ref_iterator); -} - -int ref_iterator_peel(struct ref_iterator *ref_iterator, - struct object_id *peeled) -{ - return ref_iterator->vtable->peel(ref_iterator, peeled); -} - -int ref_iterator_abort(struct ref_iterator *ref_iterator) -{ - return ref_iterator->vtable->abort(ref_iterator); -} - -void base_ref_iterator_init(struct ref_iterator *iter, - struct ref_iterator_vtable *vtable, - int ordered) -{ - iter->vtable = vtable; - iter->ordered = !!ordered; - iter->refname = NULL; - iter->oid = NULL; - iter->flags = 0; -} - -void base_ref_iterator_free(struct ref_iterator *iter) -{ - /* Help make use-after-free bugs fail quickly: */ - iter->vtable = NULL; - free(iter); -} - -struct empty_ref_iterator { - struct ref_iterator base; -}; - -static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator) -{ - return ref_iterator_abort(ref_iterator); -} - -static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator, - struct object_id *peeled) -{ - BUG("peel called for empty iterator"); -} - -static int empty_ref_iterator_abort(struct ref_iterator *ref_iterator) -{ - base_ref_iterator_free(ref_iterator); - return ITER_DONE; -} - -static struct ref_iterator_vtable empty_ref_iterator_vtable = { - empty_ref_iterator_advance, - empty_ref_iterator_peel, - empty_ref_iterator_abort -}; - -struct ref_iterator *empty_ref_iterator_begin(void) -{ - struct empty_ref_iterator *iter = xcalloc(1, sizeof(*iter)); - struct ref_iterator *ref_iterator = &iter->base; - - base_ref_iterator_init(ref_iterator, &empty_ref_iterator_vtable, 1); - return ref_iterator; -} - -int is_empty_ref_iterator(struct ref_iterator *ref_iterator) -{ - return ref_iterator->vtable == &empty_ref_iterator_vtable; -} - -struct merge_ref_iterator { - struct ref_iterator base; - - struct ref_iterator *iter0, *iter1; - - ref_iterator_select_fn *select; - void *cb_data; - - /* - * A pointer to iter0 or iter1 (whichever is supplying the - * current value), or NULL if advance has not yet been called. - */ - struct ref_iterator **current; -}; - -static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator) -{ - struct merge_ref_iterator *iter = - (struct merge_ref_iterator *)ref_iterator; - int ok; - - if (!iter->current) { - /* Initialize: advance both iterators to their first entries */ - if ((ok = ref_iterator_advance(iter->iter0)) != ITER_OK) { - iter->iter0 = NULL; - if (ok == ITER_ERROR) - goto error; - } - if ((ok = ref_iterator_advance(iter->iter1)) != ITER_OK) { - iter->iter1 = NULL; - if (ok == ITER_ERROR) - goto error; - } - } else { - /* - * Advance the current iterator past the just-used - * entry: - */ - if ((ok = ref_iterator_advance(*iter->current)) != ITER_OK) { - *iter->current = NULL; - if (ok == ITER_ERROR) - goto error; - } - } - - /* Loop until we find an entry that we can yield. */ - while (1) { - struct ref_iterator **secondary; - enum iterator_selection selection = - iter->select(iter->iter0, iter->iter1, iter->cb_data); - - if (selection == ITER_SELECT_DONE) { - return ref_iterator_abort(ref_iterator); - } else if (selection == ITER_SELECT_ERROR) { - ref_iterator_abort(ref_iterator); - return ITER_ERROR; - } - - if ((selection & ITER_CURRENT_SELECTION_MASK) == 0) { - iter->current = &iter->iter0; - secondary = &iter->iter1; - } else { - iter->current = &iter->iter1; - secondary = &iter->iter0; - } - - if (selection & ITER_SKIP_SECONDARY) { - if ((ok = ref_iterator_advance(*secondary)) != ITER_OK) { - *secondary = NULL; - if (ok == ITER_ERROR) - goto error; - } - } - - if (selection & ITER_YIELD_CURRENT) { - iter->base.refname = (*iter->current)->refname; - iter->base.oid = (*iter->current)->oid; - iter->base.flags = (*iter->current)->flags; - return ITER_OK; - } - } - -error: - ref_iterator_abort(ref_iterator); - return ITER_ERROR; -} - -static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator, - struct object_id *peeled) -{ - struct merge_ref_iterator *iter = - (struct merge_ref_iterator *)ref_iterator; - - if (!iter->current) { - BUG("peel called before advance for merge iterator"); - } - return ref_iterator_peel(*iter->current, peeled); -} - -static int merge_ref_iterator_abort(struct ref_iterator *ref_iterator) -{ - struct merge_ref_iterator *iter = - (struct merge_ref_iterator *)ref_iterator; - int ok = ITER_DONE; - - if (iter->iter0) { - if (ref_iterator_abort(iter->iter0) != ITER_DONE) - ok = ITER_ERROR; - } - if (iter->iter1) { - if (ref_iterator_abort(iter->iter1) != ITER_DONE) - ok = ITER_ERROR; - } - base_ref_iterator_free(ref_iterator); - return ok; -} - -static struct ref_iterator_vtable merge_ref_iterator_vtable = { - merge_ref_iterator_advance, - merge_ref_iterator_peel, - merge_ref_iterator_abort -}; - -struct ref_iterator *merge_ref_iterator_begin( - int ordered, - struct ref_iterator *iter0, struct ref_iterator *iter1, - ref_iterator_select_fn *select, void *cb_data) -{ - struct merge_ref_iterator *iter = xcalloc(1, sizeof(*iter)); - struct ref_iterator *ref_iterator = &iter->base; - - /* - * We can't do the same kind of is_empty_ref_iterator()-style - * optimization here as overlay_ref_iterator_begin() does, - * because we don't know the semantics of the select function. - * It might, for example, implement "intersect" by passing - * references through only if they exist in both iterators. - */ - - base_ref_iterator_init(ref_iterator, &merge_ref_iterator_vtable, ordered); - iter->iter0 = iter0; - iter->iter1 = iter1; - iter->select = select; - iter->cb_data = cb_data; - iter->current = NULL; - return ref_iterator; -} - -/* - * A ref_iterator_select_fn that overlays the items from front on top - * of those from back (like loose refs over packed refs). See - * overlay_ref_iterator_begin(). - */ -static enum iterator_selection overlay_iterator_select( - struct ref_iterator *front, struct ref_iterator *back, - void *cb_data) -{ - int cmp; - - if (!back) - return front ? ITER_SELECT_0 : ITER_SELECT_DONE; - else if (!front) - return ITER_SELECT_1; - - cmp = strcmp(front->refname, back->refname); - - if (cmp < 0) - return ITER_SELECT_0; - else if (cmp > 0) - return ITER_SELECT_1; - else - return ITER_SELECT_0_SKIP_1; -} - -struct ref_iterator *overlay_ref_iterator_begin( - struct ref_iterator *front, struct ref_iterator *back) -{ - /* - * Optimization: if one of the iterators is empty, return the - * other one rather than incurring the overhead of wrapping - * them. - */ - if (is_empty_ref_iterator(front)) { - ref_iterator_abort(front); - return back; - } else if (is_empty_ref_iterator(back)) { - ref_iterator_abort(back); - return front; - } else if (!front->ordered || !back->ordered) { - BUG("overlay_ref_iterator requires ordered inputs"); - } - - return merge_ref_iterator_begin(1, front, back, - overlay_iterator_select, NULL); -} - -struct prefix_ref_iterator { - struct ref_iterator base; - - struct ref_iterator *iter0; - char *prefix; - int trim; -}; - -/* Return -1, 0, 1 if refname is before, inside, or after the prefix. */ -static int compare_prefix(const char *refname, const char *prefix) -{ - while (*prefix) { - if (*refname != *prefix) - return ((unsigned char)*refname < (unsigned char)*prefix) ? -1 : +1; - - refname++; - prefix++; - } - - return 0; -} - -static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator) -{ - struct prefix_ref_iterator *iter = - (struct prefix_ref_iterator *)ref_iterator; - int ok; - - while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) { - int cmp = compare_prefix(iter->iter0->refname, iter->prefix); - - if (cmp < 0) - continue; - - if (cmp > 0) { - /* - * If the source iterator is ordered, then we - * can stop the iteration as soon as we see a - * refname that comes after the prefix: - */ - if (iter->iter0->ordered) { - ok = ref_iterator_abort(iter->iter0); - break; - } else { - continue; - } - } - - if (iter->trim) { - /* - * It is nonsense to trim off characters that - * you haven't already checked for via a - * prefix check, whether via this - * `prefix_ref_iterator` or upstream in - * `iter0`). So if there wouldn't be at least - * one character left in the refname after - * trimming, report it as a bug: - */ - if (strlen(iter->iter0->refname) <= iter->trim) - BUG("attempt to trim too many characters"); - iter->base.refname = iter->iter0->refname + iter->trim; - } else { - iter->base.refname = iter->iter0->refname; - } - - iter->base.oid = iter->iter0->oid; - iter->base.flags = iter->iter0->flags; - return ITER_OK; - } - - iter->iter0 = NULL; - if (ref_iterator_abort(ref_iterator) != ITER_DONE) - return ITER_ERROR; - return ok; -} - -static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator, - struct object_id *peeled) -{ - struct prefix_ref_iterator *iter = - (struct prefix_ref_iterator *)ref_iterator; - - return ref_iterator_peel(iter->iter0, peeled); -} - -static int prefix_ref_iterator_abort(struct ref_iterator *ref_iterator) -{ - struct prefix_ref_iterator *iter = - (struct prefix_ref_iterator *)ref_iterator; - int ok = ITER_DONE; - - if (iter->iter0) - ok = ref_iterator_abort(iter->iter0); - free(iter->prefix); - base_ref_iterator_free(ref_iterator); - return ok; -} - -static struct ref_iterator_vtable prefix_ref_iterator_vtable = { - prefix_ref_iterator_advance, - prefix_ref_iterator_peel, - prefix_ref_iterator_abort -}; - -struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0, - const char *prefix, - int trim) -{ - struct prefix_ref_iterator *iter; - struct ref_iterator *ref_iterator; - - if (!*prefix && !trim) - return iter0; /* optimization: no need to wrap iterator */ - - iter = xcalloc(1, sizeof(*iter)); - ref_iterator = &iter->base; - - base_ref_iterator_init(ref_iterator, &prefix_ref_iterator_vtable, iter0->ordered); - - iter->iter0 = iter0; - iter->prefix = xstrdup(prefix); - iter->trim = trim; - - return ref_iterator; -} - -struct ref_iterator *current_ref_iter = NULL; - -int do_for_each_repo_ref_iterator(struct repository *r, struct ref_iterator *iter, - each_repo_ref_fn fn, void *cb_data) -{ - int retval = 0, ok; - struct ref_iterator *old_ref_iter = current_ref_iter; - - current_ref_iter = iter; - while ((ok = ref_iterator_advance(iter)) == ITER_OK) { - retval = fn(r, iter->refname, iter->oid, iter->flags, cb_data); - if (retval) { - /* - * If ref_iterator_abort() returns ITER_ERROR, - * we ignore that error in deference to the - * callback function's return value. - */ - ref_iterator_abort(iter); - goto out; - } - } - -out: - current_ref_iter = old_ref_iter; - if (ok == ITER_ERROR) - return -1; - return retval; -} |