@@ -819,6 +819,8 @@ struct packed_ref_iterator {
819
819
820
820
struct snapshot * snapshot ;
821
821
822
+ char * prefix ;
823
+
822
824
/* The current position in the snapshot's buffer: */
823
825
const char * pos ;
824
826
@@ -841,11 +843,9 @@ struct packed_ref_iterator {
841
843
};
842
844
843
845
/*
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`.
849
849
*/
850
850
static int next_record (struct packed_ref_iterator * iter )
851
851
{
@@ -942,6 +942,9 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
942
942
int ok ;
943
943
944
944
while ((ok = next_record (iter )) == ITER_OK ) {
945
+ const char * refname = iter -> base .refname ;
946
+ const char * prefix = iter -> prefix ;
947
+
945
948
if (iter -> flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
946
949
!is_per_worktree_ref (iter -> base .refname ))
947
950
continue ;
@@ -951,12 +954,41 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
951
954
& iter -> oid , iter -> flags ))
952
955
continue ;
953
956
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
+
954
966
return ITER_OK ;
955
967
}
956
968
957
969
return ok ;
958
970
}
959
971
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
+
960
992
static int packed_ref_iterator_peel (struct ref_iterator * ref_iterator ,
961
993
struct object_id * peeled )
962
994
{
@@ -979,11 +1011,13 @@ static void packed_ref_iterator_release(struct ref_iterator *ref_iterator)
979
1011
(struct packed_ref_iterator * )ref_iterator ;
980
1012
strbuf_release (& iter -> refname_buf );
981
1013
free (iter -> jump );
1014
+ free (iter -> prefix );
982
1015
release_snapshot (iter -> snapshot );
983
1016
}
984
1017
985
1018
static struct ref_iterator_vtable packed_ref_iterator_vtable = {
986
1019
.advance = packed_ref_iterator_advance ,
1020
+ .seek = packed_ref_iterator_seek ,
987
1021
.peel = packed_ref_iterator_peel ,
988
1022
.release = packed_ref_iterator_release ,
989
1023
};
@@ -1097,7 +1131,6 @@ static struct ref_iterator *packed_ref_iterator_begin(
1097
1131
{
1098
1132
struct packed_ref_store * refs ;
1099
1133
struct snapshot * snapshot ;
1100
- const char * start ;
1101
1134
struct packed_ref_iterator * iter ;
1102
1135
struct ref_iterator * ref_iterator ;
1103
1136
unsigned int required_flags = REF_STORE_READ ;
@@ -1113,14 +1146,6 @@ static struct ref_iterator *packed_ref_iterator_begin(
1113
1146
*/
1114
1147
snapshot = get_snapshot (refs );
1115
1148
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
-
1124
1149
CALLOC_ARRAY (iter , 1 );
1125
1150
ref_iterator = & iter -> base ;
1126
1151
base_ref_iterator_init (ref_iterator , & packed_ref_iterator_vtable );
@@ -1130,19 +1155,15 @@ static struct ref_iterator *packed_ref_iterator_begin(
1130
1155
1131
1156
iter -> snapshot = snapshot ;
1132
1157
acquire_snapshot (snapshot );
1133
-
1134
- iter -> pos = start ;
1135
- iter -> eof = snapshot -> eof ;
1136
1158
strbuf_init (& iter -> refname_buf , 0 );
1137
-
1138
1159
iter -> base .oid = & iter -> oid ;
1139
-
1140
1160
iter -> repo = ref_store -> repo ;
1141
1161
iter -> flags = flags ;
1142
1162
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
+ }
1146
1167
1147
1168
return ref_iterator ;
1148
1169
}
0 commit comments