ref-filter: abstract ref format into its own struct

The ref-filter module provides routines for formatting a ref for output. The fundamental interface for the format is a "const char *" containing the format, and any additional options need to be passed to each invocation of show_ref_array_item. Instead, let's make a ref_format struct that holds the format, along with any associated format options. That will make some enhancements easier in the future: 1. new formatting options can be added without disrupting existing callers 2. some state can be carried in the struct rather than as global variables For now this just has the text format itself along with the quote_style option, but we'll add more fields in future patches. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Jul 13, 2017 at 11:01 UTC 4a68e36d7d106abaf44e3ac960276145b5a25723
6 files changed +70 -52
builtin/branch.c
+7 -7
@@ -383,7 +383,7 @@ static char *build_format(struct ref_filter *filter, int maxwidth, const char *r
383 return strbuf_detach(&fmt, NULL);
384 }
385
386 -static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting, const char *format)
386 +static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting, struct ref_format *format)
387 {
388 int i;
389 struct ref_array array;
@@ -407,8 +407,8 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
407 if (filter->verbose)
408 maxwidth = calc_maxwidth(&array, strlen(remote_prefix));
409
410 - if (!format)
411 - format = to_free = build_format(filter, maxwidth, remote_prefix);
410 + if (!format->format)
411 + format->format = to_free = build_format(filter, maxwidth, remote_prefix);
412
413 if (verify_ref_format(format))
414 die(_("unable to parse format string"));
@@ -416,7 +416,7 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
416 ref_array_sort(sorting, &array);
417
418 for (i = 0; i < array.nr; i++) {
419 - format_ref_array_item(array.items[i], format, 0, &out);
419 + format_ref_array_item(array.items[i], format, &out);
420 if (column_active(colopts)) {
421 assert(!filter->verbose && "--column and --verbose are incompatible");
422 /* format to a string_list to let print_columns() do its job */
@@ -551,7 +551,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
551 struct ref_filter filter;
552 int icase = 0;
553 static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
554 - const char *format = NULL;
554 + struct ref_format format = REF_FORMAT_INIT;
555
556 struct option options[] = {
557 OPT_GROUP(N_("Generic options")),
@@ -595,7 +595,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
595 N_("print only branches of the object"), 0, parse_opt_object_name
596 },
597 OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
598 - OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")),
598 + OPT_STRING( 0 , "format", &format.format, N_("format"), N_("format to use for the output")),
599 OPT_END(),
600 };
601
@@ -669,7 +669,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
669 if (!sorting)
670 sorting = ref_default_sorting();
671 sorting->ignore_case = icase;
672 - print_ref_list(&filter, sorting, format);
672 + print_ref_list(&filter, sorting, &format);
673 print_columns(&output, colopts, NULL);
674 string_list_clear(&output, 0);
675 return 0;
builtin/for-each-ref.c
+12 -10
@@ -17,25 +17,25 @@ static char const * const for_each_ref_usage[] = {
17 int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
18 {
19 int i;
20 - const char *format = "%(objectname) %(objecttype)\t%(refname)";
20 struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
22 - int maxcount = 0, quote_style = 0, icase = 0;
21 + int maxcount = 0, icase = 0;
22 struct ref_array array;
23 struct ref_filter filter;
24 + struct ref_format format = REF_FORMAT_INIT;
25
26 struct option opts[] = {
27 - OPT_BIT('s', "shell", &quote_style,
27 + OPT_BIT('s', "shell", &format.quote_style,
28 N_("quote placeholders suitably for shells"), QUOTE_SHELL),
29 - OPT_BIT('p', "perl", &quote_style,
29 + OPT_BIT('p', "perl", &format.quote_style,
30 N_("quote placeholders suitably for perl"), QUOTE_PERL),
31 - OPT_BIT(0 , "python", &quote_style,
31 + OPT_BIT(0 , "python", &format.quote_style,
32 N_("quote placeholders suitably for python"), QUOTE_PYTHON),
33 - OPT_BIT(0 , "tcl", &quote_style,
33 + OPT_BIT(0 , "tcl", &format.quote_style,
34 N_("quote placeholders suitably for Tcl"), QUOTE_TCL),
35
36 OPT_GROUP(""),
37 OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")),
38 - OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")),
38 + OPT_STRING( 0 , "format", &format.format, N_("format"), N_("format to use for the output")),
39 OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"),
40 N_("field name to sort on"), &parse_opt_ref_sorting),
41 OPT_CALLBACK(0, "points-at", &filter.points_at,
@@ -52,16 +52,18 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
52 memset(&array, 0, sizeof(array));
53 memset(&filter, 0, sizeof(filter));
54
55 + format.format = "%(objectname) %(objecttype)\t%(refname)";
56 +
57 parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
58 if (maxcount < 0) {
59 error("invalid --count argument: `%d'", maxcount);
60 usage_with_options(for_each_ref_usage, opts);
61 }
60 - if (HAS_MULTI_BITS(quote_style)) {
62 + if (HAS_MULTI_BITS(format.quote_style)) {
63 error("more than one quoting style?");
64 usage_with_options(for_each_ref_usage, opts);
65 }
64 - if (verify_ref_format(format))
66 + if (verify_ref_format(&format))
67 usage_with_options(for_each_ref_usage, opts);
68
69 if (!sorting)
@@ -80,7 +82,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
82 if (!maxcount || array.nr < maxcount)
83 maxcount = array.nr;
84 for (i = 0; i < maxcount; i++)
83 - show_ref_array_item(array.items[i], format, quote_style);
85 + show_ref_array_item(array.items[i], &format);
86 ref_array_clear(&array);
87 return 0;
88 }
builtin/tag.c
+16 -14
@@ -32,7 +32,8 @@ static const char * const git_tag_usage[] = {
32 static unsigned int colopts;
33 static int force_sign_annotate;
34
35 -static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, const char *format)
35 +static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,
36 + struct ref_format *format)
37 {
38 struct ref_array array;
39 char *to_free = NULL;
@@ -43,14 +44,14 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, con
44 if (filter->lines == -1)
45 filter->lines = 0;
46
46 - if (!format) {
47 + if (!format->format) {
48 if (filter->lines) {
49 to_free = xstrfmt("%s %%(contents:lines=%d)",
50 "%(align:15)%(refname:lstrip=2)%(end)",
51 filter->lines);
51 - format = to_free;
52 + format->format = to_free;
53 } else
53 - format = "%(refname:lstrip=2)";
54 + format->format = "%(refname:lstrip=2)";
55 }
56
57 if (verify_ref_format(format))
@@ -60,7 +61,7 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, con
61 ref_array_sort(sorting, &array);
62
63 for (i = 0; i < array.nr; i++)
63 - show_ref_array_item(array.items[i], format, 0);
64 + show_ref_array_item(array.items[i], format);
65 ref_array_clear(&array);
66 free(to_free);
67
@@ -106,17 +107,17 @@ static int verify_tag(const char *name, const char *ref,
107 const struct object_id *oid, const void *cb_data)
108 {
109 int flags;
109 - const char *fmt_pretty = cb_data;
110 + const struct ref_format *format = cb_data;
111 flags = GPG_VERIFY_VERBOSE;
112
112 - if (fmt_pretty)
113 + if (format->format)
114 flags = GPG_VERIFY_OMIT_STATUS;
115
116 if (gpg_verify_tag(oid->hash, name, flags))
117 return -1;
118
118 - if (fmt_pretty)
119 - pretty_print_ref(name, oid->hash, fmt_pretty);
119 + if (format->format)
120 + pretty_print_ref(name, oid->hash, format);
121
122 return 0;
123 }
@@ -393,7 +394,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
394 struct strbuf err = STRBUF_INIT;
395 struct ref_filter filter;
396 static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
396 - const char *format = NULL;
397 + struct ref_format format = REF_FORMAT_INIT;
398 int icase = 0;
399 struct option options[] = {
400 OPT_CMDMODE('l', "list", &cmdmode, N_("list tag names"), 'l'),
@@ -432,7 +433,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
433 N_("print only tags of the object"), PARSE_OPT_LASTARG_DEFAULT,
434 parse_opt_object_name, (intptr_t) "HEAD"
435 },
435 - OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")),
436 + OPT_STRING( 0 , "format", &format.format, N_("format"),
437 + N_("format to use for the output")),
438 OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
439 OPT_END()
440 };
@@ -484,7 +486,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
486 run_column_filter(colopts, &copts);
487 }
488 filter.name_patterns = argv;
487 - ret = list_tags(&filter, sorting, format);
489 + ret = list_tags(&filter, sorting, &format);
490 if (column_active(colopts))
491 stop_column_filter();
492 return ret;
@@ -502,9 +504,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
504 if (cmdmode == 'd')
505 return for_each_tag_name(argv, delete_tag, NULL);
506 if (cmdmode == 'v') {
505 - if (format && verify_ref_format(format))
507 + if (format.format && verify_ref_format(&format))
508 usage_with_options(git_tag_usage, options);
507 - return for_each_tag_name(argv, verify_tag, format);
509 + return for_each_tag_name(argv, verify_tag, &format);
510 }
511
512 if (msg.given || msgfile) {
builtin/verify-tag.c
+6 -6
@@ -32,11 +32,11 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix)
32 {
33 int i = 1, verbose = 0, had_error = 0;
34 unsigned flags = 0;
35 - char *fmt_pretty = NULL;
35 + struct ref_format format = REF_FORMAT_INIT;
36 const struct option verify_tag_options[] = {
37 OPT__VERBOSE(&verbose, N_("print tag contents")),
38 OPT_BIT(0, "raw", &flags, N_("print raw gpg status output"), GPG_VERIFY_RAW),
39 - OPT_STRING( 0 , "format", &fmt_pretty, N_("format"), N_("format to use for the output")),
39 + OPT_STRING(0, "format", &format.format, N_("format"), N_("format to use for the output")),
40 OPT_END()
41 };
42
@@ -50,8 +50,8 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix)
50 if (verbose)
51 flags |= GPG_VERIFY_VERBOSE;
52
53 - if (fmt_pretty) {
54 - if (verify_ref_format(fmt_pretty))
53 + if (format.format) {
54 + if (verify_ref_format(&format))
55 usage_with_options(verify_tag_usage,
56 verify_tag_options);
57 flags |= GPG_VERIFY_OMIT_STATUS;
@@ -70,8 +70,8 @@ int cmd_verify_tag(int argc, const char **argv, const char *prefix)
70 continue;
71 }
72
73 - if (fmt_pretty)
74 - pretty_print_ref(name, sha1, fmt_pretty);
73 + if (format.format)
74 + pretty_print_ref(name, sha1, &format);
75 }
76 return had_error;
77 }
ref-filter.c
+12 -10
@@ -657,12 +657,12 @@ static const char *find_next(const char *cp)
657 * Make sure the format string is well formed, and parse out
658 * the used atoms.
659 */
660 -int verify_ref_format(const char *format)
660 +int verify_ref_format(struct ref_format *format)
661 {
662 const char *cp, *sp;
663
664 need_color_reset_at_eol = 0;
665 - for (cp = format; *cp && (sp = find_next(cp)); ) {
665 + for (cp = format->format; *cp && (sp = find_next(cp)); ) {
666 const char *color, *ep = strchr(sp, ')');
667 int at;
668
@@ -2060,16 +2060,17 @@ static void append_literal(const char *cp, const char *ep, struct ref_formatting
2060 }
2061 }
2062
2063 -void format_ref_array_item(struct ref_array_item *info, const char *format,
2064 - int quote_style, struct strbuf *final_buf)
2063 +void format_ref_array_item(struct ref_array_item *info,
2064 + const struct ref_format *format,
2065 + struct strbuf *final_buf)
2066 {
2067 const char *cp, *sp, *ep;
2068 struct ref_formatting_state state = REF_FORMATTING_STATE_INIT;
2069
2069 - state.quote_style = quote_style;
2070 + state.quote_style = format->quote_style;
2071 push_stack_element(&state.stack);
2072
2072 - for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) {
2073 + for (cp = format->format; *cp && (sp = find_next(cp)); cp = ep + 1) {
2074 struct atom_value *atomv;
2075
2076 ep = strchr(sp, ')');
@@ -2093,23 +2094,24 @@ void format_ref_array_item(struct ref_array_item *info, const char *format,
2094 pop_stack_element(&state.stack);
2095 }
2096
2096 -void show_ref_array_item(struct ref_array_item *info, const char *format, int quote_style)
2097 +void show_ref_array_item(struct ref_array_item *info,
2098 + const struct ref_format *format)
2099 {
2100 struct strbuf final_buf = STRBUF_INIT;
2101
2100 - format_ref_array_item(info, format, quote_style, &final_buf);
2102 + format_ref_array_item(info, format, &final_buf);
2103 fwrite(final_buf.buf, 1, final_buf.len, stdout);
2104 strbuf_release(&final_buf);
2105 putchar('\n');
2106 }
2107
2108 void pretty_print_ref(const char *name, const unsigned char *sha1,
2107 - const char *format)
2109 + const struct ref_format *format)
2110 {
2111 struct ref_array_item *ref_item;
2112 ref_item = new_ref_array_item(name, sha1, 0);
2113 ref_item->kind = ref_kind_from_refname(name);
2112 - show_ref_array_item(ref_item, format, 0);
2114 + show_ref_array_item(ref_item, format);
2115 free_array_item(ref_item);
2116 }
2117
ref-filter.h
+17 -5
@@ -72,6 +72,17 @@ struct ref_filter {
72 verbose;
73 };
74
75 +struct ref_format {
76 + /*
77 + * Set these to define the format; make sure you call
78 + * verify_ref_format() afterwards to finalize.
79 + */
80 + const char *format;
81 + int quote_style;
82 +};
83 +
84 +#define REF_FORMAT_INIT { NULL, 0 }
85 +
86 /* Macros for checking --merged and --no-merged options */
87 #define _OPT_MERGED_NO_MERGED(option, filter, h) \
88 { OPTION_CALLBACK, 0, option, (filter), N_("commit"), (h), \
@@ -93,14 +104,15 @@ void ref_array_clear(struct ref_array *array);
104 /* Parse format string and sort specifiers */
105 int parse_ref_filter_atom(const char *atom, const char *ep);
106 /* Used to verify if the given format is correct and to parse out the used atoms */
96 -int verify_ref_format(const char *format);
107 +int verify_ref_format(struct ref_format *format);
108 /* Sort the given ref_array as per the ref_sorting provided */
109 void ref_array_sort(struct ref_sorting *sort, struct ref_array *array);
110 /* Based on the given format and quote_style, fill the strbuf */
100 -void format_ref_array_item(struct ref_array_item *info, const char *format,
101 - int quote_style, struct strbuf *final_buf);
111 +void format_ref_array_item(struct ref_array_item *info,
112 + const struct ref_format *format,
113 + struct strbuf *final_buf);
114 /* Print the ref using the given format and quote_style */
103 -void show_ref_array_item(struct ref_array_item *info, const char *format, int quote_style);
115 +void show_ref_array_item(struct ref_array_item *info, const struct ref_format *format);
116 /* Callback function for parsing the sort option */
117 int parse_opt_ref_sorting(const struct option *opt, const char *arg, int unset);
118 /* Default sort option based on refname */
@@ -117,6 +129,6 @@ void setup_ref_filter_porcelain_msg(void);
129 * name must be a fully qualified refname.
130 */
131 void pretty_print_ref(const char *name, const unsigned char *sha1,
120 - const char *format);
132 + const struct ref_format *format);
133
134 #endif /* REF_FILTER_H */