Skip to content

Commit 523ee2d

Browse files
mhaggergitster
authored andcommitted
mmapped_ref_iterator: inline into packed_ref_iterator
Since `packed_ref_iterator` is now delegating to `mmapped_ref_iterator` rather than `cache_ref_iterator` to do the heavy lifting, there is no need to keep the two iterators separate. So "inline" `mmapped_ref_iterator` into `packed_ref_iterator`. This removes a bunch of boilerplate. Signed-off-by: Michael Haggerty <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent a6e19bc commit 523ee2d

File tree

1 file changed

+114
-170
lines changed

1 file changed

+114
-170
lines changed

refs/packed-backend.c

Lines changed: 114 additions & 170 deletions
Original file line numberDiff line numberDiff line change
@@ -225,157 +225,6 @@ static NORETURN void die_invalid_line(const char *path,
225225

226226
}
227227

228-
/*
229-
* This value is set in `base.flags` if the peeled value of the
230-
* current reference is known. In that case, `peeled` contains the
231-
* correct peeled value for the reference, which might be `null_sha1`
232-
* if the reference is not a tag or if it is broken.
233-
*/
234-
#define REF_KNOWS_PEELED 0x40
235-
236-
/*
237-
* An iterator over a packed-refs file that is currently mmapped.
238-
*/
239-
struct mmapped_ref_iterator {
240-
struct ref_iterator base;
241-
242-
struct packed_ref_cache *packed_refs;
243-
244-
/* The current position in the mmapped file: */
245-
const char *pos;
246-
247-
/* The end of the mmapped file: */
248-
const char *eof;
249-
250-
struct object_id oid, peeled;
251-
252-
struct strbuf refname_buf;
253-
};
254-
255-
static int mmapped_ref_iterator_advance(struct ref_iterator *ref_iterator)
256-
{
257-
struct mmapped_ref_iterator *iter =
258-
(struct mmapped_ref_iterator *)ref_iterator;
259-
const char *p = iter->pos, *eol;
260-
261-
strbuf_reset(&iter->refname_buf);
262-
263-
if (iter->pos == iter->eof)
264-
return ref_iterator_abort(ref_iterator);
265-
266-
iter->base.flags = REF_ISPACKED;
267-
268-
if (iter->eof - p < GIT_SHA1_HEXSZ + 2 ||
269-
parse_oid_hex(p, &iter->oid, &p) ||
270-
!isspace(*p++))
271-
die_invalid_line(iter->packed_refs->refs->path,
272-
iter->pos, iter->eof - iter->pos);
273-
274-
eol = memchr(p, '\n', iter->eof - p);
275-
if (!eol)
276-
die_unterminated_line(iter->packed_refs->refs->path,
277-
iter->pos, iter->eof - iter->pos);
278-
279-
strbuf_add(&iter->refname_buf, p, eol - p);
280-
iter->base.refname = iter->refname_buf.buf;
281-
282-
if (check_refname_format(iter->base.refname, REFNAME_ALLOW_ONELEVEL)) {
283-
if (!refname_is_safe(iter->base.refname))
284-
die("packed refname is dangerous: %s",
285-
iter->base.refname);
286-
oidclr(&iter->oid);
287-
iter->base.flags |= REF_BAD_NAME | REF_ISBROKEN;
288-
}
289-
if (iter->packed_refs->peeled == PEELED_FULLY ||
290-
(iter->packed_refs->peeled == PEELED_TAGS &&
291-
starts_with(iter->base.refname, "refs/tags/")))
292-
iter->base.flags |= REF_KNOWS_PEELED;
293-
294-
iter->pos = eol + 1;
295-
296-
if (iter->pos < iter->eof && *iter->pos == '^') {
297-
p = iter->pos + 1;
298-
if (iter->eof - p < GIT_SHA1_HEXSZ + 1 ||
299-
parse_oid_hex(p, &iter->peeled, &p) ||
300-
*p++ != '\n')
301-
die_invalid_line(iter->packed_refs->refs->path,
302-
iter->pos, iter->eof - iter->pos);
303-
iter->pos = p;
304-
305-
/*
306-
* Regardless of what the file header said, we
307-
* definitely know the value of *this* reference. But
308-
* we suppress it if the reference is broken:
309-
*/
310-
if ((iter->base.flags & REF_ISBROKEN)) {
311-
oidclr(&iter->peeled);
312-
iter->base.flags &= ~REF_KNOWS_PEELED;
313-
} else {
314-
iter->base.flags |= REF_KNOWS_PEELED;
315-
}
316-
} else {
317-
oidclr(&iter->peeled);
318-
}
319-
320-
return ITER_OK;
321-
}
322-
323-
static int mmapped_ref_iterator_peel(struct ref_iterator *ref_iterator,
324-
struct object_id *peeled)
325-
{
326-
struct mmapped_ref_iterator *iter =
327-
(struct mmapped_ref_iterator *)ref_iterator;
328-
329-
if ((iter->base.flags & REF_KNOWS_PEELED)) {
330-
oidcpy(peeled, &iter->peeled);
331-
return is_null_oid(&iter->peeled) ? -1 : 0;
332-
} else if ((iter->base.flags & (REF_ISBROKEN | REF_ISSYMREF))) {
333-
return -1;
334-
} else {
335-
return !!peel_object(iter->oid.hash, peeled->hash);
336-
}
337-
}
338-
339-
static int mmapped_ref_iterator_abort(struct ref_iterator *ref_iterator)
340-
{
341-
struct mmapped_ref_iterator *iter =
342-
(struct mmapped_ref_iterator *)ref_iterator;
343-
344-
release_packed_ref_cache(iter->packed_refs);
345-
strbuf_release(&iter->refname_buf);
346-
base_ref_iterator_free(ref_iterator);
347-
return ITER_DONE;
348-
}
349-
350-
static struct ref_iterator_vtable mmapped_ref_iterator_vtable = {
351-
mmapped_ref_iterator_advance,
352-
mmapped_ref_iterator_peel,
353-
mmapped_ref_iterator_abort
354-
};
355-
356-
struct ref_iterator *mmapped_ref_iterator_begin(
357-
struct packed_ref_cache *packed_refs,
358-
const char *pos, const char *eof)
359-
{
360-
struct mmapped_ref_iterator *iter = xcalloc(1, sizeof(*iter));
361-
struct ref_iterator *ref_iterator = &iter->base;
362-
363-
if (!packed_refs->buf)
364-
return empty_ref_iterator_begin();
365-
366-
base_ref_iterator_init(ref_iterator, &mmapped_ref_iterator_vtable, 1);
367-
368-
iter->packed_refs = packed_refs;
369-
acquire_packed_ref_cache(iter->packed_refs);
370-
iter->pos = pos;
371-
iter->eof = eof;
372-
strbuf_init(&iter->refname_buf, 0);
373-
374-
iter->base.oid = &iter->oid;
375-
376-
return ref_iterator;
377-
}
378-
379228
struct packed_ref_entry {
380229
const char *start;
381230
size_t len;
@@ -858,38 +707,120 @@ static int packed_read_raw_ref(struct ref_store *ref_store,
858707
return 0;
859708
}
860709

710+
/*
711+
* This value is set in `base.flags` if the peeled value of the
712+
* current reference is known. In that case, `peeled` contains the
713+
* correct peeled value for the reference, which might be `null_sha1`
714+
* if the reference is not a tag or if it is broken.
715+
*/
716+
#define REF_KNOWS_PEELED 0x40
717+
718+
/*
719+
* An iterator over a packed-refs file that is currently mmapped.
720+
*/
861721
struct packed_ref_iterator {
862722
struct ref_iterator base;
863723

864-
struct packed_ref_cache *cache;
865-
struct ref_iterator *iter0;
724+
struct packed_ref_cache *packed_refs;
725+
726+
/* The current position in the mmapped file: */
727+
const char *pos;
728+
729+
/* The end of the mmapped file: */
730+
const char *eof;
731+
732+
struct object_id oid, peeled;
733+
734+
struct strbuf refname_buf;
735+
866736
unsigned int flags;
867737
};
868738

739+
static int next_record(struct packed_ref_iterator *iter)
740+
{
741+
const char *p = iter->pos, *eol;
742+
743+
strbuf_reset(&iter->refname_buf);
744+
745+
if (iter->pos == iter->eof)
746+
return ITER_DONE;
747+
748+
iter->base.flags = REF_ISPACKED;
749+
750+
if (iter->eof - p < GIT_SHA1_HEXSZ + 2 ||
751+
parse_oid_hex(p, &iter->oid, &p) ||
752+
!isspace(*p++))
753+
die_invalid_line(iter->packed_refs->refs->path,
754+
iter->pos, iter->eof - iter->pos);
755+
756+
eol = memchr(p, '\n', iter->eof - p);
757+
if (!eol)
758+
die_unterminated_line(iter->packed_refs->refs->path,
759+
iter->pos, iter->eof - iter->pos);
760+
761+
strbuf_add(&iter->refname_buf, p, eol - p);
762+
iter->base.refname = iter->refname_buf.buf;
763+
764+
if (check_refname_format(iter->base.refname, REFNAME_ALLOW_ONELEVEL)) {
765+
if (!refname_is_safe(iter->base.refname))
766+
die("packed refname is dangerous: %s",
767+
iter->base.refname);
768+
oidclr(&iter->oid);
769+
iter->base.flags |= REF_BAD_NAME | REF_ISBROKEN;
770+
}
771+
if (iter->packed_refs->peeled == PEELED_FULLY ||
772+
(iter->packed_refs->peeled == PEELED_TAGS &&
773+
starts_with(iter->base.refname, "refs/tags/")))
774+
iter->base.flags |= REF_KNOWS_PEELED;
775+
776+
iter->pos = eol + 1;
777+
778+
if (iter->pos < iter->eof && *iter->pos == '^') {
779+
p = iter->pos + 1;
780+
if (iter->eof - p < GIT_SHA1_HEXSZ + 1 ||
781+
parse_oid_hex(p, &iter->peeled, &p) ||
782+
*p++ != '\n')
783+
die_invalid_line(iter->packed_refs->refs->path,
784+
iter->pos, iter->eof - iter->pos);
785+
iter->pos = p;
786+
787+
/*
788+
* Regardless of what the file header said, we
789+
* definitely know the value of *this* reference. But
790+
* we suppress it if the reference is broken:
791+
*/
792+
if ((iter->base.flags & REF_ISBROKEN)) {
793+
oidclr(&iter->peeled);
794+
iter->base.flags &= ~REF_KNOWS_PEELED;
795+
} else {
796+
iter->base.flags |= REF_KNOWS_PEELED;
797+
}
798+
} else {
799+
oidclr(&iter->peeled);
800+
}
801+
802+
return ITER_OK;
803+
}
804+
869805
static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
870806
{
871807
struct packed_ref_iterator *iter =
872808
(struct packed_ref_iterator *)ref_iterator;
873809
int ok;
874810

875-
while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
811+
while ((ok = next_record(iter)) == ITER_OK) {
876812
if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
877-
ref_type(iter->iter0->refname) != REF_TYPE_PER_WORKTREE)
813+
ref_type(iter->base.refname) != REF_TYPE_PER_WORKTREE)
878814
continue;
879815

880816
if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
881-
!ref_resolves_to_object(iter->iter0->refname,
882-
iter->iter0->oid,
883-
iter->iter0->flags))
817+
!ref_resolves_to_object(iter->base.refname, &iter->oid,
818+
iter->flags))
884819
continue;
885820

