for-each-ref: introduce filter_refs()

Introduce filter_refs() which will act as an API for filtering a set of refs. Based on the type of refs the user has requested, we iterate through those refs and apply filters as per the given ref_filter structure and finally store the filtered refs in the ref_array structure. Currently this will wrap around ref_filter_handler(). Hence, ref_filter_handler is made file scope static. As users of this API will no longer send a ref_filter_cbdata structure directly, we make the elements of ref_filter_cbdata pointers. We can now use the information given by the users to obtain our own ref_filter_cbdata structure. Changes are made to support the change in ref_filter_cbdata structure. Make 'for-each-ref' use this API. Helped-by: Junio C Hamano <gitster@pobox.com> Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr> Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Reviewed-by: Matthieu Moy <Matthieu.Moy@imag.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Karthik Nayak committed Jun 14, 2015 at 01:07 UTC 14de7fba3462aa8051bc63260fc6407aa51b8f68
3 files changed +49 -18
builtin/for-each-ref.c
+11 -10
@@ -16,7 +16,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
16 const char *format = "%(objectname) %(objecttype)\t%(refname)";
17 struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
18 int maxcount = 0, quote_style = 0;
19 - struct ref_filter_cbdata ref_cbdata;
19 + struct ref_array array;
20 + struct ref_filter filter;
21
22 struct option opts[] = {
23 OPT_BIT('s', "shell", &quote_style,
@@ -54,16 +55,16 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
55 /* for warn_ambiguous_refs */
56 git_config(git_default_config, NULL);
57
57 - memset(&ref_cbdata, 0, sizeof(ref_cbdata));
58 - ref_cbdata.filter.name_patterns = argv;
59 - for_each_rawref(ref_filter_handler, &ref_cbdata);
58 + memset(&array, 0, sizeof(array));
59 + memset(&filter, 0, sizeof(filter));
60 + filter.name_patterns = argv;
61 + filter_refs(&array, &filter, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN);
62 + ref_array_sort(sorting, &array);
63
61 - ref_array_sort(sorting, &ref_cbdata.array);
62 -
63 - if (!maxcount || ref_cbdata.array.nr < maxcount)
64 - maxcount = ref_cbdata.array.nr;
64 + if (!maxcount || array.nr < maxcount)
65 + maxcount = array.nr;
66 for (i = 0; i < maxcount; i++)
66 - show_ref_array_item(ref_cbdata.array.items[i], format, quote_style);
67 - ref_array_clear(&ref_cbdata.array);
67 + show_ref_array_item(array.items[i], format, quote_style);
68 + ref_array_clear(&array);
69 return 0;
70 }
ref-filter.c
+26 -4
@@ -859,10 +859,10 @@ static struct ref_array_item *new_ref_array_item(const char *refname,
859 * A call-back given to for_each_ref(). Filter refs and keep them for
860 * later object processing.
861 */
862 -int ref_filter_handler(const char *refname, const struct object_id *oid, int flag, void *cb_data)
862 +static int ref_filter_handler(const char *refname, const struct object_id *oid, int flag, void *cb_data)
863 {
864 struct ref_filter_cbdata *ref_cbdata = cb_data;
865 - struct ref_filter *filter = &ref_cbdata->filter;
865 + struct ref_filter *filter = ref_cbdata->filter;
866 struct ref_array_item *ref;
867
868 if (flag & REF_BAD_NAME) {
@@ -880,8 +880,8 @@ int ref_filter_handler(const char *refname, const struct object_id *oid, int fla
880 */
881 ref = new_ref_array_item(refname, oid->hash, flag);
882
883 - REALLOC_ARRAY(ref_cbdata->array.items, ref_cbdata->array.nr + 1);
884 - ref_cbdata->array.items[ref_cbdata->array.nr++] = ref;
883 + REALLOC_ARRAY(ref_cbdata->array->items, ref_cbdata->array->nr + 1);
884 + ref_cbdata->array->items[ref_cbdata->array->nr++] = ref;
885 return 0;
886 }
887
@@ -905,6 +905,28 @@ void ref_array_clear(struct ref_array *array)
905 array->nr = array->alloc = 0;
906 }
907
908 +/*
909 + * API for filtering a set of refs. Based on the type of refs the user
910 + * has requested, we iterate through those refs and apply filters
911 + * as per the given ref_filter structure and finally store the
912 + * filtered refs in the ref_array structure.
913 + */
914 +int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int type)
915 +{
916 + struct ref_filter_cbdata ref_cbdata;
917 +
918 + ref_cbdata.array = array;
919 + ref_cbdata.filter = filter;
920 +
921 + if (type & (FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN))
922 + return for_each_rawref(ref_filter_handler, &ref_cbdata);
923 + else if (type & FILTER_REFS_ALL)
924 + return for_each_ref(ref_filter_handler, &ref_cbdata);
925 + else
926 + die("filter_refs: invalid type");
927 + return 0;
928 +}
929 +
930 static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, struct ref_array_item *b)
931 {
932 struct atom_value *va, *vb;
ref-filter.h
+12 -4
@@ -13,6 +13,9 @@
13 #define QUOTE_PYTHON 4
14 #define QUOTE_TCL 8
15
16 +#define FILTER_REFS_INCLUDE_BROKEN 0x1
17 +#define FILTER_REFS_ALL 0x2
18 +
19 struct atom_value {
20 const char *s;
21 unsigned long ul; /* used for sorting when not FIELD_STR */
@@ -42,12 +45,17 @@ struct ref_filter {
45 };
46
47 struct ref_filter_cbdata {
45 - struct ref_array array;
46 - struct ref_filter filter;
48 + struct ref_array *array;
49 + struct ref_filter *filter;
50 };
51
49 -/* Callback function for for_each_*ref(). This filters the refs based on the filters set */
50 -int ref_filter_handler(const char *refname, const struct object_id *oid, int flag, void *cb_data);
52 +/*
53 + * API for filtering a set of refs. Based on the type of refs the user
54 + * has requested, we iterate through those refs and apply filters
55 + * as per the given ref_filter structure and finally store the
56 + * filtered refs in the ref_array structure.
57 + */
58 +int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int type);
59 /* Clear all memory allocated to ref_array */
60 void ref_array_clear(struct ref_array *array);
61 /* Parse format string and sort specifiers */