{"thread":{"id":"56372","subject":"[PATCH 0/8] [GSOC] ref-filter: eliminate dummy ref_format to make the code cleaner","startedAt":"2021-08-25T09:08:56Z","lastAt":"2021-08-25T09:09:12Z","messageCount":9,"participants":["ZheNing Hu via GitGitGadget"],"isPatch":true,"patchVersion":1,"patchTotal":8},"messages":[{"id":"433718","messageId":"pull.1025.git.1629882532.gitgitgadget@gmail.com","threadId":"56372","inReplyTo":null,"subject":"[PATCH 0/8] [GSOC] ref-filter: eliminate dummy ref_format to make the code cleaner","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-08-25T09:08:44Z","receivedAt":"2021-08-25T09:08:56Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"Note that there are these disadvantages in the ref-filter code:\n\n 1. Scattered state variables: need_tagged, need_symref are placed globally,\n    need_color_reset_at_eol is placed inside ref_format.\n 2. parse_sorting_atom() uses a dummy ref_format, which causes us to need a\n    lot of extra logic to check in verify_ref_format(), because dummy\n    ref_format records some state, while truly ref_format does not.\n 3. struct ref_sorting uses a very strange singly linked list\n    implementation, and there is a memory leak with it.\n\nTherefore, the following modifications are made to make the logic of\nref-filter cleaner:\n\n 1. Let ref_sorting use list api.\n 2. Eliminate dummy ref_format.\n 3. Add ref_format to ref_array_item.\n 4. Move the check in verify_ref_format() to atom parsing function.\n 5. Add deref member to used_atom.\n 6. Move need_symref, need_tagged to ref_format.\n\nZheNing Hu (8):\n  [GSOC] ref-filter: use list api to replace ref_sorting linked list\n  [GSOC] ref-filter: let parse_sorting_atom() use real ref_format\n  [GSOC] ref-filter: add ref_format to ref_array_item\n  [GSOC] ref-filter: clean up verify_ref_format()\n  [GSOC] ref-filter: introduce symref_atom_parser()\n  [GSOC] ref-filter: remove grab_oid() function\n  [GSOC] ref-filter: add deref member to struct used_atom\n  [GSOC] ref-filter: move need_symref, need_tagged into ref_format\n\n builtin/branch.c       |  26 +++--\n builtin/for-each-ref.c |  20 ++--\n builtin/ls-remote.c    |  18 ++--\n builtin/tag.c          |  24 +++--\n ref-filter.c           | 236 +++++++++++++++++++++--------------------\n ref-filter.h           |  20 ++--\n 6 files changed, 185 insertions(+), 159 deletions(-)\n\n\nbase-commit: c4203212e360b25a1c69467b5a8437d45a373cac\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1025%2Fadlternative%2Fref-filter-code-clean-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1025/adlternative/ref-filter-code-clean-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/1025\n-- \ngitgitgadget\n"},{"id":"433719","messageId":"e68635cda515a9cd504c1d7366e9c353ab2adb2e.1629882532.git.gitgitgadget@gmail.com","threadId":"56372","inReplyTo":"pull.1025.git.1629882532.gitgitgadget@gmail.com","subject":"[PATCH 1/8] [GSOC] ref-filter: use list api to replace ref_sorting linked list","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-08-25T09:08:45Z","receivedAt":"2021-08-25T09:08:57Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nstruct ref_sorting is connected by the internal singly linked list,\nit is very difficult to use, and each node is added by the head\ninsertion method but we can only traverse it forward.\n\nReplace it with list api, which is easy to use and introduce a\nfree_ref_sorting_list() which can free all ref_sorting item and\nsolve the problem of memory leak.\n\nThis will help the logic of ref-filter become clearer.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Hariom Verma <hariom18599@gmail.com>\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n builtin/branch.c       | 20 +++++++++++---------\n builtin/for-each-ref.c | 15 ++++++++-------\n builtin/ls-remote.c    | 12 ++++++------\n builtin/tag.c          | 19 +++++++++++--------\n ref-filter.c           | 42 ++++++++++++++++++++++++++++--------------\n ref-filter.h           |  8 +++++---\n 6 files changed, 69 insertions(+), 47 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex b23b1d1752a..72fafd301c5 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -77,7 +77,7 @@ define_list_config_array(color_branch_slots);\n static int git_branch_config(const char *var, const char *value, void *cb)\n {\n \tconst char *slot_name;\n-\tstruct ref_sorting **sorting_tail = (struct ref_sorting **)cb;\n+\tstruct ref_sorting *sorting_tail = (struct ref_sorting *)cb;\n \n \tif (!strcmp(var, \"branch.sort\")) {\n \t\tif (!value)\n@@ -624,7 +624,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tenum branch_track track;\n \tstruct ref_filter filter;\n \tint icase = 0;\n-\tstatic struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;\n+\tstruct ref_sorting sorting;\n \tstruct ref_format format = REF_FORMAT_INIT;\n \n \tstruct option options[] = {\n@@ -665,7 +665,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\tOPT_MERGED(&filter, N_(\"print only branches that are merged\")),\n \t\tOPT_NO_MERGED(&filter, N_(\"print only branches that are not merged\")),\n \t\tOPT_COLUMN(0, \"column\", &colopts, N_(\"list branches in columns\")),\n-\t\tOPT_REF_SORT(sorting_tail),\n+\t\tOPT_REF_SORT(&sorting),\n \t\tOPT_CALLBACK(0, \"points-at\", &filter.points_at, N_(\"object\"),\n \t\t\tN_(\"print only branches of the object\"), parse_opt_object_name),\n \t\tOPT_BOOL('i', \"ignore-case\", &icase, N_(\"sorting and filtering are case insensitive\")),\n@@ -678,11 +678,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \tmemset(&filter, 0, sizeof(filter));\n \tfilter.kind = FILTER_REFS_BRANCHES;\n \tfilter.abbrev = -1;\n+\tINIT_LIST_HEAD(&sorting.list);\n \n \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n \t\tusage_with_options(builtin_branch_usage, options);\n \n-\tgit_config(git_branch_config, sorting_tail);\n+\tgit_config(git_branch_config, &sorting);\n \n \ttrack = git_branch_track;\n \n@@ -748,12 +749,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\t * local branches 'refs/heads/...' and finally remote-tracking\n \t\t * branches 'refs/remotes/...'.\n \t\t */\n-\t\tif (!sorting)\n-\t\t\tsorting = ref_default_sorting();\n-\t\tref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase);\n+\t\tif (list_empty(&sorting.list))\n+\t\t\tref_default_sorting(&sorting);\n+\t\tref_sorting_set_sort_flags_all(&sorting, REF_SORTING_ICASE, icase);\n \t\tref_sorting_set_sort_flags_all(\n-\t\t\tsorting, REF_SORTING_DETACHED_HEAD_FIRST, 1);\n-\t\tprint_ref_list(&filter, sorting, &format);\n+\t\t\t&sorting, REF_SORTING_DETACHED_HEAD_FIRST, 1);\n+\t\tprint_ref_list(&filter, &sorting, &format);\n \t\tprint_columns(&output, colopts, NULL);\n \t\tstring_list_clear(&output, 0);\n \t\treturn 0;\n@@ -864,5 +865,6 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t} else\n \t\tusage_with_options(builtin_branch_usage, options);\n \n+\tfree_ref_sorting_list(&sorting);\n \treturn 0;\n }\ndiff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c\nindex 89cb6307d46..3cd38eacd7c 100644\n--- a/builtin/for-each-ref.c\n+++ b/builtin/for-each-ref.c\n@@ -17,7 +17,7 @@ static char const * const for_each_ref_usage[] = {\n int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n {\n \tint i;\n-\tstruct ref_sorting *sorting = NULL, **sorting_tail = &sorting;\n+\tstruct ref_sorting sorting;\n \tint maxcount = 0, icase = 0;\n \tstruct ref_array array;\n \tstruct ref_filter filter;\n@@ -39,7 +39,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n \t\tOPT_INTEGER( 0 , \"count\", &maxcount, N_(\"show only <n> matched refs\")),\n \t\tOPT_STRING(  0 , \"format\", &format.format, N_(\"format\"), N_(\"format to use for the output\")),\n \t\tOPT__COLOR(&format.use_color, N_(\"respect format colors\")),\n-\t\tOPT_REF_SORT(sorting_tail),\n+\t\tOPT_REF_SORT(&sorting),\n \t\tOPT_CALLBACK(0, \"points-at\", &filter.points_at,\n \t\t\t     N_(\"object\"), N_(\"print only refs which points at the given object\"),\n \t\t\t     parse_opt_object_name),\n@@ -51,6 +51,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n \t\tOPT_END(),\n \t};\n \n+\tINIT_LIST_HEAD(&sorting.list);\n \tmemset(&array, 0, sizeof(array));\n \tmemset(&filter, 0, sizeof(filter));\n \n@@ -70,15 +71,15 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n \tif (verify_ref_format(&format))\n \t\tusage_with_options(for_each_ref_usage, opts);\n \n-\tif (!sorting)\n-\t\tsorting = ref_default_sorting();\n-\tref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase);\n+\tif (list_empty(&sorting.list))\n+\t\tref_default_sorting(&sorting);\n+\tref_sorting_set_sort_flags_all(&sorting, REF_SORTING_ICASE, icase);\n \tfilter.ignore_case = icase;\n \n \tfilter.name_patterns = argv;\n \tfilter.match_as_path = 1;\n \tfilter_refs(&array, &filter, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN);\n-\tref_array_sort(sorting, &array);\n+\tref_array_sort(&sorting, &array);\n \n \tif (!maxcount || array.nr < maxcount)\n \t\tmaxcount = array.nr;\n@@ -96,6 +97,6 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n \tref_array_clear(&array);\n \tfree_commit_list(filter.with_commit);\n \tfree_commit_list(filter.no_commit);\n-\tUNLEAK(sorting);\n+\tfree_ref_sorting_list(&sorting);\n \treturn 0;\n }\ndiff --git a/builtin/ls-remote.c b/builtin/ls-remote.c\nindex 1794548c711..717ecde03d1 100644\n--- a/builtin/ls-remote.c\n+++ b/builtin/ls-remote.c\n@@ -54,7 +54,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)\n \tstruct transport *transport;\n \tconst struct ref *ref;\n \tstruct ref_array ref_array;\n-\tstatic struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;\n+\tstatic struct ref_sorting sorting;\n \n \tstruct option options[] = {\n \t\tOPT__QUIET(&quiet, N_(\"do not print remote URL\")),\n@@ -68,7 +68,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)\n \t\tOPT_BIT(0, \"refs\", &flags, N_(\"do not show peeled tags\"), REF_NORMAL),\n \t\tOPT_BOOL(0, \"get-url\", &get_url,\n \t\t\t N_(\"take url.<base>.insteadOf into account\")),\n-\t\tOPT_REF_SORT(sorting_tail),\n+\t\tOPT_REF_SORT(&sorting),\n \t\tOPT_SET_INT_F(0, \"exit-code\", &status,\n \t\t\t      N_(\"exit with exit code 2 if no matching refs are found\"),\n \t\t\t      2, PARSE_OPT_NOCOMPLETE),\n@@ -79,13 +79,12 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)\n \t};\n \n \tmemset(&ref_array, 0, sizeof(ref_array));\n+\tINIT_LIST_HEAD(&sorting.list);\n \n \targc = parse_options(argc, argv, prefix, options, ls_remote_usage,\n \t\t\t     PARSE_OPT_STOP_AT_NON_OPTION);\n \tdest = argv[0];\n \n-\tUNLEAK(sorting);\n-\n \tif (argc > 1) {\n \t\tint i;\n \t\tCALLOC_ARRAY(pattern, argc);\n@@ -137,8 +136,8 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)\n \t\titem->symref = xstrdup_or_null(ref->symref);\n \t}\n \n-\tif (sorting)\n-\t\tref_array_sort(sorting, &ref_array);\n+\tif (!list_empty(&sorting.list))\n+\t\tref_array_sort(&sorting, &ref_array);\n \n \tfor (i = 0; i < ref_array.nr; i++) {\n \t\tconst struct ref_array_item *ref = ref_array.items[i];\n@@ -149,6 +148,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)\n \t}\n \n \tref_array_clear(&ref_array);\n+\tfree_ref_sorting_list(&sorting);\n \tif (transport_disconnect(transport))\n \t\treturn 1;\n \treturn status;\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex 452558ec957..9d057b214e2 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -178,7 +178,7 @@ static const char tag_template_nocleanup[] =\n static int git_tag_config(const char *var, const char *value, void *cb)\n {\n \tint status;\n-\tstruct ref_sorting **sorting_tail = (struct ref_sorting **)cb;\n+\tstruct ref_sorting *sorting_tail = (struct ref_sorting *)cb;\n \n \tif (!strcmp(var, \"tag.gpgsign\")) {\n \t\tconfig_sign_tag = git_config_bool(var, value);\n@@ -438,7 +438,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \tstruct ref_transaction *transaction;\n \tstruct strbuf err = STRBUF_INIT;\n \tstruct ref_filter filter;\n-\tstatic struct ref_sorting *sorting = NULL, **sorting_tail = &sorting;\n+\tstruct ref_sorting sorting;\n \tstruct ref_format format = REF_FORMAT_INIT;\n \tint icase = 0;\n \tint edit_flag = 0;\n@@ -472,7 +472,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t\tOPT_WITHOUT(&filter.no_commit, N_(\"print only tags that don't contain the commit\")),\n \t\tOPT_MERGED(&filter, N_(\"print only tags that are merged\")),\n \t\tOPT_NO_MERGED(&filter, N_(\"print only tags that are not merged\")),\n-\t\tOPT_REF_SORT(sorting_tail),\n+\t\tOPT_REF_SORT(&sorting),\n \t\t{\n \t\t\tOPTION_CALLBACK, 0, \"points-at\", &filter.points_at, N_(\"object\"),\n \t\t\tN_(\"print only tags of the object\"), PARSE_OPT_LASTARG_DEFAULT,\n@@ -487,7 +487,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \n \tsetup_ref_filter_porcelain_msg();\n \n-\tgit_config(git_tag_config, sorting_tail);\n+\tINIT_LIST_HEAD(&sorting.list);\n+\tgit_config(git_tag_config, &sorting);\n \n \tmemset(&opt, 0, sizeof(opt));\n \tmemset(&filter, 0, sizeof(filter));\n@@ -526,9 +527,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t\t\tdie(_(\"--column and -n are incompatible\"));\n \t\tcolopts = 0;\n \t}\n-\tif (!sorting)\n-\t\tsorting = ref_default_sorting();\n-\tref_sorting_set_sort_flags_all(sorting, REF_SORTING_ICASE, icase);\n+\tif (list_empty(&sorting.list))\n+\t\tref_default_sorting(&sorting);\n+\tref_sorting_set_sort_flags_all(&sorting, REF_SORTING_ICASE, icase);\n \tfilter.ignore_case = icase;\n \tif (cmdmode == 'l') {\n \t\tint ret;\n@@ -539,11 +540,13 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t\t\trun_column_filter(colopts, &copts);\n \t\t}\n \t\tfilter.name_patterns = argv;\n-\t\tret = list_tags(&filter, sorting, &format);\n+\t\tret = list_tags(&filter, &sorting, &format);\n \t\tif (column_active(colopts))\n \t\t\tstop_column_filter();\n \t\treturn ret;\n \t}\n+\tfree_ref_sorting_list(&sorting);\n+\n \tif (filter.lines != -1)\n \t\tdie(_(\"-n option is only allowed in list mode\"));\n \tif (filter.with_commit)\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 93ce2a6ef2e..e9e3841c326 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -2534,14 +2534,16 @@ static int compare_refs(const void *a_, const void *b_, void *ref_sorting)\n {\n \tstruct ref_array_item *a = *((struct ref_array_item **)a_);\n \tstruct ref_array_item *b = *((struct ref_array_item **)b_);\n-\tstruct ref_sorting *s;\n+\tstruct ref_sorting *s = ref_sorting;\n+\tstruct list_head *pos;\n \n-\tfor (s = ref_sorting; s; s = s->next) {\n-\t\tint cmp = cmp_ref_sorting(s, a, b);\n+\tlist_for_each_prev(pos, &s->list) {\n+\t\tint cmp = cmp_ref_sorting(list_entry(pos, struct ref_sorting, list),\n+\t\t\t\t\t\t     a, b);\n \t\tif (cmp)\n \t\t\treturn cmp;\n \t}\n-\ts = ref_sorting;\n+\n \treturn s && s->sort_flags & REF_SORTING_ICASE ?\n \t\tstrcasecmp(a->refname, b->refname) :\n \t\tstrcmp(a->refname, b->refname);\n@@ -2550,11 +2552,15 @@ static int compare_refs(const void *a_, const void *b_, void *ref_sorting)\n void ref_sorting_set_sort_flags_all(struct ref_sorting *sorting,\n \t\t\t\t    unsigned int mask, int on)\n {\n-\tfor (; sorting; sorting = sorting->next) {\n+\tstruct list_head *pos;\n+\tstruct ref_sorting *entry;\n+\n+\tlist_for_each(pos, &sorting->list) {\n+\t\tentry = list_entry(pos, struct ref_sorting, list);\n \t\tif (on)\n-\t\t\tsorting->sort_flags |= mask;\n+\t\t\tentry->sort_flags |= mask;\n \t\telse\n-\t\t\tsorting->sort_flags &= ~mask;\n+\t\t\tentry->sort_flags &= ~mask;\n \t}\n }\n \n@@ -2667,24 +2673,32 @@ static int parse_sorting_atom(const char *atom)\n }\n \n /*  If no sorting option is given, use refname to sort as default */\n-struct ref_sorting *ref_default_sorting(void)\n+void ref_default_sorting(struct ref_sorting *sorting_list)\n {\n \tstatic const char cstr_name[] = \"refname\";\n \n \tstruct ref_sorting *sorting = xcalloc(1, sizeof(*sorting));\n-\n-\tsorting->next = NULL;\n+\tlist_add_tail(&sorting->list, &sorting_list->list);\n \tsorting->atom = parse_sorting_atom(cstr_name);\n-\treturn sorting;\n }\n \n-void parse_ref_sorting(struct ref_sorting **sorting_tail, const char *arg)\n+void free_ref_sorting_list(struct ref_sorting *sorting_list) {\n+\tstruct list_head *pos, *tmp;\n+\tstruct ref_sorting *item;\n+\n+\tlist_for_each_safe(pos, tmp, &sorting_list->list) {\n+\t\titem = list_entry(pos, struct ref_sorting, list);\n+\t\tlist_del(pos);\n+\t\tfree(item);\n+\t}\n+}\n+\n+void parse_ref_sorting(struct ref_sorting *sorting_list, const char *arg)\n {\n \tstruct ref_sorting *s;\n \n \tCALLOC_ARRAY(s, 1);\n-\ts->next = *sorting_tail;\n-\t*sorting_tail = s;\n+\tlist_add_tail(&s->list, &sorting_list->list);\n \n \tif (*arg == '-') {\n \t\ts->sort_flags |= REF_SORTING_REVERSE;\ndiff --git a/ref-filter.h b/ref-filter.h\nindex c15dee8d6b9..a502c2758e9 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -26,7 +26,7 @@\n struct atom_value;\n \n struct ref_sorting {\n-\tstruct ref_sorting *next;\n+\tstruct list_head list;\n \tint atom; /* index into used_atom array (internal) */\n \tenum {\n \t\tREF_SORTING_REVERSE = 1<<0,\n@@ -123,11 +123,13 @@ int format_ref_array_item(struct ref_array_item *info,\n \t\t\t  struct strbuf *final_buf,\n \t\t\t  struct strbuf *error_buf);\n /*  Parse a single sort specifier and add it to the list */\n-void parse_ref_sorting(struct ref_sorting **sorting_tail, const char *atom);\n+void parse_ref_sorting(struct ref_sorting *sorting_list, const char *arg);\n /*  Callback function for parsing the sort option */\n int parse_opt_ref_sorting(const struct option *opt, const char *arg, int unset);\n /*  Default sort option based on refname */\n-struct ref_sorting *ref_default_sorting(void);\n+void ref_default_sorting(struct ref_sorting *sorting_list);\n+/* Free all ref_sorting items in sorting list */\n+void free_ref_sorting_list(struct ref_sorting *sorting_list);\n /*  Function to parse --merged and --no-merged options */\n int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset);\n /*  Get the current HEAD's description */\n-- \ngitgitgadget\n\n"},{"id":"433720","messageId":"97d4a0b3793240b1bd5e3bed5318611064d9ccb7.1629882532.git.gitgitgadget@gmail.com","threadId":"56372","inReplyTo":"pull.1025.git.1629882532.gitgitgadget@gmail.com","subject":"[PATCH 2/8] [GSOC] ref-filter: let parse_sorting_atom() use real ref_format","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-08-25T09:08:46Z","receivedAt":"2021-08-25T09:08:58Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nparse_sorting_atom() currently uses a \"dummy\" ref_format, because\nit doesn't care about the details of real ref_format. But in fact,\nwe expect to save some state in ref_format, and we need to check\nthese statuses when executing some functions, e.g. in\nverify_ref_format() we check format->quote_style and\nformat->need_color_reset_at_eol. And we intentionally want some\nglobal options (e.g. need_tagged) to be added to struct ref_format,\nso we need to care about ref_format details now, but the \"dummy\"\nref_format prevents the truly ref_format to record them correctly.\n\nSo let parse_sorting_atom() use the real ref_format, this requires us\nto separate the work of parsing the sort atom from parse_ref_sorting().\nAdd an \"arg\" member to struct ref_sorting to record the name of the\nsort atom, and parse_ref_sorting() only records the atom name, and\nintroduce a parse_ref_sorting_list() to traverse the ref_sorting\nlinked list and parsing each sort atom.\n\nThis will help us add some global options to struct ref_format later.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Hariom Verma <hariom18599@gmail.com>\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n builtin/branch.c       |  1 +\n builtin/for-each-ref.c |  1 +\n builtin/ls-remote.c    |  6 ++++--\n builtin/tag.c          |  1 +\n ref-filter.c           | 25 ++++++++++++++-----------\n ref-filter.h           |  3 +++\n 6 files changed, 24 insertions(+), 13 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 72fafd301c5..3b21c2b54b9 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -751,6 +751,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)\n \t\t */\n \t\tif (list_empty(&sorting.list))\n \t\t\tref_default_sorting(&sorting);\n+\t\tparse_ref_sorting_list(&sorting, &format);\n \t\tref_sorting_set_sort_flags_all(&sorting, REF_SORTING_ICASE, icase);\n \t\tref_sorting_set_sort_flags_all(\n \t\t\t&sorting, REF_SORTING_DETACHED_HEAD_FIRST, 1);\ndiff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c\nindex 3cd38eacd7c..8948b7bcd32 100644\n--- a/builtin/for-each-ref.c\n+++ b/builtin/for-each-ref.c\n@@ -73,6 +73,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n \n \tif (list_empty(&sorting.list))\n \t\tref_default_sorting(&sorting);\n+\tparse_ref_sorting_list(&sorting, &format);\n \tref_sorting_set_sort_flags_all(&sorting, REF_SORTING_ICASE, icase);\n \tfilter.ignore_case = icase;\n \ndiff --git a/builtin/ls-remote.c b/builtin/ls-remote.c\nindex 717ecde03d1..7fac069a29d 100644\n--- a/builtin/ls-remote.c\n+++ b/builtin/ls-remote.c\n@@ -49,6 +49,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)\n \t\tTRANSPORT_LS_REFS_OPTIONS_INIT;\n \tint i;\n \tstruct string_list server_options = STRING_LIST_INIT_DUP;\n+\tstruct ref_format dummy = REF_FORMAT_INIT;\n \n \tstruct remote *remote;\n \tstruct transport *transport;\n@@ -136,9 +137,10 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)\n \t\titem->symref = xstrdup_or_null(ref->symref);\n \t}\n \n-\tif (!list_empty(&sorting.list))\n+\tif (!list_empty(&sorting.list)) {\n+\t\tparse_ref_sorting_list(&sorting, &dummy);\n \t\tref_array_sort(&sorting, &ref_array);\n-\n+\t}\n \tfor (i = 0; i < ref_array.nr; i++) {\n \t\tconst struct ref_array_item *ref = ref_array.items[i];\n \t\tif (show_symref_target && ref->symref)\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex 9d057b214e2..a0d4aa775e3 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -529,6 +529,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t}\n \tif (list_empty(&sorting.list))\n \t\tref_default_sorting(&sorting);\n+\tparse_ref_sorting_list(&sorting, &format);\n \tref_sorting_set_sort_flags_all(&sorting, REF_SORTING_ICASE, icase);\n \tfilter.ignore_case = icase;\n \tif (cmdmode == 'l') {\ndiff --git a/ref-filter.c b/ref-filter.c\nindex e9e3841c326..88a3e06eea9 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -2656,30 +2656,33 @@ void pretty_print_ref(const char *name, const struct object_id *oid,\n \tfree_array_item(ref_item);\n }\n \n-static int parse_sorting_atom(const char *atom)\n+static int parse_sorting_atom(struct ref_format *format, const char *atom)\n {\n-\t/*\n-\t * This parses an atom using a dummy ref_format, since we don't\n-\t * actually care about the formatting details.\n-\t */\n-\tstruct ref_format dummy = REF_FORMAT_INIT;\n \tconst char *end = atom + strlen(atom);\n \tstruct strbuf err = STRBUF_INIT;\n-\tint res = parse_ref_filter_atom(&dummy, atom, end, &err);\n+\tint res = parse_ref_filter_atom(format, atom, end, &err);\n \tif (res < 0)\n \t\tdie(\"%s\", err.buf);\n \tstrbuf_release(&err);\n \treturn res;\n }\n \n+void parse_ref_sorting_list(struct ref_sorting *sorting_list, struct ref_format *format) {\n+\tstruct list_head *pos;\n+\tstruct ref_sorting *entry;\n+\n+\tlist_for_each(pos, &sorting_list->list) {\n+\t\tentry = list_entry(pos, struct ref_sorting, list);\n+\t\tentry->atom = parse_sorting_atom(format, entry->arg);\n+\t}\n+}\n+\n /*  If no sorting option is given, use refname to sort as default */\n void ref_default_sorting(struct ref_sorting *sorting_list)\n {\n-\tstatic const char cstr_name[] = \"refname\";\n-\n \tstruct ref_sorting *sorting = xcalloc(1, sizeof(*sorting));\n \tlist_add_tail(&sorting->list, &sorting_list->list);\n-\tsorting->atom = parse_sorting_atom(cstr_name);\n+\tsorting->arg = \"refname\";\n }\n \n void free_ref_sorting_list(struct ref_sorting *sorting_list) {\n@@ -2707,7 +2710,7 @@ void parse_ref_sorting(struct ref_sorting *sorting_list, const char *arg)\n \tif (skip_prefix(arg, \"version:\", &arg) ||\n \t    skip_prefix(arg, \"v:\", &arg))\n \t\ts->sort_flags |= REF_SORTING_VERSION;\n-\ts->atom = parse_sorting_atom(arg);\n+\ts->arg = arg;\n }\n \n int parse_opt_ref_sorting(const struct option *opt, const char *arg, int unset)\ndiff --git a/ref-filter.h b/ref-filter.h\nindex a502c2758e9..8f602583788 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -28,6 +28,7 @@ struct atom_value;\n struct ref_sorting {\n \tstruct list_head list;\n \tint atom; /* index into used_atom array (internal) */\n+\tconst char *arg;\n \tenum {\n \t\tREF_SORTING_REVERSE = 1<<0,\n \t\tREF_SORTING_ICASE = 1<<1,\n@@ -128,6 +129,8 @@ void parse_ref_sorting(struct ref_sorting *sorting_list, const char *arg);\n int parse_opt_ref_sorting(const struct option *opt, const char *arg, int unset);\n /*  Default sort option based on refname */\n void ref_default_sorting(struct ref_sorting *sorting_list);\n+/* Parse every sort atom of ref_sorting list */\n+void parse_ref_sorting_list(struct ref_sorting *sorting_list, struct ref_format *format);\n /* Free all ref_sorting items in sorting list */\n void free_ref_sorting_list(struct ref_sorting *sorting_list);\n /*  Function to parse --merged and --no-merged options */\n-- \ngitgitgadget\n\n"},{"id":"433721","messageId":"48458437c4a6e0633643f383fb0bf14e710bc9a9.1629882532.git.gitgitgadget@gmail.com","threadId":"56372","inReplyTo":"pull.1025.git.1629882532.gitgitgadget@gmail.com","subject":"[PATCH 3/8] [GSOC] ref-filter: add ref_format to ref_array_item","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-08-25T09:08:47Z","receivedAt":"2021-08-25T09:09:00Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nSince we expect to move some global options to ref_format,\nwe may want check these global options in some functions\nlike populate_value(), but the problem is that these\nfunctions cannot use ref_format, which means we may need\na deep call chain to pass ref_format to them, this will\nbe a bit cumbersome.\n\nWe can use another method: Add the ref_format member to\nref_array_item. Since we have successfully eliminated dummy\nref_format, this can ensure that the same ref_array can use\nthe same ref_format, so we pass ref_format through the call\nchain when ref_array_item is initialized, we also add\nref_format member to ref_cbdata.\n\nThis will help us move the global options to ref_format later.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Hariom Verma <hariom18599@gmail.com>\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n builtin/branch.c       |  5 +++--\n builtin/for-each-ref.c |  4 ++--\n builtin/ls-remote.c    |  2 +-\n builtin/tag.c          |  4 ++--\n ref-filter.c           | 24 ++++++++++++++----------\n ref-filter.h           |  7 ++++---\n 6 files changed, 26 insertions(+), 20 deletions(-)\n\ndiff --git a/builtin/branch.c b/builtin/branch.c\nindex 3b21c2b54b9..4c6e7ef5f10 100644\n--- a/builtin/branch.c\n+++ b/builtin/branch.c\n@@ -427,7 +427,7 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin\n \n \tmemset(&array, 0, sizeof(array));\n \n-\tfilter_refs(&array, filter, filter->kind | FILTER_REFS_INCLUDE_BROKEN);\n+\tfilter_refs(&array, filter, format, filter->kind | FILTER_REFS_INCLUDE_BROKEN);\n \n \tif (filter->verbose)\n \t\tmaxwidth = calc_maxwidth(&array, strlen(remote_prefix));\n@@ -444,7 +444,8 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin\n \tfor (i = 0; i < array.nr; i++) {\n \t\tstrbuf_reset(&err);\n \t\tstrbuf_reset(&out);\n-\t\tif (format_ref_array_item(array.items[i], format, &out, &err))\n+\t\tarray.items[i]->format = format;\n+\t\tif (format_ref_array_item(array.items[i], &out, &err))\n \t\t\tdie(\"%s\", err.buf);\n \t\tif (column_active(colopts)) {\n \t\t\tassert(!filter->verbose && \"--column and --verbose are incompatible\");\ndiff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c\nindex 8948b7bcd32..4a71caca929 100644\n--- a/builtin/for-each-ref.c\n+++ b/builtin/for-each-ref.c\n@@ -79,7 +79,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n \n \tfilter.name_patterns = argv;\n \tfilter.match_as_path = 1;\n-\tfilter_refs(&array, &filter, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN);\n+\tfilter_refs(&array, &filter, &format, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN);\n \tref_array_sort(&sorting, &array);\n \n \tif (!maxcount || array.nr < maxcount)\n@@ -87,7 +87,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)\n \tfor (i = 0; i < maxcount; i++) {\n \t\tstrbuf_reset(&err);\n \t\tstrbuf_reset(&output);\n-\t\tif (format_ref_array_item(array.items[i], &format, &output, &err))\n+\t\tif (format_ref_array_item(array.items[i], &output, &err))\n \t\t\tdie(\"%s\", err.buf);\n \t\tfwrite(output.buf, 1, output.len, stdout);\n \t\tputchar('\\n');\ndiff --git a/builtin/ls-remote.c b/builtin/ls-remote.c\nindex 7fac069a29d..2dd19a8583d 100644\n--- a/builtin/ls-remote.c\n+++ b/builtin/ls-remote.c\n@@ -133,7 +133,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)\n \t\t\tcontinue;\n \t\tif (!tail_match(pattern, ref->name))\n \t\t\tcontinue;\n-\t\titem = ref_array_push(&ref_array, ref->name, &ref->old_oid);\n+\t\titem = ref_array_push(&ref_array, ref->name, &ref->old_oid, &dummy);\n \t\titem->symref = xstrdup_or_null(ref->symref);\n \t}\n \ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex a0d4aa775e3..9a66c4d37a5 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -62,13 +62,13 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting,\n \tif (verify_ref_format(format))\n \t\tdie(_(\"unable to parse format string\"));\n \tfilter->with_commit_tag_algo = 1;\n-\tfilter_refs(&array, filter, FILTER_REFS_TAGS);\n+\tfilter_refs(&array, filter, format, FILTER_REFS_TAGS);\n \tref_array_sort(sorting, &array);\n \n \tfor (i = 0; i < array.nr; i++) {\n \t\tstrbuf_reset(&output);\n \t\tstrbuf_reset(&err);\n-\t\tif (format_ref_array_item(array.items[i], format, &output, &err))\n+\t\tif (format_ref_array_item(array.items[i], &output, &err))\n \t\t\tdie(\"%s\", err.buf);\n \t\tfwrite(output.buf, 1, output.len, stdout);\n \t\tputchar('\\n');\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 88a3e06eea9..f4fa3102da6 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -2167,22 +2167,24 @@ static const struct object_id *match_points_at(struct oid_array *points_at,\n  * Callers can then fill in other struct members at their leisure.\n  */\n static struct ref_array_item *new_ref_array_item(const char *refname,\n-\t\t\t\t\t\t const struct object_id *oid)\n+\t\t\t\t\t\t const struct object_id *oid,\n+\t\t\t\t\t\t struct ref_format *format)\n {\n \tstruct ref_array_item *ref;\n \n \tFLEX_ALLOC_STR(ref, refname, refname);\n \toidcpy(&ref->objectname, oid);\n \tref->rest = NULL;\n-\n+\tref->format = format;\n \treturn ref;\n }\n \n struct ref_array_item *ref_array_push(struct ref_array *array,\n \t\t\t\t      const char *refname,\n-\t\t\t\t      const struct object_id *oid)\n+\t\t\t\t      const struct object_id *oid,\n+\t\t\t\t      struct ref_format *format)\n {\n-\tstruct ref_array_item *ref = new_ref_array_item(refname, oid);\n+\tstruct ref_array_item *ref = new_ref_array_item(refname, oid, format);\n \n \tALLOC_GROW(array->items, array->nr + 1, array->alloc);\n \tarray->items[array->nr++] = ref;\n@@ -2226,6 +2228,7 @@ static int filter_ref_kind(struct ref_filter *filter, const char *refname)\n struct ref_filter_cbdata {\n \tstruct ref_array *array;\n \tstruct ref_filter *filter;\n+\tstruct ref_format *format;\n \tstruct contains_cache contains_cache;\n \tstruct contains_cache no_contains_cache;\n };\n@@ -2238,6 +2241,7 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,\n {\n \tstruct ref_filter_cbdata *ref_cbdata = cb_data;\n \tstruct ref_filter *filter = ref_cbdata->filter;\n+\tstruct ref_format *format = ref_cbdata->format;\n \tstruct ref_array_item *ref;\n \tstruct commit *commit = NULL;\n \tunsigned int kind;\n@@ -2288,7 +2292,7 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid,\n \t * to do its job and the resulting list may yet to be pruned\n \t * by maxcount logic.\n \t */\n-\tref = ref_array_push(ref_cbdata->array, refname, oid);\n+\tref = ref_array_push(ref_cbdata->array, refname, oid, format);\n \tref->commit = commit;\n \tref->flag = flag;\n \tref->kind = kind;\n@@ -2401,7 +2405,7 @@ static void reach_filter(struct ref_array *array,\n  * as per the given ref_filter structure and finally store the\n  * filtered refs in the ref_array structure.\n  */\n-int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int type)\n+int filter_refs(struct ref_array *array, struct ref_filter *filter, struct ref_format *format, unsigned int type)\n {\n \tstruct ref_filter_cbdata ref_cbdata;\n \tint ret = 0;\n@@ -2409,7 +2413,7 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int\n \n \tref_cbdata.array = array;\n \tref_cbdata.filter = filter;\n-\n+\tref_cbdata.format = format;\n \tif (type & FILTER_REFS_INCLUDE_BROKEN)\n \t\tbroken = 1;\n \tfilter->kind = type & FILTER_REFS_KIND_MASK;\n@@ -2592,12 +2596,12 @@ static void append_literal(const char *cp, const char *ep, struct ref_formatting\n }\n \n int format_ref_array_item(struct ref_array_item *info,\n-\t\t\t  struct ref_format *format,\n \t\t\t  struct strbuf *final_buf,\n \t\t\t  struct strbuf *error_buf)\n {\n \tconst char *cp, *sp, *ep;\n \tstruct ref_formatting_state state = REF_FORMATTING_STATE_INIT;\n+\tstruct ref_format *format = info->format;\n \n \tstate.quote_style = format->quote_style;\n \tpush_stack_element(&state.stack);\n@@ -2644,9 +2648,9 @@ void pretty_print_ref(const char *name, const struct object_id *oid,\n \tstruct strbuf output = STRBUF_INIT;\n \tstruct strbuf err = STRBUF_INIT;\n \n-\tref_item = new_ref_array_item(name, oid);\n+\tref_item = new_ref_array_item(name, oid, format);\n \tref_item->kind = ref_kind_from_refname(name);\n-\tif (format_ref_array_item(ref_item, format, &output, &err))\n+\tif (format_ref_array_item(ref_item, &output, &err))\n \t\tdie(\"%s\", err.buf);\n \tfwrite(output.buf, 1, output.len, stdout);\n \tputchar('\\n');\ndiff --git a/ref-filter.h b/ref-filter.h\nindex 8f602583788..e95c055fb86 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -45,6 +45,7 @@ struct ref_array_item {\n \tconst char *symref;\n \tstruct commit *commit;\n \tstruct atom_value *value;\n+\tstruct ref_format *format;\n \tchar refname[FLEX_ARRAY];\n };\n \n@@ -109,7 +110,7 @@ struct ref_format {\n  * as per the given ref_filter structure and finally store the\n  * filtered refs in the ref_array structure.\n  */\n-int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int type);\n+int filter_refs(struct ref_array *array, struct ref_filter *filter, struct ref_format *format, unsigned int type);\n /*  Clear all memory allocated to ref_array */\n void ref_array_clear(struct ref_array *array);\n /*  Used to verify if the given format is correct and to parse out the used atoms */\n@@ -120,7 +121,6 @@ void ref_array_sort(struct ref_sorting *sort, struct ref_array *array);\n void ref_sorting_set_sort_flags_all(struct ref_sorting *sorting, unsigned int mask, int on);\n /*  Based on the given format and quote_style, fill the strbuf */\n int format_ref_array_item(struct ref_array_item *info,\n-\t\t\t  struct ref_format *format,\n \t\t\t  struct strbuf *final_buf,\n \t\t\t  struct strbuf *error_buf);\n /*  Parse a single sort specifier and add it to the list */\n@@ -153,6 +153,7 @@ void pretty_print_ref(const char *name, const struct object_id *oid,\n  */\n struct ref_array_item *ref_array_push(struct ref_array *array,\n \t\t\t\t      const char *refname,\n-\t\t\t\t      const struct object_id *oid);\n+\t\t\t\t      const struct object_id *oid,\n+\t\t\t\t      struct ref_format *format);\n \n #endif /*  REF_FILTER_H  */\n-- \ngitgitgadget\n\n"},{"id":"433722","messageId":"54c95b0386ea7238b09931cecabc71dc1b9c0d21.1629882532.git.gitgitgadget@gmail.com","threadId":"56372","inReplyTo":"pull.1025.git.1629882532.gitgitgadget@gmail.com","subject":"[PATCH 4/8] [GSOC] ref-filter: clean up verify_ref_format()","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-08-25T09:08:48Z","receivedAt":"2021-08-25T09:09:02Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nBecause we may not use the real ref_format when using\nparse_ref_filter_atom() before, we have to perform some\natom checks in verify_ref_format() (instead of the parsing\nfunction of each atom), which is very inelegant.\n\nSince we have eliminated dummy ref_format, we can freely put\nsome of the check logic from verify_ref_format() to their\ncorresponding atom parsing functions.\n\nIntroduce raw_atom_reject_quote_style() to check if there is\nany incompatibility quote style with the %(raw) atom.\n\nThis can make the logic of the program more concise.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Hariom Verma <hariom18599@gmail.com>\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n ref-filter.c | 43 ++++++++++++++++++++++---------------------\n 1 file changed, 22 insertions(+), 21 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex f4fa3102da6..e42cd738c32 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -242,6 +242,7 @@ static int color_atom_parser(struct ref_format *format, struct used_atom *atom,\n \t */\n \tif (!want_color(format->use_color))\n \t\tcolor_parse(\"\", atom->u.color);\n+\tformat->need_color_reset_at_eol = !!strcmp(color_value, \"reset\");\n \treturn 0;\n }\n \n@@ -432,12 +433,29 @@ static int contents_atom_parser(struct ref_format *format, struct used_atom *ato\n \treturn 0;\n }\n \n+static int raw_atom_reject_quote_style(int quote_style) {\n+\tswitch (quote_style) {\n+\tcase QUOTE_PYTHON:\n+\tcase QUOTE_SHELL:\n+\tcase QUOTE_TCL:\n+\t\treturn 1;\n+\tcase QUOTE_PERL:\n+\tcase 0:\n+\t\treturn 0;\n+\tdefault:\n+\t\tBUG(\"unknown quote style %d\", quote_style);\n+\t}\n+}\n+\n static int raw_atom_parser(struct ref_format *format, struct used_atom *atom,\n \t\t\t\tconst char *arg, struct strbuf *err)\n {\n-\tif (!arg)\n+\tif (!arg) {\n \t\tatom->u.raw_data.option = RAW_BARE;\n-\telse if (!strcmp(arg, \"size\"))\n+\t\tif (raw_atom_reject_quote_style(format->quote_style))\n+\t\t\treturn strbuf_addf_ret(err, -1, _(\"--format=%%(raw) cannot be used with\"\n+\t\t\t\t\t\t   \"--python, --shell, --tcl\"));\n+\t} else if (!strcmp(arg, \"size\"))\n \t\tatom->u.raw_data.option = RAW_LENGTH;\n \telse\n \t\treturn strbuf_addf_ret(err, -1, _(\"unrecognized %%(raw) argument: %s\"), arg);\n@@ -567,7 +585,7 @@ static int rest_atom_parser(struct ref_format *format, struct used_atom *atom,\n \tif (arg)\n \t\treturn strbuf_addf_ret(err, -1, _(\"%%(rest) does not take arguments\"));\n \tformat->use_rest = 1;\n-\treturn 0;\n+\treturn strbuf_addf_ret(err, -1, _(\"this command reject atom %%(rest)\"));\n }\n \n static int head_atom_parser(struct ref_format *format, struct used_atom *atom,\n@@ -1004,11 +1022,6 @@ static const char *find_next(const char *cp)\n \treturn NULL;\n }\n \n-static int reject_atom(enum atom_type atom_type)\n-{\n-\treturn atom_type == ATOM_REST;\n-}\n-\n /*\n  * Make sure the format string is well formed, and parse out\n  * the used atoms.\n@@ -1020,7 +1033,7 @@ int verify_ref_format(struct ref_format *format)\n \tformat->need_color_reset_at_eol = 0;\n \tfor (cp = format->format; *cp && (sp = find_next(cp)); ) {\n \t\tstruct strbuf err = STRBUF_INIT;\n-\t\tconst char *color, *ep = strchr(sp, ')');\n+\t\tconst char *ep = strchr(sp, ')');\n \t\tint at;\n \n \t\tif (!ep)\n@@ -1029,20 +1042,8 @@ int verify_ref_format(struct ref_format *format)\n \t\tat = parse_ref_filter_atom(format, sp + 2, ep, &err);\n \t\tif (at < 0)\n \t\t\tdie(\"%s\", err.buf);\n-\t\tif (reject_atom(used_atom[at].atom_type))\n-\t\t\tdie(_(\"this command reject atom %%(%.*s)\"), (int)(ep - sp - 2), sp + 2);\n-\n-\t\tif ((format->quote_style == QUOTE_PYTHON ||\n-\t\t     format->quote_style == QUOTE_SHELL ||\n-\t\t     format->quote_style == QUOTE_TCL) &&\n-\t\t     used_atom[at].atom_type == ATOM_RAW &&\n-\t\t     used_atom[at].u.raw_data.option == RAW_BARE)\n-\t\t\tdie(_(\"--format=%.*s cannot be used with\"\n-\t\t\t      \"--python, --shell, --tcl\"), (int)(ep - sp - 2), sp + 2);\n \t\tcp = ep + 1;\n \n-\t\tif (skip_prefix(used_atom[at].name, \"color:\", &color))\n-\t\t\tformat->need_color_reset_at_eol = !!strcmp(color, \"reset\");\n \t\tstrbuf_release(&err);\n \t}\n \tif (format->need_color_reset_at_eol && !want_color(format->use_color))\n-- \ngitgitgadget\n\n"},{"id":"433723","messageId":"40ab1faad39285ecd05ea57d6d2107e644d01bb7.1629882532.git.gitgitgadget@gmail.com","threadId":"56372","inReplyTo":"pull.1025.git.1629882532.gitgitgadget@gmail.com","subject":"[PATCH 5/8] [GSOC] ref-filter: introduce symref_atom_parser()","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-08-25T09:08:49Z","receivedAt":"2021-08-25T09:09:03Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nparse_ref_filter_atom() sets need_symref by checking\nwhether the atom type is ATOM_SYMREF. When we are operating\nother atoms here, this step of checking is not necessary.\n\nSo add the symref_atom_parser() specifically to parse the\n%(symref) atom, and set need_symref in it.\n\nThis can make the program logic more concise.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Hariom Verma <hariom18599@gmail.com>\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n ref-filter.c | 11 ++++++++---\n 1 file changed, 8 insertions(+), 3 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex e42cd738c32..8dca273f720 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -495,6 +495,13 @@ static int person_email_atom_parser(struct ref_format *format, struct used_atom\n \treturn 0;\n }\n \n+static int symref_atom_parser(struct ref_format *format, struct used_atom *atom,\n+\t\t\t       const char *arg, struct strbuf *err)\n+{\n+\tneed_symref = 1;\n+\treturn refname_atom_parser_internal(&atom->u.refname, arg, atom->name, err);\n+}\n+\n static int refname_atom_parser(struct ref_format *format, struct used_atom *atom,\n \t\t\t       const char *arg, struct strbuf *err)\n {\n@@ -634,7 +641,7 @@ static struct {\n \t[ATOM_RAW] = { \"raw\", SOURCE_OBJ, FIELD_STR, raw_atom_parser },\n \t[ATOM_UPSTREAM] = { \"upstream\", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },\n \t[ATOM_PUSH] = { \"push\", SOURCE_NONE, FIELD_STR, remote_ref_atom_parser },\n-\t[ATOM_SYMREF] = { \"symref\", SOURCE_NONE, FIELD_STR, refname_atom_parser },\n+\t[ATOM_SYMREF] = { \"symref\", SOURCE_NONE, FIELD_STR, symref_atom_parser },\n \t[ATOM_FLAG] = { \"flag\", SOURCE_NONE },\n \t[ATOM_HEAD] = { \"HEAD\", SOURCE_NONE, FIELD_STR, head_atom_parser },\n \t[ATOM_COLOR] = { \"color\", SOURCE_NONE, FIELD_STR, color_atom_parser },\n@@ -758,8 +765,6 @@ static int parse_ref_filter_atom(struct ref_format *format,\n \t\treturn -1;\n \tif (*atom == '*')\n \t\tneed_tagged = 1;\n-\tif (i == ATOM_SYMREF)\n-\t\tneed_symref = 1;\n \treturn at;\n }\n \n-- \ngitgitgadget\n\n"},{"id":"433724","messageId":"63758a71e4001aa0a09d64a2c61f8c8b256c480a.1629882532.git.gitgitgadget@gmail.com","threadId":"56372","inReplyTo":"pull.1025.git.1629882532.gitgitgadget@gmail.com","subject":"[PATCH 6/8] [GSOC] ref-filter: remove grab_oid() function","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-08-25T09:08:50Z","receivedAt":"2021-08-25T09:09:08Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nBecause \"atom_type == ATOM_OBJECTNAME\" implies the condition\nof `starts_with(name, \"objectname\")`, \"atom_type == ATOM_TREE\"\nimplies the condition of `starts_with(name, \"tree\")`, so the\ncheck for `starts_with(name, field)` in grab_oid() is redundant.\n\nRemove the grab_oid() from ref-filter, to reduce repeated check.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Hariom Verma <hariom18599@gmail.com>\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n ref-filter.c | 26 +++++++++-----------------\n 1 file changed, 9 insertions(+), 17 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 8dca273f720..67f62a3b591 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -1071,16 +1071,6 @@ static const char *do_grab_oid(const char *field, const struct object_id *oid,\n \t}\n }\n \n-static int grab_oid(const char *name, const char *field, const struct object_id *oid,\n-\t\t    struct atom_value *v, struct used_atom *atom)\n-{\n-\tif (starts_with(name, field)) {\n-\t\tv->s = xstrdup(do_grab_oid(field, oid, atom));\n-\t\treturn 1;\n-\t}\n-\treturn 0;\n-}\n-\n /* See grab_values */\n static void grab_common_values(struct atom_value *val, int deref, struct expand_data *oi)\n {\n@@ -1106,8 +1096,9 @@ static void grab_common_values(struct atom_value *val, int deref, struct expand_\n \t\t\t}\n \t\t} else if (atom_type == ATOM_DELTABASE)\n \t\t\tv->s = xstrdup(oid_to_hex(&oi->delta_base_oid));\n-\t\telse if (atom_type == ATOM_OBJECTNAME && deref)\n-\t\t\tgrab_oid(name, \"objectname\", &oi->oid, v, &used_atom[i]);\n+\t\telse if (atom_type == ATOM_OBJECTNAME && deref) {\n+\t\t\tv->s = xstrdup(do_grab_oid(\"objectname\", &oi->oid, &used_atom[i]));\n+\t\t}\n \t}\n }\n \n@@ -1148,9 +1139,10 @@ static void grab_commit_values(struct atom_value *val, int deref, struct object\n \t\t\tcontinue;\n \t\tif (deref)\n \t\t\tname++;\n-\t\tif (atom_type == ATOM_TREE &&\n-\t\t    grab_oid(name, \"tree\", get_commit_tree_oid(commit), v, &used_atom[i]))\n+\t\tif (atom_type == ATOM_TREE) {\n+\t\t\tv->s = xstrdup(do_grab_oid(\"tree\", get_commit_tree_oid(commit), &used_atom[i]));\n \t\t\tcontinue;\n+\t\t}\n \t\tif (atom_type == ATOM_NUMPARENT) {\n \t\t\tv->value = commit_list_count(commit->parents);\n \t\t\tv->s = xstrfmt(\"%lu\", (unsigned long)v->value);\n@@ -1923,9 +1915,9 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\t\t\tv->s = xstrdup(buf + 1);\n \t\t\t}\n \t\t\tcontinue;\n-\t\t} else if (!deref && atom_type == ATOM_OBJECTNAME &&\n-\t\t\t   grab_oid(name, \"objectname\", &ref->objectname, v, atom)) {\n-\t\t\t\tcontinue;\n+\t\t} else if (!deref && atom_type == ATOM_OBJECTNAME) {\n+\t\t\t   v->s = xstrdup(do_grab_oid(\"objectname\", &ref->objectname, atom));\n+\t\t\t   continue;\n \t\t} else if (atom_type == ATOM_HEAD) {\n \t\t\tif (atom->u.head && !strcmp(ref->refname, atom->u.head))\n \t\t\t\tv->s = xstrdup(\"*\");\n-- \ngitgitgadget\n\n"},{"id":"433725","messageId":"cf868636c57dad04f9eee8affab7cd77b6ac6b22.1629882532.git.gitgitgadget@gmail.com","threadId":"56372","inReplyTo":"pull.1025.git.1629882532.gitgitgadget@gmail.com","subject":"[PATCH 7/8] [GSOC] ref-filter: add deref member to struct used_atom","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-08-25T09:08:51Z","receivedAt":"2021-08-25T09:09:09Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nIn the ref-filter logic, the dereference flag '*' is stored\nat the beginning of used_atom[i].name (e.g. '*objectname:short'),\nthis leads us to make some check on used_atom[i].name[0] to\nknow if the atom need to be dereferenced. This is not only\ncumbersome to use, but also poor in readability.\n\nSo add `deref` flag to struct used_atom used to indicate\nwhether the atom needs to be dereferenced and let used_atom\nrecord only the rest part (i.e. 'objectname:short').\n\nThis can make the logic of the program clearer and easy to use.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Hariom Verma <hariom18599@gmail.com>\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n ref-filter.c | 55 ++++++++++++++++++++--------------------------------\n 1 file changed, 21 insertions(+), 34 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex 67f62a3b591..e4f96dad504 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -171,6 +171,7 @@ enum atom_type {\n  * array.\n  */\n static struct used_atom {\n+\tunsigned int deref : 1;\n \tenum atom_type atom_type;\n \tconst char *name;\n \tcmp_type type;\n@@ -319,7 +320,7 @@ static int objecttype_atom_parser(struct ref_format *format, struct used_atom *a\n {\n \tif (arg)\n \t\treturn strbuf_addf_ret(err, -1, _(\"%%(objecttype) does not take arguments\"));\n-\tif (*atom->name == '*')\n+\tif (atom->deref)\n \t\toi_deref.info.typep = &oi_deref.type;\n \telse\n \t\toi.info.typep = &oi.type;\n@@ -331,13 +332,13 @@ static int objectsize_atom_parser(struct ref_format *format, struct used_atom *a\n {\n \tif (!arg) {\n \t\tatom->u.objectsize.option = O_SIZE;\n-\t\tif (*atom->name == '*')\n+\t\tif (atom->deref)\n \t\t\toi_deref.info.sizep = &oi_deref.size;\n \t\telse\n \t\t\toi.info.sizep = &oi.size;\n \t} else if (!strcmp(arg, \"disk\")) {\n \t\tatom->u.objectsize.option = O_SIZE_DISK;\n-\t\tif (*atom->name == '*')\n+\t\tif (atom->deref)\n \t\t\toi_deref.info.disk_sizep = &oi_deref.disk_size;\n \t\telse\n \t\t\toi.info.disk_sizep = &oi.disk_size;\n@@ -351,7 +352,7 @@ static int deltabase_atom_parser(struct ref_format *format, struct used_atom *at\n {\n \tif (arg)\n \t\treturn strbuf_addf_ret(err, -1, _(\"%%(deltabase) does not take arguments\"));\n-\tif (*atom->name == '*')\n+\tif (atom->deref)\n \t\toi_deref.info.delta_base_oid = &oi_deref.delta_base_oid;\n \telse\n \t\toi.info.delta_base_oid = &oi.delta_base_oid;\n@@ -697,10 +698,13 @@ static int parse_ref_filter_atom(struct ref_format *format,\n \tconst char *sp;\n \tconst char *arg;\n \tint i, at, atom_len;\n+\tint deref = 0;\n \n \tsp = atom;\n-\tif (*sp == '*' && sp < ep)\n+\tif (*sp == '*' && sp < ep) {\n \t\tsp++; /* deref */\n+\t\tderef = 1;\n+\t}\n \tif (ep <= sp)\n \t\treturn strbuf_addf_ret(err, -1, _(\"malformed field name: %.*s\"),\n \t\t\t\t       (int)(ep-atom), atom);\n@@ -717,7 +721,7 @@ static int parse_ref_filter_atom(struct ref_format *format,\n \t/* Do we have the atom already used elsewhere? */\n \tfor (i = 0; i < used_atom_cnt; i++) {\n \t\tint len = strlen(used_atom[i].name);\n-\t\tif (len == ep - atom && !memcmp(used_atom[i].name, atom, len))\n+\t\tif (len == ep - sp && !memcmp(used_atom[i].name, sp, len))\n \t\t\treturn i;\n \t}\n \n@@ -741,17 +745,18 @@ static int parse_ref_filter_atom(struct ref_format *format,\n \tused_atom_cnt++;\n \tREALLOC_ARRAY(used_atom, used_atom_cnt);\n \tused_atom[at].atom_type = i;\n-\tused_atom[at].name = xmemdupz(atom, ep - atom);\n+\tused_atom[at].deref = deref;\n+\tused_atom[at].name = xmemdupz(sp, ep - sp);\n \tused_atom[at].type = valid_atom[i].cmp_type;\n \tused_atom[at].source = valid_atom[i].source;\n \tif (used_atom[at].source == SOURCE_OBJ) {\n-\t\tif (*atom == '*')\n+\t\tif (deref)\n \t\t\toi_deref.info.contentp = &oi_deref.content;\n \t\telse\n \t\t\toi.info.contentp = &oi.content;\n \t}\n \tif (arg) {\n-\t\targ = used_atom[at].name + (arg - atom) + 1;\n+\t\targ = used_atom[at].name + (arg - sp) + 1;\n \t\tif (!*arg) {\n \t\t\t/*\n \t\t\t * Treat empty sub-arguments list as NULL (i.e.,\n@@ -763,7 +768,7 @@ static int parse_ref_filter_atom(struct ref_format *format,\n \tmemset(&used_atom[at].u, 0, sizeof(used_atom[at].u));\n \tif (valid_atom[i].parser && valid_atom[i].parser(format, &used_atom[at], arg, err))\n \t\treturn -1;\n-\tif (*atom == '*')\n+\tif (deref)\n \t\tneed_tagged = 1;\n \treturn at;\n }\n@@ -1077,13 +1082,10 @@ static void grab_common_values(struct atom_value *val, int deref, struct expand_\n \tint i;\n \n \tfor (i = 0; i < used_atom_cnt; i++) {\n-\t\tconst char *name = used_atom[i].name;\n \t\tenum atom_type atom_type = used_atom[i].atom_type;\n \t\tstruct atom_value *v = &val[i];\n-\t\tif (!!deref != (*name == '*'))\n+\t\tif (!!deref != used_atom[i].deref)\n \t\t\tcontinue;\n-\t\tif (deref)\n-\t\t\tname++;\n \t\tif (atom_type == ATOM_OBJECTTYPE)\n \t\t\tv->s = xstrdup(type_name(oi->type));\n \t\telse if (atom_type == ATOM_OBJECTSIZE) {\n@@ -1109,13 +1111,10 @@ static void grab_tag_values(struct atom_value *val, int deref, struct object *ob\n \tstruct tag *tag = (struct tag *) obj;\n \n \tfor (i = 0; i < used_atom_cnt; i++) {\n-\t\tconst char *name = used_atom[i].name;\n \t\tenum atom_type atom_type = used_atom[i].atom_type;\n \t\tstruct atom_value *v = &val[i];\n-\t\tif (!!deref != (*name == '*'))\n+\t\tif (!!deref != used_atom[i].deref)\n \t\t\tcontinue;\n-\t\tif (deref)\n-\t\t\tname++;\n \t\tif (atom_type == ATOM_TAG)\n \t\t\tv->s = xstrdup(tag->tag);\n \t\telse if (atom_type == ATOM_TYPE && tag->tagged)\n@@ -1132,13 +1131,10 @@ static void grab_commit_values(struct atom_value *val, int deref, struct object\n \tstruct commit *commit = (struct commit *) obj;\n \n \tfor (i = 0; i < used_atom_cnt; i++) {\n-\t\tconst char *name = used_atom[i].name;\n \t\tenum atom_type atom_type = used_atom[i].atom_type;\n \t\tstruct atom_value *v = &val[i];\n-\t\tif (!!deref != (*name == '*'))\n+\t\tif (!!deref != used_atom[i].deref)\n \t\t\tcontinue;\n-\t\tif (deref)\n-\t\t\tname++;\n \t\tif (atom_type == ATOM_TREE) {\n \t\t\tv->s = xstrdup(do_grab_oid(\"tree\", get_commit_tree_oid(commit), &used_atom[i]));\n \t\t\tcontinue;\n@@ -1290,10 +1286,8 @@ static void grab_person(const char *who, struct atom_value *val, int deref, void\n \tfor (i = 0; i < used_atom_cnt; i++) {\n \t\tconst char *name = used_atom[i].name;\n \t\tstruct atom_value *v = &val[i];\n-\t\tif (!!deref != (*name == '*'))\n+\t\tif (!!deref != used_atom[i].deref)\n \t\t\tcontinue;\n-\t\tif (deref)\n-\t\t\tname++;\n \t\tif (strncmp(who, name, wholen))\n \t\t\tcontinue;\n \t\tif (name[wholen] != 0 &&\n@@ -1432,10 +1426,8 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct exp\n \t\tstruct atom_value *v = &val[i];\n \t\tenum atom_type atom_type = atom->atom_type;\n \n-\t\tif (!!deref != (*name == '*'))\n+\t\tif (!!deref != used_atom[i].deref)\n \t\t\tcontinue;\n-\t\tif (deref)\n-\t\t\tname++;\n \n \t\tif (atom_type == ATOM_RAW) {\n \t\t\tunsigned long buf_size = data->size;\n@@ -1840,7 +1832,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\tenum atom_type atom_type = atom->atom_type;\n \t\tconst char *name = used_atom[i].name;\n \t\tstruct atom_value *v = &ref->value[i];\n-\t\tint deref = 0;\n+\t\tint deref = atom->deref;\n \t\tconst char *refname;\n \t\tstruct branch *branch = NULL;\n \n@@ -1848,11 +1840,6 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\tv->handler = append_atom;\n \t\tv->atom = atom;\n \n-\t\tif (*name == '*') {\n-\t\t\tderef = 1;\n-\t\t\tname++;\n-\t\t}\n-\n \t\tif (atom_type == ATOM_REFNAME)\n \t\t\trefname = get_refname(atom, ref);\n \t\telse if (atom_type == ATOM_WORKTREEPATH) {\n-- \ngitgitgadget\n\n"},{"id":"433726","messageId":"a7dfd0a5866c9c0474b8d02ab7a276d132925bc8.1629882532.git.gitgitgadget@gmail.com","threadId":"56372","inReplyTo":"pull.1025.git.1629882532.gitgitgadget@gmail.com","subject":"[PATCH 8/8] [GSOC] ref-filter: move need_symref, need_tagged into ref_format","fromName":"ZheNing Hu via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2021-08-25T09:08:52Z","receivedAt":"2021-08-25T09:09:12Z","isPatch":true,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"From: ZheNing Hu <adlternative@gmail.com>\n\nThere are many global options variables in ref-filter, e.g.\nneed_tagged, need_symref, which may affect the reentrancy of\nthe functions. Moving these variables into ref_format which\ncan make the code cleaner.\n\nMentored-by: Christian Couder <christian.couder@gmail.com>\nMentored-by: Hariom Verma <hariom18599@gmail.com>\nSigned-off-by: ZheNing Hu <adlternative@gmail.com>\n---\n ref-filter.c | 14 +++++++-------\n ref-filter.h |  2 ++\n 2 files changed, 9 insertions(+), 7 deletions(-)\n\ndiff --git a/ref-filter.c b/ref-filter.c\nindex e4f96dad504..29be1e865d2 100644\n--- a/ref-filter.c\n+++ b/ref-filter.c\n@@ -213,7 +213,7 @@ static struct used_atom {\n \t\tchar *head;\n \t} u;\n } *used_atom;\n-static int used_atom_cnt, need_tagged, need_symref;\n+static int used_atom_cnt;\n \n /*\n  * Expand string, append it to strbuf *sb, then return error code ret.\n@@ -499,7 +499,7 @@ static int person_email_atom_parser(struct ref_format *format, struct used_atom\n static int symref_atom_parser(struct ref_format *format, struct used_atom *atom,\n \t\t\t       const char *arg, struct strbuf *err)\n {\n-\tneed_symref = 1;\n+\tformat->need_symref = 1;\n \treturn refname_atom_parser_internal(&atom->u.refname, arg, atom->name, err);\n }\n \n@@ -769,7 +769,7 @@ static int parse_ref_filter_atom(struct ref_format *format,\n \tif (valid_atom[i].parser && valid_atom[i].parser(format, &used_atom[at], arg, err))\n \t\treturn -1;\n \tif (deref)\n-\t\tneed_tagged = 1;\n+\t\tformat->need_tagged = 1;\n \treturn at;\n }\n \n@@ -1816,10 +1816,10 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \tstruct object *obj;\n \tint i;\n \tstruct object_info empty = OBJECT_INFO_INIT;\n-\n+\tstruct ref_format *format = ref->format;\n \tCALLOC_ARRAY(ref->value, used_atom_cnt);\n \n-\tif (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {\n+\tif (format->need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {\n \t\tref->symref = resolve_refdup(ref->refname, RESOLVE_REF_READING,\n \t\t\t\t\t     NULL, NULL);\n \t\tif (!ref->symref)\n@@ -1958,7 +1958,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t\t\t\t\t       oid_to_hex(&ref->objectname), ref->refname);\n \t}\n \n-\tif (need_tagged)\n+\tif (format->need_tagged)\n \t\toi.info.contentp = &oi.content;\n \tif (!memcmp(&oi.info, &empty, sizeof(empty)) &&\n \t    !memcmp(&oi_deref.info, &empty, sizeof(empty)))\n@@ -1973,7 +1973,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)\n \t * If there is no atom that wants to know about tagged\n \t * object, we are done.\n \t */\n-\tif (!need_tagged || (obj->type != OBJ_TAG))\n+\tif (!format->need_tagged || (obj->type != OBJ_TAG))\n \t\treturn 0;\n \n \t/*\ndiff --git a/ref-filter.h b/ref-filter.h\nindex e95c055fb86..ec4cc1e5f9c 100644\n--- a/ref-filter.h\n+++ b/ref-filter.h\n@@ -86,6 +86,8 @@ struct ref_format {\n \n \t/* Internal state to ref-filter */\n \tint need_color_reset_at_eol;\n+\tint need_tagged;\n+\tint need_symref;\n };\n \n #define REF_FORMAT_INIT { .use_color = -1 }\n-- \ngitgitgadget\n"}]}