886-
iter->base.refname = iter->iter0->refname;
887-
iter->base.oid = iter->iter0->oid;
888-
iter->base.flags = iter->iter0->flags;
889821
return ITER_OK;
890822
}
891823

892-
iter->iter0 = NULL;
893824
if (ref_iterator_abort(ref_iterator) != ITER_DONE)
894825
ok = ITER_ERROR;
895826

@@ -902,7 +833,14 @@ static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator,
902833
struct packed_ref_iterator *iter =
903834
(struct packed_ref_iterator *)ref_iterator;
904835

905-
return ref_iterator_peel(iter->iter0, peeled);
836+
if ((iter->base.flags & REF_KNOWS_PEELED)) {
837+
oidcpy(peeled, &iter->peeled);
838+
return is_null_oid(&iter->peeled) ? -1 : 0;
839+
} else if ((iter->base.flags & (REF_ISBROKEN | REF_ISSYMREF))) {
840+
return -1;
841+
} else {
842+
return !!peel_object(iter->oid.hash, peeled->hash);
843+
}
906844
}
907845

908846
static int packed_ref_iterator_abort(struct ref_iterator *ref_iterator)
@@ -911,10 +849,8 @@ static int packed_ref_iterator_abort(struct ref_iterator *ref_iterator)
911849
(struct packed_ref_iterator *)ref_iterator;
912850
int ok = ITER_DONE;
913851

