@@ -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 */
850850static 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+
960992static 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
9851018static 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