Skip to content

Commit 22600c0

Browse files
pks-tgitster
authored andcommitted
refs/iterator: implement seeking for packed-ref iterators
Implement seeking of `packed-ref` iterators. The implementation is again straight forward, except that we cannot continue to use the prefix iterator as we would otherwise not be able to reseek the iterator anymore in case one first asks for an empty and then for a non-empty prefix. Instead, we open-code the logic to in `advance()`. Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 84e6569 commit 22600c0

File tree

1 file changed

+43
-22
lines changed

1 file changed

+43
-22
lines changed

refs/packed-backend.c

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,8 @@ struct packed_ref_iterator {
819819

820820
struct snapshot *snapshot;
821821

822+
char *prefix;
823+
822824
/* The current position in the snapshot's buffer: */
823825
const char *pos;
824826

@@ -841,11 +843,9 @@ struct packed_ref_iterator {
841843
};
842844

843845
/*
844-
* Move the iterator to the next record in the snapshot, without
845-
* respect for whether the record is actually required by the current
846-
* iteration. Adjust the fields in `iter` and return `ITER_OK` or
847-
* `ITER_DONE`. This function does not free the iterator in the case
848-
* of `ITER_DONE`.
846+
* Move the iterator to the next record in the snapshot. Adjust the fields in
847+
* `iter` and return `ITER_OK` or `ITER_DONE`. This function does not free the
848+
* iterator in the case of `ITER_DONE`.
849849
*/
850850
static int next_record(struct packed_ref_iterator *iter)
851851
{
@@ -942,6 +942,9 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
942942
int ok;
943943

944944
while ((ok = next_record(iter)) == ITER_OK) {
945+
const char *refname = iter->base.refname;
946+
const char *prefix = iter->prefix;
947+
945948
if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
946949
!is_per_worktree_ref(iter->base.refname))
947950
continue;
@@ -951,12 +954,41 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
951954
&iter->oid, iter->flags))
952955
continue;
953956

957+
while (prefix && *prefix) {
958+
if (*refname < *prefix)
959+
BUG("packed-refs backend yielded reference preceding its prefix");
960+
else if (*refname > *prefix)
961+
return ITER_DONE;
962+
prefix++;
963+
refname++;
964+
}
965+
954966
return ITER_OK;
955967
}
956968

957969
return ok;
958970
}
959971

972+
static int packed_ref_iterator_seek(struct ref_iterator *ref_iterator,
973+
const char *prefix)
974+
{
975+
struct packed_ref_iterator *iter =
976+
(struct packed_ref_iterator *)ref_iterator;
977+
const char *start;
978+
979+
if (prefix && *prefix)
980+
start = find_reference_location(iter->snapshot, prefix, 0);
981+
else
982+
start = iter->snapshot->start;
983+
984+
free(iter->prefix);
985+
iter->prefix = xstrdup_or_null(prefix);
986+
iter->pos = start;
987+
iter->eof = iter->snapshot->eof;
988+
989+
return 0;
990+
}
991+
960992
static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator,
961993
struct object_id *peeled)
962994
{
@@ -979,11 +1011,13 @@ static void packed_ref_iterator_release(struct ref_iterator *ref_iterator)
9791011
(struct packed_ref_iterator *)ref_iterator;
9801012
strbuf_release(&iter->refname_buf);
9811013
free(iter->jump);
1014+
free(iter->prefix);
9821015
release_snapshot(iter->snapshot);
9831016
}
9841017

9851018
static struct ref_iterator_vtable packed_ref_iterator_vtable = {
9861019
.advance = packed_ref_iterator_advance,
1020+
.seek = packed_ref_iterator_seek,
9871021
.peel = packed_ref_iterator_peel,
9881022
.release = packed_ref_iterator_release,
9891023
};
@@ -1097,7 +1131,6 @@ static struct ref_iterator *packed_ref_iterator_begin(
10971131
{
10981132
struct packed_ref_store *refs;
10991133
struct snapshot *snapshot;
1100-
const char *start;
11011134
struct packed_ref_iterator *iter;
11021135
struct ref_iterator *ref_iterator;
11031136
unsigned int required_flags = REF_STORE_READ;
@@ -1113,14 +1146,6 @@ static struct ref_iterator *packed_ref_iterator_begin(
11131146
*/
11141147
snapshot = get_snapshot(refs);
11151148

1116-
if (prefix && *prefix)
1117-
start = find_reference_location(snapshot, prefix, 0);
1118-
else
1119-
start = snapshot->start;
1120-
1121-
if (start == snapshot->eof)
1122-
return empty_ref_iterator_begin();
1123-
11241149
CALLOC_ARRAY(iter, 1);
11251150
ref_iterator = &iter->base;
11261151
base_ref_iterator_init(ref_iterator, &packed_ref_iterator_vtable);
@@ -1130,19 +1155,15 @@ static struct ref_iterator *packed_ref_iterator_begin(
11301155

11311156
iter->snapshot = snapshot;
11321157
acquire_snapshot(snapshot);
1133-
1134-
iter->pos = start;
1135-
iter->eof = snapshot->eof;
11361158
strbuf_init(&iter->refname_buf, 0);
1137-
11381159
iter->base.oid = &iter->oid;
1139-
11401160
iter->repo = ref_store->repo;
11411161
iter->flags = flags;
11421162

1143-
if (prefix && *prefix)
1144-
/* Stop iteration after we've gone *past* prefix: */
1145-
ref_iterator = prefix_ref_iterator_begin(ref_iterator, prefix, 0);
1163+
if (packed_ref_iterator_seek(&iter->base, prefix) < 0) {
1164+
ref_iterator_free(&iter->base);
1165+
return NULL;
1166+
}
11461167

11471168
return ref_iterator;
11481169
}

0 commit comments

Comments
 (0)