ref-filter.h: add functions for filter/format & format-only

Add two new public methods to 'ref-filter.h': * 'print_formatted_ref_array()' which, given a format specification & array of ref items, formats and prints the items to stdout. * 'filter_and_format_refs()' which combines 'filter_refs()', 'ref_array_sort()', and 'print_formatted_ref_array()' into a single function. This consolidates much of the code used to filter and format refs in 'builtin/for-each-ref.c', 'builtin/tag.c', and 'builtin/branch.c', reducing duplication and simplifying the future changes needed to optimize the filter & format process. 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 e7574b0c6b1e0cf2de9e000766a13d23fd9516e6
5 files changed +68 -64
builtin/branch.c
+17 -16
@@ -437,8 +437,6 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
437 {
438 int i;
439 struct ref_array array;
440 - struct strbuf out = STRBUF_INIT;
441 - struct strbuf err = STRBUF_INIT;
440 int maxwidth = 0;
441 const char *remote_prefix = "";
442 char *to_free = NULL;
@@ -468,24 +466,27 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
466 filter_ahead_behind(the_repository, format, &array);
467 ref_array_sort(sorting, &array);
468
471 - for (i = 0; i < array.nr; i++) {
472 - strbuf_reset(&err);
473 - strbuf_reset(&out);
474 - if (format_ref_array_item(array.items[i], format, &out, &err))
475 - die("%s", err.buf);
476 - if (column_active(colopts)) {
477 - assert(!filter->verbose && "--column and --verbose are incompatible");
478 - /* format to a string_list to let print_columns() do its job */
469 + if (column_active(colopts)) {
470 + struct strbuf out = STRBUF_INIT, err = STRBUF_INIT;
471 +
472 + assert(!filter->verbose && "--column and --verbose are incompatible");
473 +
474 + for (i = 0; i < array.nr; i++) {
475 + strbuf_reset(&err);
476 + strbuf_reset(&out);
477 + if (format_ref_array_item(array.items[i], format, &out, &err))
478 + die("%s", err.buf);
479 +
480 + /* format to a string_list to let print_columns() do its job */
481 string_list_append(output, out.buf);
480 - } else {
481 - fwrite(out.buf, 1, out.len, stdout);
482 - if (out.len || !format->array_opts.omit_empty)
483 - putchar('\n');
482 }
483 +
484 + strbuf_release(&err);
485 + strbuf_release(&out);
486 + } else {
487 + print_formatted_ref_array(&array, format);
488 }
489
487 - strbuf_release(&err);
488 - strbuf_release(&out);
490 ref_array_clear(&array);
491 free(to_free);
492 }
builtin/for-each-ref.c
+1 -26
@@ -19,15 +19,11 @@ static char const * const for_each_ref_usage[] = {
19
20 int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
21 {
22 - int i, total;
22 struct ref_sorting *sorting;
23 struct string_list sorting_options = STRING_LIST_INIT_DUP;
24 int icase = 0;
26 - struct ref_array array;
25 struct ref_filter filter = REF_FILTER_INIT;
26 struct ref_format format = REF_FORMAT_INIT;
29 - struct strbuf output = STRBUF_INIT;
30 - struct strbuf err = STRBUF_INIT;
27 int from_stdin = 0;
28 struct strvec vec = STRVEC_INIT;
29
@@ -61,8 +57,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
57 OPT_END(),
58 };
59
64 - memset(&array, 0, sizeof(array));
65 -
60 format.format = "%(objectname) %(objecttype)\t%(refname)";
61
62 git_config(git_default_config, NULL);
@@ -104,27 +98,8 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
98 }
99
100 filter.match_as_path = 1;
107 - filter_refs(&array, &filter, FILTER_REFS_ALL);
108 - filter_ahead_behind(the_repository, &format, &array);
109 -
110 - ref_array_sort(sorting, &array);
111 -
112 - total = format.array_opts.max_count;
113 - if (!total || array.nr < total)
114 - total = array.nr;
115 - for (i = 0; i < total; i++) {
116 - strbuf_reset(&err);
117 - strbuf_reset(&output);
118 - if (format_ref_array_item(array.items[i], &format, &output, &err))
119 - die("%s", err.buf);
120 - fwrite(output.buf, 1, output.len, stdout);
121 - if (output.len || !format.array_opts.omit_empty)
122 - putchar('\n');
123 - }
101 + filter_and_format_refs(&filter, FILTER_REFS_ALL, sorting, &format);
102
125 - strbuf_release(&err);
126 - strbuf_release(&output);
127 - ref_array_clear(&array);
103 ref_filter_clear(&filter);
104 ref_sorting_release(sorting);
105 strvec_clear(&vec);
builtin/tag.c
+1 -22
@@ -48,13 +48,7 @@ static int config_sign_tag = -1; /* unspecified */
48 static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
49 struct ref_format *format)
50 {
51 - struct ref_array array;
52 - struct strbuf output = STRBUF_INIT;
53 - struct strbuf err = STRBUF_INIT;
51 char *to_free = NULL;
55 - int i;
56 -
57 - memset(&array, 0, sizeof(array));
52
53 if (filter->lines == -1)
54 filter->lines = 0;
@@ -72,23 +66,8 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
66 if (verify_ref_format(format))
67 die(_("unable to parse format string"));
68 filter->with_commit_tag_algo = 1;
75 - filter_refs(&array, filter, FILTER_REFS_TAGS);
76 - filter_ahead_behind(the_repository, format, &array);
77 - ref_array_sort(sorting, &array);
78 -
79 - for (i = 0; i < array.nr; i++) {
80 - strbuf_reset(&output);
81 - strbuf_reset(&err);
82 - if (format_ref_array_item(array.items[i], format, &output, &err))
83 - die("%s", err.buf);
84 - fwrite(output.buf, 1, output.len, stdout);
85 - if (output.len || !format->array_opts.omit_empty)
86 - putchar('\n');
87 - }
69 + filter_and_format_refs(filter, FILTER_REFS_TAGS, sorting, format);
70
89 - strbuf_release(&err);
90 - strbuf_release(&output);
91 - ref_array_clear(&array);
71 free(to_free);
72
73 return 0;
ref-filter.c
+35
@@ -2939,6 +2939,18 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
2939 return ret;
2940 }
2941
2942 +void filter_and_format_refs(struct ref_filter *filter, unsigned int type,
2943 + struct ref_sorting *sorting,
2944 + struct ref_format *format)
2945 +{
2946 + struct ref_array array = { 0 };
2947 + filter_refs(&array, filter, type);
2948 + filter_ahead_behind(the_repository, format, &array);
2949 + ref_array_sort(sorting, &array);
2950 + print_formatted_ref_array(&array, format);
2951 + ref_array_clear(&array);
2952 +}
2953 +
2954 static int compare_detached_head(struct ref_array_item *a, struct ref_array_item *b)
2955 {
2956 if (!(a->kind ^ b->kind))
@@ -3128,6 +3140,29 @@ int format_ref_array_item(struct ref_array_item *info,
3140 return 0;
3141 }
3142
3143 +void print_formatted_ref_array(struct ref_array *array, struct ref_format *format)
3144 +{
3145 + int total;
3146 + struct strbuf output = STRBUF_INIT, err = STRBUF_INIT;
3147 +
3148 + total = format->array_opts.max_count;
3149 + if (!total || array->nr < total)
3150 + total = array->nr;
3151 + for (int i = 0; i < total; i++) {
3152 + strbuf_reset(&err);
3153 + strbuf_reset(&output);
3154 + if (format_ref_array_item(array->items[i], format, &output, &err))
3155 + die("%s", err.buf);
3156 + if (output.len || !format->array_opts.omit_empty) {
3157 + fwrite(output.buf, 1, output.len, stdout);
3158 + putchar('\n');
3159 + }
3160 + }
3161 +
3162 + strbuf_release(&err);
3163 + strbuf_release(&output);
3164 +}
3165 +
3166 void pretty_print_ref(const char *name, const struct object_id *oid,
3167 struct ref_format *format)
3168 {
ref-filter.h
+14
@@ -137,6 +137,14 @@ struct ref_format {
137 * filtered refs in the ref_array structure.
138 */
139 int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int type);
140 +/*
141 + * Filter refs using the given ref_filter and type, sort the contents
142 + * according to the given ref_sorting, format the filtered refs with the
143 + * given ref_format, and print them to stdout.
144 + */
145 +void filter_and_format_refs(struct ref_filter *filter, unsigned int type,
146 + struct ref_sorting *sorting,
147 + struct ref_format *format);
148 /* Clear all memory allocated to ref_array */
149 void ref_array_clear(struct ref_array *array);
150 /* Used to verify if the given format is correct and to parse out the used atoms */
@@ -161,6 +169,12 @@ char *get_head_description(void);
169 /* Set up translated strings in the output. */
170 void setup_ref_filter_porcelain_msg(void);
171
172 +/*
173 + * Print up to maxcount ref_array elements to stdout using the given
174 + * ref_format.
175 + */
176 +void print_formatted_ref_array(struct ref_array *array, struct ref_format *format);
177 +
178 /*
179 * Print a single ref, outside of any ref-filter. Note that the
180 * name must be a fully qualified refname.