@@ -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 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
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;
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> --- refs/iterator.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-)