refs/iterator: implement seeking for merged iterators
Implement seeking on merged iterators. The implementation is rather straight forward, with the only exception that we must not deallocate the underlying iterators once they have been exhausted. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>main
parent
82c39c6055
commit
9821d90f13
|
@ -96,7 +96,8 @@ int is_empty_ref_iterator(struct ref_iterator *ref_iterator)
|
|||
struct merge_ref_iterator {
|
||||
struct ref_iterator base;
|
||||
|
||||
struct ref_iterator *iter0, *iter1;
|
||||
struct ref_iterator *iter0, *iter0_owned;
|
||||
struct ref_iterator *iter1, *iter1_owned;
|
||||
|
||||
ref_iterator_select_fn *select;
|
||||
void *cb_data;
|
||||
|
@ -160,13 +161,11 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
if (!iter->current) {
|
||||
/* Initialize: advance both iterators to their first entries */
|
||||
if ((ok = ref_iterator_advance(iter->iter0)) != ITER_OK) {
|
||||
ref_iterator_free(iter->iter0);
|
||||
iter->iter0 = NULL;
|
||||
if (ok == ITER_ERROR)
|
||||
goto error;
|
||||
}
|
||||
if ((ok = ref_iterator_advance(iter->iter1)) != ITER_OK) {
|
||||
ref_iterator_free(iter->iter1);
|
||||
iter->iter1 = NULL;
|
||||
if (ok == ITER_ERROR)
|
||||
goto error;
|
||||
|
@ -177,7 +176,6 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
* entry:
|
||||
*/
|
||||
if ((ok = ref_iterator_advance(*iter->current)) != ITER_OK) {
|
||||
ref_iterator_free(*iter->current);
|
||||
*iter->current = NULL;
|
||||
if (ok == ITER_ERROR)
|
||||
goto error;
|
||||
|
@ -206,7 +204,6 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
|
||||
if (selection & ITER_SKIP_SECONDARY) {
|
||||
if ((ok = ref_iterator_advance(*secondary)) != ITER_OK) {
|
||||
ref_iterator_free(*secondary);
|
||||
*secondary = NULL;
|
||||
if (ok == ITER_ERROR)
|
||||
goto error;
|
||||
|
@ -226,6 +223,28 @@ error:
|
|||
return ITER_ERROR;
|
||||
}
|
||||
|
||||
static int merge_ref_iterator_seek(struct ref_iterator *ref_iterator,
|
||||
const char *prefix)
|
||||
{
|
||||
struct merge_ref_iterator *iter =
|
||||
(struct merge_ref_iterator *)ref_iterator;
|
||||
int ret;
|
||||
|
||||
iter->current = NULL;
|
||||
iter->iter0 = iter->iter0_owned;
|
||||
iter->iter1 = iter->iter1_owned;
|
||||
|
||||
ret = ref_iterator_seek(iter->iter0, prefix);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ref_iterator_seek(iter->iter1, prefix);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
||||
struct object_id *peeled)
|
||||
{
|
||||
|
@ -242,12 +261,13 @@ static void merge_ref_iterator_release(struct ref_iterator *ref_iterator)
|
|||
{
|
||||
struct merge_ref_iterator *iter =
|
||||
(struct merge_ref_iterator *)ref_iterator;
|
||||
ref_iterator_free(iter->iter0);
|
||||
ref_iterator_free(iter->iter1);
|
||||
ref_iterator_free(iter->iter0_owned);
|
||||
ref_iterator_free(iter->iter1_owned);
|
||||
}
|
||||
|
||||
static struct ref_iterator_vtable merge_ref_iterator_vtable = {
|
||||
.advance = merge_ref_iterator_advance,
|
||||
.seek = merge_ref_iterator_seek,
|
||||
.peel = merge_ref_iterator_peel,
|
||||
.release = merge_ref_iterator_release,
|
||||
};
|
||||
|
@ -268,8 +288,8 @@ struct ref_iterator *merge_ref_iterator_begin(
|
|||
*/
|
||||
|
||||
base_ref_iterator_init(ref_iterator, &merge_ref_iterator_vtable);
|
||||
iter->iter0 = iter0;
|
||||
iter->iter1 = iter1;
|
||||
iter->iter0 = iter->iter0_owned = iter0;
|
||||
iter->iter1 = iter->iter1_owned = iter1;
|
||||
iter->select = select;
|
||||
iter->cb_data = cb_data;
|
||||
iter->current = NULL;
|
||||
|
|
Loading…
Reference in New Issue