summaryrefslogtreecommitdiff
path: root/builtin/tag.c
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2021-10-20 12:23:53 -0700
committerLibravatar Junio C Hamano <gitster@pobox.com>2021-10-20 14:33:07 -0700
commit98e7ab6d42beba8b35fefb3856b07ac20e89d1ca (patch)
tree4e083a023ea19acbece8ba5a6a8f89ff8d97b06a /builtin/tag.c
parentMerge branch 'ab/ref-filter-leakfix' into jc/fix-ref-sorting-parse (diff)
downloadtgif-98e7ab6d42beba8b35fefb3856b07ac20e89d1ca.tar.xz
for-each-ref: delay parsing of --sort=<atom> options
The for-each-ref family of commands invoke parsers immediately when it sees each --sort=<atom> option, and die before even seeing the other options on the command line when the <atom> is unrecognised. Instead, accumulate them in a string list, and have them parsed into a ref_sorting structure after the command line parsing is done. As a consequence, "git branch --sort=bogus -h" used to fail to give the brief help, which arguably may have been a feature, now does so, which is more consistent with how other options work. The patch is smaller than the actual extent of the "damage" to the codebase, thanks to the fact that the original code consistently used OPT_REF_SORT() macro to handle command line options. We only needed to replace the variable used for the list, and implementation of the callback function used in the macro. The old rule was for the users of the API to: - Declare ref_sorting and ref_sorting_tail variables; - OPT_REF_SORT() macro will instantiate ref_sorting instance (which may barf and die) and append it to the tail; - Append to the tail each ref_sorting read from the configuration by parsing in the config callback (which may barf and die); - See if ref_sorting is null and use ref_sorting_default() instead. Now the rule is not all that different but is simpler: - Declare ref_sorting_options string list. - OPT_REF_SORT() macro will append it to the string list; - Append to the string list the sort key read from the configuration; - call ref_sorting_options() to turn the string list to ref_sorting structure (which also deals with the default value). As side effects, this change also cleans up a few issues: - 95be717c (parse_opt_ref_sorting: always use with NONEG flag, 2019-03-20) muses that "git for-each-ref --no-sort" should simply clear the sort keys accumulated so far; it now does. - The implementation detail of "struct ref_sorting" and the helper function parse_ref_sorting() can now be private to the ref-filter API implementation. - If you set branch.sort to a bogus value, the any "git branch" invocation, not only the listing mode, would abort with the original code; now it doesn't Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin/tag.c')
-rw-r--r--builtin/tag.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/builtin/tag.c b/builtin/tag.c
index 6fe646710d..41863c5ab7 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -178,7 +178,6 @@ static const char tag_template_nocleanup[] =
static int git_tag_config(const char *var, const char *value, void *cb)
{
int status;
- struct ref_sorting **sorting_tail = (struct ref_sorting **)cb;
if (!strcmp(var, "tag.gpgsign")) {
config_sign_tag = git_config_bool(var, value);
@@ -188,7 +187,7 @@ static int git_tag_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "tag.sort")) {
if (!value)
return config_error_nonbool(var);
- parse_ref_sorting(sorting_tail, value);
+ string_list_append(cb, value);
return 0;
}
@@ -436,7 +435,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
struct ref_transaction *transaction;
struct strbuf err = STRBUF_INIT;
struct ref_filter filter;
- static struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;
+ struct ref_sorting *sorting;
+ struct string_list sorting_options = STRING_LIST_INIT_DUP;
struct ref_format format = REF_FORMAT_INIT;
int icase = 0;
int edit_flag = 0;
@@ -470,7 +470,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
OPT_WITHOUT(&filter.no_commit, N_("print only tags that don't contain the commit")),
OPT_MERGED(&filter, N_("print only tags that are merged")),
OPT_NO_MERGED(&filter, N_("print only tags that are not merged")),
- OPT_REF_SORT(sorting_tail),
+ OPT_REF_SORT(&sorting_options),
{
OPTION_CALLBACK, 0, "points-at", &filter.points_at, N_("object"),
N_("print only tags of the object"), PARSE_OPT_LASTARG_DEFAULT,
@@ -486,7 +486,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
setup_ref_filter_porcelain_msg();
- git_config(git_tag_config, sorting_tail);
+ git_config(git_tag_config, &sorting_options);
memset(&opt, 0, sizeof(opt));
memset(&filter, 0, sizeof(filter));
@@ -525,8 +525,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
die(_("--column and -n are incompatible"));
colopts = 0;
}
- if (!sorting)
- sorting = ref_default_sorting();
+ sorting = ref_sorting_options(&sorting_options);
ref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase);
filter.ignore_case = icase;
if (cmdmode == 'l') {