914-
if (iter->iter0)
915-
ok = ref_iterator_abort(iter->iter0);
916-
917-
release_packed_ref_cache(iter->cache);
852+
strbuf_release(&iter->refname_buf);
853+
release_packed_ref_cache(iter->packed_refs);
918854
base_ref_iterator_free(ref_iterator);
919855
return ok;
920856
}
@@ -940,6 +876,11 @@ static struct ref_iterator *packed_ref_iterator_begin(
940876
required_flags |= REF_STORE_ODB;
941877
refs = packed_downcast(ref_store, required_flags, "ref_iterator_begin");
942878

879+
packed_refs = get_packed_ref_cache(refs);
880+
881+
if (!packed_refs->buf)
882+
return empty_ref_iterator_begin();
883+
943884
iter = xcalloc(1, sizeof(*iter));
944885
ref_iterator = &iter->base;
945886
base_ref_iterator_init(ref_iterator, &packed_ref_iterator_vtable, 1);
@@ -949,16 +890,19 @@ static struct ref_iterator *packed_ref_iterator_begin(
949890
* the packed-ref cache is up to date with what is on disk,
950891
* and re-reads it if not.
951892
*/
952-
iter->cache = packed_refs = get_packed_ref_cache(refs);
893+
iter->packed_refs = packed_refs;
953894
acquire_packed_ref_cache(packed_refs);
954895

955896
if (prefix && *prefix)
956897
start = find_reference_location(packed_refs, prefix, 0);
957898
else
958899
start = packed_refs->buf + packed_refs->header_len;
959900

960-
iter->iter0 = mmapped_ref_iterator_begin(packed_refs,
961-
start, packed_refs->eof);
901+
iter->pos = start;
902+
iter->eof = packed_refs->eof;
903+
strbuf_init(&iter->refname_buf, 0);
904+
905+
iter->base.oid = &iter->oid;
962906

963907
iter->flags = flags;
964908

0 commit comments

Comments
 (0)