ref-filter.c: refactor to create common helper functions

Factor out parts of 'ref_array_push()', 'ref_filter_handler()', and 'filter_refs()' into new helper functions: * Extract the code to grow a 'struct ref_array' and append a given 'struct ref_array_item *' to it from 'ref_array_push()' into 'ref_array_append()'. * Extract the code to filter a given ref by refname & object ID then create a new 'struct ref_array_item *' from 'filter_one()' into 'apply_ref_filter()'. * Extract the code for filter pre-processing, contains cache creation, and ref iteration from 'filter_refs()' into 'do_filter_refs()'. In later patches, these helpers will be used by new ref-filter API functions. This patch does not result in any user-facing behavior changes or changes to callers outside of 'ref-filter.c'. Signed-off-by: Victoria Dye <vdye@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Victoria Dye committed Nov 14, 2023 at 19:53 UTC 613d9915499ed9d1fd21d743002d17ef972e9e57
1 file changed +69 -46
ref-filter.c
+69 -46
@@ -2632,15 +2632,18 @@ static struct ref_array_item *new_ref_array_item(const char *refname,
2632 return ref;
2633 }
2634
2635 +static void ref_array_append(struct ref_array *array, struct ref_array_item *ref)
2636 +{
2637 + ALLOC_GROW(array->items, array->nr + 1, array->alloc);
2638 + array->items[array->nr++] = ref;
2639 +}
2640 +
2641 struct ref_array_item *ref_array_push(struct ref_array *array,
2642 const char *refname,
2643 const struct object_id *oid)
2644 {
2645 struct ref_array_item *ref = new_ref_array_item(refname, oid);
2640 -
2641 - ALLOC_GROW(array->items, array->nr + 1, array->alloc);
2642 - array->items[array->nr++] = ref;
2643 -
2646 + ref_array_append(array, ref);
2647 return ref;
2648 }
2649
@@ -2677,46 +2680,36 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname)
2680 return ref_kind_from_refname(refname);
2681 }
2682
2680 -struct ref_filter_cbdata {
2681 - struct ref_array *array;
2682 - struct ref_filter *filter;
2683 -};
2684 -
2685 -/*
2686 - * A call-back given to for_each_ref(). Filter refs and keep them for
2687 - * later object processing.
2688 - */
2689 -static int filter_one(const char *refname, const struct object_id *oid, int flag, void *cb_data)
2683 +static struct ref_array_item *apply_ref_filter(const char *refname, const struct object_id *oid,
2684 + int flag, struct ref_filter *filter)
2685 {
2691 - struct ref_filter_cbdata *ref_cbdata = cb_data;
2692 - struct ref_filter *filter = ref_cbdata->filter;
2686 struct ref_array_item *ref;
2687 struct commit *commit = NULL;
2688 unsigned int kind;
2689
2690 if (flag & REF_BAD_NAME) {
2691 warning(_("ignoring ref with broken name %s"), refname);
2699 - return 0;
2692 + return NULL;
2693 }
2694
2695 if (flag & REF_ISBROKEN) {
2696 warning(_("ignoring broken ref %s"), refname);
2704 - return 0;
2697 + return NULL;
2698 }
2699
2700 /* Obtain the current ref kind from filter_ref_kind() and ignore unwanted refs. */
2701 kind = filter_ref_kind(filter, refname);
2702 if (!(kind & filter->kind))
2710 - return 0;
2703 + return NULL;
2704
2705 if (!filter_pattern_match(filter, refname))
2713 - return 0;
2706 + return NULL;
2707
2708 if (filter_exclude_match(filter, refname))
2716 - return 0;
2709 + return NULL;
2710
2711 if (filter->points_at.nr && !match_points_at(&filter->points_at, oid, refname))
2719 - return 0;
2712 + return NULL;
2713
2714 /*
2715 * A merge filter is applied on refs pointing to commits. Hence
@@ -2727,15 +2720,15 @@ static int filter_one(const char *refname, const struct object_id *oid, int flag
2720 filter->with_commit || filter->no_commit || filter->verbose) {
2721 commit = lookup_commit_reference_gently(the_repository, oid, 1);
2722 if (!commit)
2730 - return 0;
2723 + return NULL;
2724 /* We perform the filtering for the '--contains' option... */
2725 if (filter->with_commit &&
2726 !commit_contains(filter, commit, filter->with_commit, &filter->internal.contains_cache))
2734 - return 0;
2727 + return NULL;
2728 /* ...or for the `--no-contains' option */
2729 if (filter->no_commit &&
2730 commit_contains(filter, commit, filter->no_commit, &filter->internal.no_contains_cache))
2738 - return 0;
2731 + return NULL;
2732 }
2733
2734 /*
@@ -2743,11 +2736,32 @@ static int filter_one(const char *refname, const struct object_id *oid, int flag
2736 * to do its job and the resulting list may yet to be pruned
2737 * by maxcount logic.
2738 */
2746 - ref = ref_array_push(ref_cbdata->array, refname, oid);
2739 + ref = new_ref_array_item(refname, oid);
2740 ref->commit = commit;
2741 ref->flag = flag;
2742 ref->kind = kind;
2743
2744 + return ref;
2745 +}
2746 +
2747 +struct ref_filter_cbdata {
2748 + struct ref_array *array;
2749 + struct ref_filter *filter;
2750 +};
2751 +
2752 +/*
2753 + * A call-back given to for_each_ref(). Filter refs and keep them for
2754 + * later object processing.
2755 + */
2756 +static int filter_one(const char *refname, const struct object_id *oid, int flag, void *cb_data)
2757 +{
2758 + struct ref_filter_cbdata *ref_cbdata = cb_data;
2759 + struct ref_array_item *ref;
2760 +
2761 + ref = apply_ref_filter(refname, oid, flag, ref_cbdata->filter);
2762 + if (ref)
2763 + ref_array_append(ref_cbdata->array, ref);
2764 +
2765 return 0;
2766 }
2767
@@ -2883,26 +2897,12 @@ void filter_ahead_behind(struct repository *r,
2897 free(commits);
2898 }
2899
2886 -/*
2887 - * API for filtering a set of refs. Based on the type of refs the user
2888 - * has requested, we iterate through those refs and apply filters
2889 - * as per the given ref_filter structure and finally store the
2890 - * filtered refs in the ref_array structure.
2891 - */
2892 -int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int type)
2900 +static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref_fn fn, void *cb_data)
2901 {
2894 - struct ref_filter_cbdata ref_cbdata;
2895 - int save_commit_buffer_orig;
2902 int ret = 0;
2903
2898 - ref_cbdata.array = array;
2899 - ref_cbdata.filter = filter;
2900 -
2904 filter->kind = type & FILTER_REFS_KIND_MASK;
2905
2903 - save_commit_buffer_orig = save_commit_buffer;
2904 - save_commit_buffer = 0;
2905 -
2906 init_contains_cache(&filter->internal.contains_cache);
2907 init_contains_cache(&filter->internal.no_contains_cache);
2908
@@ -2917,20 +2917,43 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
2917 * of filter_ref_kind().
2918 */
2919 if (filter->kind == FILTER_REFS_BRANCHES)
2920 - ret = for_each_fullref_in("refs/heads/", filter_one, &ref_cbdata);
2920 + ret = for_each_fullref_in("refs/heads/", fn, cb_data);
2921 else if (filter->kind == FILTER_REFS_REMOTES)
2922 - ret = for_each_fullref_in("refs/remotes/", filter_one, &ref_cbdata);
2922 + ret = for_each_fullref_in("refs/remotes/", fn, cb_data);
2923 else if (filter->kind == FILTER_REFS_TAGS)
2924 - ret = for_each_fullref_in("refs/tags/", filter_one, &ref_cbdata);
2924 + ret = for_each_fullref_in("refs/tags/", fn, cb_data);
2925 else if (filter->kind & FILTER_REFS_ALL)
2926 - ret = for_each_fullref_in_pattern(filter, filter_one, &ref_cbdata);
2926 + ret = for_each_fullref_in_pattern(filter, fn, cb_data);
2927 if (!ret && (filter->kind & FILTER_REFS_DETACHED_HEAD))
2928 - head_ref(filter_one, &ref_cbdata);
2928 + head_ref(fn, cb_data);
2929 }
2930
2931 clear_contains_cache(&filter->internal.contains_cache);
2932 clear_contains_cache(&filter->internal.no_contains_cache);
2933
2934 + return ret;
2935 +}
2936 +
2937 +/*
2938 + * API for filtering a set of refs. Based on the type of refs the user
2939 + * has requested, we iterate through those refs and apply filters
2940 + * as per the given ref_filter structure and finally store the
2941 + * filtered refs in the ref_array structure.
2942 + */
2943 +int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int type)
2944 +{
2945 + struct ref_filter_cbdata ref_cbdata;
2946 + int save_commit_buffer_orig;
2947 + int ret = 0;
2948 +
2949 + ref_cbdata.array = array;
2950 + ref_cbdata.filter = filter;
2951 +
2952 + save_commit_buffer_orig = save_commit_buffer;
2953 + save_commit_buffer = 0;
2954 +
2955 + ret = do_filter_refs(filter, type, filter_one, &ref_cbdata);
2956 +
2957 /* Filters that need revision walking */
2958 reach_filter(array, &filter->reachable_from, INCLUDE_REACHED);
2959 reach_filter(array, &filter->unreachable_from, EXCLUDE_REACHED);