@@ -2683,6 +2683,41 @@ static int filter_exclude_match(struct ref_filter *filter, const char *refname)
2683
2683
return match_pattern (filter -> exclude .v , refname , filter -> ignore_case );
2684
2684
}
2685
2685
2686
+ /*
2687
+ * We need to seek to the reference right after a given marker but excluding any
2688
+ * matching references. So we seek to the lexicographically next reference.
2689
+ */
2690
+ static int start_ref_iterator_after (struct ref_iterator * iter , const char * marker )
2691
+ {
2692
+ struct strbuf sb = STRBUF_INIT ;
2693
+ int ret ;
2694
+
2695
+ strbuf_addstr (& sb , marker );
2696
+ strbuf_addch (& sb , 1 );
2697
+
2698
+ ret = ref_iterator_seek (iter , sb .buf , 0 );
2699
+
2700
+ strbuf_release (& sb );
2701
+ return ret ;
2702
+ }
2703
+
2704
+ static int for_each_fullref_with_seek (struct ref_filter * filter , each_ref_fn cb ,
2705
+ void * cb_data , unsigned int flags )
2706
+ {
2707
+ struct ref_iterator * iter ;
2708
+ int ret = 0 ;
2709
+
2710
+ iter = refs_ref_iterator_begin (get_main_ref_store (the_repository ), "" ,
2711
+ NULL , 0 , flags );
2712
+ if (filter -> start_after )
2713
+ ret = start_ref_iterator_after (iter , filter -> start_after );
2714
+
2715
+ if (ret )
2716
+ return ret ;
2717
+
2718
+ return do_for_each_ref_iterator (iter , cb , cb_data );
2719
+ }
2720
+
2686
2721
/*
2687
2722
* This is the same as for_each_fullref_in(), but it tries to iterate
2688
2723
* only over the patterns we'll care about. Note that it _doesn't_ do a full
@@ -2694,8 +2729,8 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
2694
2729
{
2695
2730
if (filter -> kind & FILTER_REFS_ROOT_REFS ) {
2696
2731
/* In this case, we want to print all refs including root refs. */
2697
- return refs_for_each_include_root_refs ( get_main_ref_store ( the_repository ) ,
2698
- cb , cb_data );
2732
+ return for_each_fullref_with_seek ( filter , cb , cb_data ,
2733
+ DO_FOR_EACH_INCLUDE_ROOT_REFS );
2699
2734
}
2700
2735
2701
2736
if (!filter -> match_as_path ) {
@@ -2704,8 +2739,7 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
2704
2739
* prefixes like "refs/heads/" etc. are stripped off,
2705
2740
* so we have to look at everything:
2706
2741
*/
2707
- return refs_for_each_fullref_in (get_main_ref_store (the_repository ),
2708
- "" , NULL , cb , cb_data );
2742
+ return for_each_fullref_with_seek (filter , cb , cb_data , 0 );
2709
2743
}
2710
2744
2711
2745
if (filter -> ignore_case ) {
@@ -2714,14 +2748,12 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
2714
2748
* so just return everything and let the caller
2715
2749
* sort it out.
2716
2750
*/
2717
- return refs_for_each_fullref_in (get_main_ref_store (the_repository ),
2718
- "" , NULL , cb , cb_data );
2751
+ return for_each_fullref_with_seek (filter , cb , cb_data , 0 );
2719
2752
}
2720
2753
2721
2754
if (!filter -> name_patterns [0 ]) {
2722
2755
/* no patterns; we have to look at everything */
2723
- return refs_for_each_fullref_in (get_main_ref_store (the_repository ),
2724
- "" , filter -> exclude .v , cb , cb_data );
2756
+ return for_each_fullref_with_seek (filter , cb , cb_data , 0 );
2725
2757
}
2726
2758
2727
2759
return refs_for_each_fullref_in_prefixes (get_main_ref_store (the_repository ),
@@ -3189,6 +3221,7 @@ void filter_is_base(struct repository *r,
3189
3221
3190
3222
static int do_filter_refs (struct ref_filter * filter , unsigned int type , each_ref_fn fn , void * cb_data )
3191
3223
{
3224
+ const char * prefix = NULL ;
3192
3225
int ret = 0 ;
3193
3226
3194
3227
filter -> kind = type & FILTER_REFS_KIND_MASK ;
@@ -3199,38 +3232,47 @@ static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref
3199
3232
/* Simple per-ref filtering */
3200
3233
if (!filter -> kind )
3201
3234
die ("filter_refs: invalid type" );
3202
- else {
3203
- /*
3204
- * For common cases where we need only branches or remotes or tags,
3205
- * we only iterate through those refs. If a mix of refs is needed,
3206
- * we iterate over all refs and filter out required refs with the help
3207
- * of filter_ref_kind().
3208
- */
3209
- if (filter -> kind == FILTER_REFS_BRANCHES )
3210
- ret = refs_for_each_fullref_in (get_main_ref_store (the_repository ),
3211
- "refs/heads/" , NULL ,
3212
- fn , cb_data );
3213
- else if (filter -> kind == FILTER_REFS_REMOTES )
3214
- ret = refs_for_each_fullref_in (get_main_ref_store (the_repository ),
3215
- "refs/remotes/" , NULL ,
3216
- fn , cb_data );
3217
- else if (filter -> kind == FILTER_REFS_TAGS )
3218
- ret = refs_for_each_fullref_in (get_main_ref_store (the_repository ),
3219
- "refs/tags/" , NULL , fn ,
3220
- cb_data );
3221
- else if (filter -> kind & FILTER_REFS_REGULAR )
3222
- ret = for_each_fullref_in_pattern (filter , fn , cb_data );
3223
3235
3224
- /*
3225
- * When printing all ref types, HEAD is already included,
3226
- * so we don't want to print HEAD again.
3227
- */
3228
- if (!ret && !(filter -> kind & FILTER_REFS_ROOT_REFS ) &&
3229
- (filter -> kind & FILTER_REFS_DETACHED_HEAD ))
3230
- refs_head_ref (get_main_ref_store (the_repository ), fn ,
3231
- cb_data );
3236
+ /*
3237
+ * For common cases where we need only branches or remotes or tags,
3238
+ * we only iterate through those refs. If a mix of refs is needed,
3239
+ * we iterate over all refs and filter out required refs with the help
3240
+ * of filter_ref_kind().
3241
+ */
3242
+ if (filter -> kind == FILTER_REFS_BRANCHES )
3243
+ prefix = "refs/heads/" ;
3244
+ else if (filter -> kind == FILTER_REFS_REMOTES )
3245
+ prefix = "refs/remotes/" ;
3246
+ else if (filter -> kind == FILTER_REFS_TAGS )
3247
+ prefix = "refs/tags/" ;
3248
+
3249
+ if (prefix ) {
3250
+ struct ref_iterator * iter ;
3251
+
3252
+ iter = refs_ref_iterator_begin (get_main_ref_store (the_repository ),
3253
+ "" , NULL , 0 , 0 );
3254
+
3255
+ if (filter -> start_after )
3256
+ ret = start_ref_iterator_after (iter , filter -> start_after );
3257
+ else if (prefix )
3258
+ ret = ref_iterator_seek (iter , prefix , 1 );
3259
+
3260
+ if (!ret )
3261
+ ret = do_for_each_ref_iterator (iter , fn , cb_data );
3262
+ } else if (filter -> kind & FILTER_REFS_REGULAR ) {
3263
+ ret = for_each_fullref_in_pattern (filter , fn , cb_data );
3232
3264
}
3233
3265
3266
+ /*
3267
+ * When printing all ref types, HEAD is already included,
3268
+ * so we don't want to print HEAD again.
3269
+ */
3270
+ if (!ret && !(filter -> kind & FILTER_REFS_ROOT_REFS ) &&
3271
+ (filter -> kind & FILTER_REFS_DETACHED_HEAD ))
3272
+ refs_head_ref (get_main_ref_store (the_repository ), fn ,
3273
+ cb_data );
3274
+
3275
+
3234
3276
clear_contains_cache (& filter -> internal .contains_cache );
3235
3277
clear_contains_cache (& filter -> internal .no_contains_cache );
3236
3278
0 commit comments