{"thread":{"id":"58226","subject":"[PATCH 0/3] log: create tighter default decoration filter","startedAt":"2022-07-26T14:04:17Z","lastAt":"2022-09-09T17:41:41Z","messageCount":79,"participants":["Derrick Stolee via GitGitGadget","Ævar Arnfjörð Bjarmason","Derrick Stolee","Junio C Hamano","Jeff King","Eric Sunshine","Josh Steadmon","Glen Choo"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"459973","messageId":"pull.1301.git.1658844250.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":null,"subject":"[PATCH 0/3] log: create tighter default decoration filter","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-26T14:04:07Z","receivedAt":"2022-07-26T14:04:17Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"When running 'git log', the default is to report any refs within refs/* as\ndecorations. This series reduces the default set to be more specific to a\nset of known-useful namespaces.\n\nThis was previously reduced by adding the log.excludeDecoration config\noption and modifying that config in git maintenance's prefetch task (to hide\nrefs/prefetch/*). I then followed that pattern again for the bundle URI\nfeature [1], but this caught some reviewers by surprise as an unfortunate\nside-effect. This series is a way to roll back the previous decision to use\nlog.excludeDecoration and instead use tighter filters by default.\n\n[1]\nhttps://lore.kernel.org/git/a217e9a0640b45d21ef971d6e91cee3f1993f383.1656535245.git.gitgitgadget@gmail.com/\n\nAs noted in the last patch, the current design ignores the new filters if\nthere are any previously-specified filters. This includes the\nlog.excludeDecorations=refs/prefetch/ set by the git maintenance command.\nThis means that users who ran that command in their repo will not get the\nbenefits of the more strict filters. While we stop writing\nlog.excludeDecorations, we don't remove existing instances of it.\n\nI'm interested if anyone has another way around this issue, or if we\nconsider adding the default filter as long as no --decorate=refs options are\nspecified.\n\nThanks, -Stolee\n\nDerrick Stolee (3):\n  refs: allow \"HEAD\" as decoration filter\n  log: add default decoration filter\n  maintenance: stop writing log.excludeDecoration\n\n Documentation/git-log.txt |  7 ++++--\n builtin/gc.c              |  6 -----\n builtin/log.c             | 53 +++++++++++++++++++++++++++++----------\n refs.c                    |  4 +--\n t/t4202-log.sh            | 29 +++++++++++++++++++++\n t/t7900-maintenance.sh    | 21 ----------------\n 6 files changed, 76 insertions(+), 44 deletions(-)\n\n\nbase-commit: 6a475b71f8c4ce708d69fdc9317aefbde3769e25\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1301%2Fderrickstolee%2Fdecorations-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1301/derrickstolee/decorations-v1\nPull-Request: https://github.com/gitgitgadget/git/pull/1301\n-- \ngitgitgadget\n"},{"id":"459974","messageId":"c2e5a0b3a50237f3b7f5ceb5d05faa83fd41de68.1658844250.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.git.1658844250.gitgitgadget@gmail.com","subject":"[PATCH 1/3] refs: allow \"HEAD\" as decoration filter","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-26T14:04:08Z","receivedAt":"2022-07-26T14:04:19Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe normalize_glob_ref() method was introduced in 65516f586b693 (log:\nadd option to choose which refs to decorate, 2017-11-21) to help with\ndecoration filters such as --decorate-refs=<filter> and\n--decorate-refs-exclude=<filter>. The method has not been used anywhere\nelse.\n\nAt the moment, it is impossible to specify HEAD as a decoration filter\nsince normalize_glob_ref() prepends \"refs/\" to the filter if it isn't\nalready there.\n\nAllow adding HEAD as a decoration filter by allowing the exact string\n\"HEAD\" to not be prepended with \"refs/\". Add a test in t4202-log.sh that\nwould previously fail since the HEAD decoration would exist in the\noutput.\n\nIt is sufficient to only cover \"HEAD\" here and not include other special\nrefs like REBASE_HEAD. This is because HEAD is the only ref outside of\nrefs/* that is added to the list of decorations.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n refs.c         | 4 ++--\n t/t4202-log.sh | 6 ++++++\n 2 files changed, 8 insertions(+), 2 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 90bcb271687..ec3134e4842 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -457,8 +457,8 @@ void normalize_glob_ref(struct string_list_item *item, const char *prefix,\n \n \tif (prefix) {\n \t\tstrbuf_addstr(&normalized_pattern, prefix);\n-\t}\n-\telse if (!starts_with(pattern, \"refs/\"))\n+\t} else if (!starts_with(pattern, \"refs/\") &&\n+\t\t   strcmp(pattern, \"HEAD\"))\n \t\tstrbuf_addstr(&normalized_pattern, \"refs/\");\n \tstrbuf_addstr(&normalized_pattern, pattern);\n \tstrbuf_strip_suffix(&normalized_pattern, \"/\");\ndiff --git a/t/t4202-log.sh b/t/t4202-log.sh\nindex 6e663525582..6b7d8e269f7 100755\n--- a/t/t4202-log.sh\n+++ b/t/t4202-log.sh\n@@ -1025,6 +1025,12 @@ test_expect_success 'decorate-refs and simplify-by-decoration without output' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'decorate-refs-exclude HEAD' '\n+\tgit log --decorate=full --oneline \\\n+\t\t--decorate-refs-exclude=\"HEAD\" >actual &&\n+\t! grep HEAD actual\n+'\n+\n test_expect_success 'log.decorate config parsing' '\n \tgit log --oneline --decorate=full >expect.full &&\n \tgit log --oneline --decorate=short >expect.short &&\n-- \ngitgitgadget\n\n"},{"id":"459975","messageId":"6b40b84773c70244bb13204ec566b713f1bdf865.1658844250.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.git.1658844250.gitgitgadget@gmail.com","subject":"[PATCH 2/3] log: add default decoration filter","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-26T14:04:09Z","receivedAt":"2022-07-26T14:04:25Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nWhen a user runs 'git log', they expect a certain set of helpful\ndecorations. This includes:\n\n* The HEAD ref\n* Branches (refs/heads/)\n* Notes (refs/notes/)\n* Stashes (refs/stash/)\n* Tags (refs/tags/)\n* Remote branches (refs/remotes/)\n\nHowever, there are other refs that are less helpful to show as\ndecoration:\n\n* Prefetch refs (refs/prefetch/)\n* Rebase refs (refs/rebase-merge/ and refs/rebase-apply/)\n* Bundle refs (refs/bundle/) [!]\n\nIn the case of prefetch refs, 96eaffebbf3d0 (maintenance: set\nlog.excludeDecoration durin prefetch, 2021-01-19) added logic to add\nrefs/prefetch/ to the log.excludeDecoration config option. Additional\nfeedback pointed out that having such a side-effect can be confusing and\nperhaps not helpful to users. Instead, we should hide these ref\nnamespaces that are being used by Git for internal reasons but are not\nhelpful for the users to see.\n\nThe way to provide a seamless user experience without setting the config\nis to modify the default decoration filters to match our expectation of\nwhat refs the user actually wants to see.\n\nIn builtin/log.c, after parsing the --decorate-refs and\n--decorate-refs-exclude options from the command-line, call\nset_default_decoration_filter(). This method populates the exclusions\nfrom log.excludeDecoration, then checks if the list of pattern\nmodifications are empty. If none are specified, then the default set is\nrestricted to the set of inclusions mentioned earlier (HEAD, branches,\netc.).\n\nNote that the logic in ref_filter_match() in log-tree.c follows this\nmatching pattern:\n\n 1. If there are exclusion patterns and the ref matches one, then ignore\n    the decoration.\n\n 2. If there are inclusion patterns and the ref matches one, then\n    definitely include the decoration.\n\n 3. If there are config-based exclusions from log.excludeDecoration and\n    the ref matches one, then ignore the decoration.\n\nWith this logic in mind, we need to ensure that we do not populate our\nnew defaults if any of these filters are manually set. Specifically, if\na user runs\n\n\tgit -c log.excludeDecoration=HEAD log\n\nthen we expect the HEAD decoration to not appear. If we left the default\ninclusions in the set, then HEAD would match that inclusion before\nreaching the config-based exclusions.\n\nA potential alternative would be to check the list of default inclusions\nat the end, after the config-based exclusions. This would still create a\nbehavior change for some uses of --decorate-refs-exclude=<X>, and could\nbe overwritten somewhat with --decorate-refs=refs/ and\n--decorate-refs=HEAD. However, it no longer becomes possible to include\nrefs outside of the defaults while also excluding some using\nlog.excludeDecoration.\n\nAdd a test that checks that the defaults are not added when\n--decorate-refs is specified. We verify this by showing that HEAD is not\nincluded as it normally would.  Also add a test that shows that the\ndefault filter avoids the unwanted decorations from refs/prefetch,\nrefs/rebase-merge,\nand refs/bundle.\n\nThere are several tests throughout the codebase that verify that\n--decorate-refs, --decorate-refs-exclude, and log.excludeDecoration work\nas designed and the tests continue to pass without intervention.\n\n[!] The bundle refs are part of a parallel series that bootstraps a repo\nfrom a bundle file, storing the bundle's refs into the repo's\nrefs/bundle/ namespace.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n Documentation/git-log.txt |  7 ++++--\n builtin/log.c             | 53 +++++++++++++++++++++++++++++----------\n t/t4202-log.sh            | 23 +++++++++++++++++\n 3 files changed, 68 insertions(+), 15 deletions(-)\n\ndiff --git a/Documentation/git-log.txt b/Documentation/git-log.txt\nindex 20e87cecf49..14b67f3d058 100644\n--- a/Documentation/git-log.txt\n+++ b/Documentation/git-log.txt\n@@ -45,13 +45,16 @@ OPTIONS\n \n --decorate-refs=<pattern>::\n --decorate-refs-exclude=<pattern>::\n-\tIf no `--decorate-refs` is given, pretend as if all refs were\n-\tincluded.  For each candidate, do not use it for decoration if it\n+\tFor each candidate reference, do not use it for decoration if it\n \tmatches any patterns given to `--decorate-refs-exclude` or if it\n \tdoesn't match any of the patterns given to `--decorate-refs`. The\n \t`log.excludeDecoration` config option allows excluding refs from\n \tthe decorations, but an explicit `--decorate-refs` pattern will\n \toverride a match in `log.excludeDecoration`.\n++\n+If none of these options or config settings are given, then references are\n+used as decoration if they match `HEAD`, `refs/heads/`, `refs/notes/`,\n+`refs/remotes/`, `refs/stash/`, or `refs/tags/`.\n \n --source::\n \tPrint out the ref name given on the command line by which each\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 88a5e98875a..dca06612b8e 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -162,6 +162,40 @@ static void cmd_log_init_defaults(struct rev_info *rev)\n \t\tparse_date_format(default_date_mode, &rev->date_mode);\n }\n \n+static void set_default_decoration_filter(struct decoration_filter *decoration_filter)\n+{\n+\tconst struct string_list *config_exclude =\n+\t\trepo_config_get_value_multi(the_repository, \"log.excludeDecoration\");\n+\n+\tif (config_exclude) {\n+\t\tstruct string_list_item *item;\n+\t\tfor_each_string_list_item(item, config_exclude)\n+\t\t\tstring_list_append(decoration_filter->exclude_ref_config_pattern,\n+\t\t\t\t\t   item->string);\n+\t}\n+\n+\tif (!decoration_filter->exclude_ref_pattern->nr &&\n+\t    !decoration_filter->include_ref_pattern->nr &&\n+\t    !decoration_filter->exclude_ref_config_pattern->nr) {\n+\t\t/*\n+\t\t * No command-line or config options were given, so\n+\t\t * populate with sensible defaults.\n+\t\t */\n+\t\tstring_list_append(decoration_filter->include_ref_pattern,\n+\t\t\t\t   \"refs/heads/\");\n+\t\tstring_list_append(decoration_filter->include_ref_pattern,\n+\t\t\t\t   \"refs/notes/\");\n+\t\tstring_list_append(decoration_filter->include_ref_pattern,\n+\t\t\t\t   \"refs/stash/\");\n+\t\tstring_list_append(decoration_filter->include_ref_pattern,\n+\t\t\t\t   \"refs/tags/\");\n+\t\tstring_list_append(decoration_filter->include_ref_pattern,\n+\t\t\t\t   \"refs/remotes/\");\n+\t\tstring_list_append(decoration_filter->include_ref_pattern,\n+\t\t\t\t   \"HEAD\");\n+\t}\n+}\n+\n static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\t\t struct rev_info *rev, struct setup_revision_opt *opt)\n {\n@@ -171,9 +205,11 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \tstatic struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n \tstatic struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;\n \tstatic struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n-\tstruct decoration_filter decoration_filter = {&decorate_refs_include,\n-\t\t\t\t\t\t      &decorate_refs_exclude,\n-\t\t\t\t\t\t      &decorate_refs_exclude_config};\n+\tstruct decoration_filter decoration_filter = {\n+\t\t.exclude_ref_pattern = &decorate_refs_exclude,\n+\t\t.include_ref_pattern = &decorate_refs_include,\n+\t\t.exclude_ref_config_pattern = &decorate_refs_exclude_config,\n+\t};\n \tstatic struct revision_sources revision_sources;\n \n \tconst struct option builtin_log_options[] = {\n@@ -265,16 +301,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t}\n \n \tif (decoration_style || rev->simplify_by_decoration) {\n-\t\tconst struct string_list *config_exclude =\n-\t\t\trepo_config_get_value_multi(the_repository,\n-\t\t\t\t\t\t    \"log.excludeDecoration\");\n-\n-\t\tif (config_exclude) {\n-\t\t\tstruct string_list_item *item;\n-\t\t\tfor_each_string_list_item(item, config_exclude)\n-\t\t\t\tstring_list_append(&decorate_refs_exclude_config,\n-\t\t\t\t\t\t   item->string);\n-\t\t}\n+\t\tset_default_decoration_filter(&decoration_filter);\n \n \t\tif (decoration_style)\n \t\t\trev->show_decorations = 1;\ndiff --git a/t/t4202-log.sh b/t/t4202-log.sh\nindex 6b7d8e269f7..1a41096c8e2 100755\n--- a/t/t4202-log.sh\n+++ b/t/t4202-log.sh\n@@ -1031,6 +1031,12 @@ test_expect_success 'decorate-refs-exclude HEAD' '\n \t! grep HEAD actual\n '\n \n+test_expect_success 'decorate-refs focus from default' '\n+\tgit log --decorate=full --oneline \\\n+\t\t--decorate-refs=\"refs/heads\" >actual &&\n+\t! grep HEAD actual\n+'\n+\n test_expect_success 'log.decorate config parsing' '\n \tgit log --oneline --decorate=full >expect.full &&\n \tgit log --oneline --decorate=short >expect.short &&\n@@ -2198,6 +2204,23 @@ test_expect_success 'log --decorate includes all levels of tag annotated tags' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'log --decorate does not include things outside filter' '\n+\treflist=\"refs/prefetch/ refs/rebase-merge/ refs/bundle/\" &&\n+\n+\tfor ref in $reflist\n+\tdo\n+\t\tmkdir -p .git/$ref &&\n+\t\techo $(git rev-parse HEAD) >.git/$ref/fake || return 1\n+\tdone &&\n+\n+\tgit log --decorate=full --oneline >actual &&\n+\n+\tfor ref in $reflist\n+\tdo\n+\t\t! grep $ref/fake actual || return 1\n+\tdone\n+'\n+\n test_expect_success 'log --end-of-options' '\n        git update-ref refs/heads/--source HEAD &&\n        git log --end-of-options --source >actual &&\n-- \ngitgitgadget\n\n"},{"id":"459976","messageId":"84fbf16613daa0ff84e1f07d23654a96bd1a8315.1658844250.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.git.1658844250.gitgitgadget@gmail.com","subject":"[PATCH 3/3] maintenance: stop writing log.excludeDecoration","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-26T14:04:10Z","receivedAt":"2022-07-26T14:04:26Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThis reverts commit 96eaffebbf3d0 (maintenance: set\nlog.excludeDecoration durin prefetch, 2021-01-19).\n\nThe previous change created a default decoration filter that does not\ninclude refs/prefetch/, so this modification of the config is no longer\nneeded.\n\nOne issue that can happen from this point on is that users who ran the\nprefetch task on previous versions of Git will still have a\nlog.excludeDecoration value and that will prevent the new default\ndecoration filter from being active. Thus, when we add the refs/bundle/\nnamespace as part of the bundle URI feature, those users will see\nrefs/bundle/ decorations.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n builtin/gc.c           |  6 ------\n t/t7900-maintenance.sh | 21 ---------------------\n 2 files changed, 27 deletions(-)\n\ndiff --git a/builtin/gc.c b/builtin/gc.c\nindex eeff2b760e0..6c222052177 100644\n--- a/builtin/gc.c\n+++ b/builtin/gc.c\n@@ -910,12 +910,6 @@ static int fetch_remote(struct remote *remote, void *cbdata)\n \n static int maintenance_task_prefetch(struct maintenance_run_opts *opts)\n {\n-\tgit_config_set_multivar_gently(\"log.excludedecoration\",\n-\t\t\t\t\t\"refs/prefetch/\",\n-\t\t\t\t\t\"refs/prefetch/\",\n-\t\t\t\t\tCONFIG_FLAGS_FIXED_VALUE |\n-\t\t\t\t\tCONFIG_FLAGS_MULTI_REPLACE);\n-\n \tif (for_each_remote(fetch_remote, opts)) {\n \t\terror(_(\"failed to prefetch remotes\"));\n \t\treturn 1;\ndiff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh\nindex 74aa6384755..62ed694a404 100755\n--- a/t/t7900-maintenance.sh\n+++ b/t/t7900-maintenance.sh\n@@ -162,7 +162,6 @@ test_expect_success 'prefetch multiple remotes' '\n \ttest_cmp_rev refs/remotes/remote1/one refs/prefetch/remotes/remote1/one &&\n \ttest_cmp_rev refs/remotes/remote2/two refs/prefetch/remotes/remote2/two &&\n \n-\ttest_cmp_config refs/prefetch/ log.excludedecoration &&\n \tgit log --oneline --decorate --all >log &&\n \t! grep \"prefetch\" log &&\n \n@@ -173,26 +172,6 @@ test_expect_success 'prefetch multiple remotes' '\n \ttest_subcommand git fetch remote2 $fetchargs <skip-remote1.txt\n '\n \n-test_expect_success 'prefetch and existing log.excludeDecoration values' '\n-\tgit config --unset-all log.excludeDecoration &&\n-\tgit config log.excludeDecoration refs/remotes/remote1/ &&\n-\tgit maintenance run --task=prefetch &&\n-\n-\tgit config --get-all log.excludeDecoration >out &&\n-\tgrep refs/remotes/remote1/ out &&\n-\tgrep refs/prefetch/ out &&\n-\n-\tgit log --oneline --decorate --all >log &&\n-\t! grep \"prefetch\" log &&\n-\t! grep \"remote1\" log &&\n-\tgrep \"remote2\" log &&\n-\n-\t# a second run does not change the config\n-\tgit maintenance run --task=prefetch &&\n-\tgit log --oneline --decorate --all >log2 &&\n-\ttest_cmp log log2\n-'\n-\n test_expect_success 'loose-objects task' '\n \t# Repack everything so we know the state of the object dir\n \tgit repack -adk &&\n-- \ngitgitgadget\n"},{"id":"459977","messageId":"220726.86y1wglyuq.gmgdl@evledraar.gmail.com","threadId":"58226","inReplyTo":"6b40b84773c70244bb13204ec566b713f1bdf865.1658844250.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 2/3] log: add default decoration filter","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-07-26T14:39:06Z","receivedAt":"2022-07-26T14:42:27Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Jul 26 2022, Derrick Stolee via GitGitGadget wrote:\n\n> From: Derrick Stolee <derrickstolee@github.com>\n> [...]\n>  test_expect_success 'log.decorate config parsing' '\n>  \tgit log --oneline --decorate=full >expect.full &&\n>  \tgit log --oneline --decorate=short >expect.short &&\n> @@ -2198,6 +2204,23 @@ test_expect_success 'log --decorate includes all levels of tag annotated tags' '\n>  \ttest_cmp expect actual\n>  '\n>  \n> +test_expect_success 'log --decorate does not include things outside filter' '\n> +\treflist=\"refs/prefetch/ refs/rebase-merge/ refs/bundle/\" &&\n> +\n> +\tfor ref in $reflist\n> +\tdo\n> +\t\tmkdir -p .git/$ref &&\n\nLet's not use -p, and fail if .git doesn't exist?\n\n> +\t\techo $(git rev-parse HEAD) >.git/$ref/fake || return 1\n\nHiding the exit code of the \"git rev-parse here, but aside fram that why\nis the echo needed at all, can't we just:\n\n\tgit rev-parse HEAD >.git/ref/fake\n\nBut even more generally can't we:\n\n\tgit update-ref $ref/fake HEAD\n\n?\n\nIf we need to manually munge the ref store let's add REFFILES prereq.\n"},{"id":"459978","messageId":"220726.86tu73ncf8.gmgdl@evledraar.gmail.com","threadId":"58226","inReplyTo":"pull.1301.git.1658844250.gitgitgadget@gmail.com","subject":"Re: [PATCH 0/3] log: create tighter default decoration filter","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-07-26T14:44:58Z","receivedAt":"2022-07-26T15:04:01Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Jul 26 2022, Derrick Stolee via GitGitGadget wrote:\n\n> This was previously reduced by adding the log.excludeDecoration config\n> option and modifying that config in git maintenance's prefetch task (to hide\n> refs/prefetch/*). I then followed that pattern again for the bundle URI\n> feature [1], but this caught some reviewers by surprise as an unfortunate\n> side-effect. This series is a way to roll back the previous decision to use\n> log.excludeDecoration and instead use tighter filters by default.\n>\n> As noted in the last patch, the current design ignores the new filters if\n> there are any previously-specified filters. This includes the\n> log.excludeDecorations=refs/prefetch/ set by the git maintenance command.\n> This means that users who ran that command in their repo will not get the\n> benefits of the more strict filters. While we stop writing\n> log.excludeDecorations, we don't remove existing instances of it.\n\nLeaving aside the question of these magic refs, and if we need new ones\n(e.g. refs/bundle/*) I have sometimes made use of out-of-standard\nrefspace refs.\n\nE.g. when I build git I create refs/built-tags/* tag object refs\n(i.e. not in refs/tags/*), which is a neat way to get \"git tag -l\" and\nthe like to ignore it.\n\nBut to still have it show decorated in logs (e.g. I'll see what my\n\"private\" branch is at), and \"for-each-ref --contains\" still knows about\nit.\n\nNow, that's a rather obscure use-case, and I suspect other \"special\nrefs\" are similarly obscure (e.g. GitLab's refs/keep-around/* comes to\nmind).\n\nBut I think this change is going about it the wrong way, let's have a\nlist of refs that Git knows about as magical, instead of assuming that\nwe can ignore everything that's not on a small list of things we're\nincluding.\n\nWouldn't that give you what you want, and not exclude these sorts of\ncustom refs unexpectedly for users?\n\n> I'm interested if anyone has another way around this issue, or if we\n> consider adding the default filter as long as no --decorate=refs options are\n> specified.\n\nI think the resulting UX here is bad, in that we ship hardcoded list of\nthese if you don't specify the config in 2/3. So I can do:\n\n      -c log.excludeDecoration=this-will-never-match\n\nTo \"clear\" the list, but not this:\n\n      -c log.excludeDecoration=\n\nWhich we usually have as a synonym for \"false\", is it just adding a\nprefix of \"\" that matches everything to my exclusion list (but HEAD\nstill shows up...).\n\nSpeaking of funny refnames isn't your:\n\n\tgit -c log.excludeDecoration=HEAD log\n\nGoing to exclude refs like \"HEAD/foo/bar\" too? I.e. it's always a\nprefix.\n\nI suspect a much better way out of this, which I think fixes the problem\nyou're raising here is:\n\n\tlog.useBuiltinDecorationExclusions=[bool]\n\nOr whatever, i.e. we ship a hardcoded list of exclusions.\n\nLeaving aside whether that's a blacklist or whitelist, or whether we\nturn that to \"true\" or \"false\" by default it wouldn't have the behavior\nof \"flushing out\" the built-in config.\n\nAnother way of doing that if you really want to use one variable would\nbe to have:\n\n      -c log.excludeDecoration=foo\n\nAdd to the built-in list, but:\n\n      -c log.excludeDecoration=\n      -c log.excludeDecoration=foo\n\nclear it, we have a couple of other list config variables that work that\nway.\n"},{"id":"459979","messageId":"220726.86pmhrnc4x.gmgdl@evledraar.gmail.com","threadId":"58226","inReplyTo":"6b40b84773c70244bb13204ec566b713f1bdf865.1658844250.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 2/3] log: add default decoration filter","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-07-26T15:04:31Z","receivedAt":"2022-07-26T15:10:15Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Jul 26 2022, Derrick Stolee via GitGitGadget wrote:\n\n> +static void set_default_decoration_filter(struct decoration_filter *decoration_filter)\n> +{\n> +\tconst struct string_list *config_exclude =\n> +\t\trepo_config_get_value_multi(the_repository, \"log.excludeDecoration\");\n\nJust use git_config_get_value_multi. It supplies the_repository.\n\n> +\tif (config_exclude) {\n> +\t\tstruct string_list_item *item;\n> +\t\tfor_each_string_list_item(item, config_exclude)\n> +\t\t\tstring_list_append(decoration_filter->exclude_ref_config_pattern,\n> +\t\t\t\t\t   item->string);\n> +\t}\n\nmm, not the first time I've wanted the equivalent of strbuf_addbuf but\nfor a string_list...\n\n> +\n> +\tif (!decoration_filter->exclude_ref_pattern->nr &&\n> +\t    !decoration_filter->include_ref_pattern->nr &&\n> +\t    !decoration_filter->exclude_ref_config_pattern->nr) {\n\nCould return if this isn't true, and save ourselves the subsequent\nindentation...\n\n> +\t\t/*\n> +\t\t * No command-line or config options were given, so\n> +\t\t * populate with sensible defaults.\n> +\t\t */\n> +\t\tstring_list_append(decoration_filter->include_ref_pattern,\n> +\t\t\t\t   \"refs/heads/\");\n> +\t\tstring_list_append(decoration_filter->include_ref_pattern,\n> +\t\t\t\t   \"refs/notes/\");\n> +\t\tstring_list_append(decoration_filter->include_ref_pattern,\n> +\t\t\t\t   \"refs/stash/\");\n> +\t\tstring_list_append(decoration_filter->include_ref_pattern,\n> +\t\t\t\t   \"refs/tags/\");\n> +\t\tstring_list_append(decoration_filter->include_ref_pattern,\n> +\t\t\t\t   \"refs/remotes/\");\n> +\t\tstring_list_append(decoration_filter->include_ref_pattern,\n> +\t\t\t\t   \"HEAD\");\n> +\t}\n> +}\n\nNit: This would be much easier to read if early on there was a:\n\n\tstruct string_list *list = decoration_filter->include_ref_pattern;\n\nYou'd also be able to avoid much of the line wrapping.\n"},{"id":"459980","messageId":"220726.86lesfnc0y.gmgdl@evledraar.gmail.com","threadId":"58226","inReplyTo":"c2e5a0b3a50237f3b7f5ceb5d05faa83fd41de68.1658844250.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 1/3] refs: allow \"HEAD\" as decoration filter","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-07-26T15:10:28Z","receivedAt":"2022-07-26T15:12:35Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Jul 26 2022, Derrick Stolee via GitGitGadget wrote:\n\n> From: Derrick Stolee <derrickstolee@github.com>\n>\n> The normalize_glob_ref() method was introduced in 65516f586b693 (log:\n> add option to choose which refs to decorate, 2017-11-21) to help with\n> decoration filters such as --decorate-refs=<filter> and\n> --decorate-refs-exclude=<filter>. The method has not been used anywhere\n> else.\n>\n> At the moment, it is impossible to specify HEAD as a decoration filter\n> since normalize_glob_ref() prepends \"refs/\" to the filter if it isn't\n> already there.\n>\n> Allow adding HEAD as a decoration filter by allowing the exact string\n> \"HEAD\" to not be prepended with \"refs/\". Add a test in t4202-log.sh that\n> would previously fail since the HEAD decoration would exist in the\n> output.\n>\n> It is sufficient to only cover \"HEAD\" here and not include other special\n> refs like REBASE_HEAD. This is because HEAD is the only ref outside of\n> refs/* that is added to the list of decorations.\n>\n> Signed-off-by: Derrick Stolee <derrickstolee@github.com>\n> ---\n>  refs.c         | 4 ++--\n>  t/t4202-log.sh | 6 ++++++\n>  2 files changed, 8 insertions(+), 2 deletions(-)\n>\n> diff --git a/refs.c b/refs.c\n> index 90bcb271687..ec3134e4842 100644\n> --- a/refs.c\n> +++ b/refs.c\n> @@ -457,8 +457,8 @@ void normalize_glob_ref(struct string_list_item *item, const char *prefix,\n>  \n>  \tif (prefix) {\n>  \t\tstrbuf_addstr(&normalized_pattern, prefix);\n> -\t}\n> -\telse if (!starts_with(pattern, \"refs/\"))\n> +\t} else if (!starts_with(pattern, \"refs/\") &&\n> +\t\t   strcmp(pattern, \"HEAD\"))\n>  \t\tstrbuf_addstr(&normalized_pattern, \"refs/\");\n\nArguably a digression for this series, but I think it would be very nice\nto have a pre-step where we'd create some pre-step to centrally declare\nthese magical refs in some struct whose flags would cover these various\ncases.\n\nE.g. we have this hardcoded in should_autocreate_reflog(), in log-tree.c\n(which AFAICT is the reference to \"HEAD\" here), refs.c etc. etc.\n\n"},{"id":"459985","messageId":"c3b14045-01a1-e207-a60d-2e3290ab8001@github.com","threadId":"58226","inReplyTo":"220726.86tu73ncf8.gmgdl@evledraar.gmail.com","subject":"Re: [PATCH 0/3] log: create tighter default decoration filter","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-07-26T16:38:06Z","receivedAt":"2022-07-26T16:38:13Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 7/26/2022 10:44 AM, Ævar Arnfjörð Bjarmason wrote:\n> \n> On Tue, Jul 26 2022, Derrick Stolee via GitGitGadget wrote:\n> \n>> This was previously reduced by adding the log.excludeDecoration config\n>> option and modifying that config in git maintenance's prefetch task (to hide\n>> refs/prefetch/*). I then followed that pattern again for the bundle URI\n>> feature [1], but this caught some reviewers by surprise as an unfortunate\n>> side-effect. This series is a way to roll back the previous decision to use\n>> log.excludeDecoration and instead use tighter filters by default.\n>>\n>> As noted in the last patch, the current design ignores the new filters if\n>> there are any previously-specified filters. This includes the\n>> log.excludeDecorations=refs/prefetch/ set by the git maintenance command.\n>> This means that users who ran that command in their repo will not get the\n>> benefits of the more strict filters. While we stop writing\n>> log.excludeDecorations, we don't remove existing instances of it.\n> \n> Leaving aside the question of these magic refs, and if we need new ones\n> (e.g. refs/bundle/*) I have sometimes made use of out-of-standard\n> refspace refs.\n> \n> E.g. when I build git I create refs/built-tags/* tag object refs\n> (i.e. not in refs/tags/*), which is a neat way to get \"git tag -l\" and\n> the like to ignore it.\n> \n> But to still have it show decorated in logs (e.g. I'll see what my\n> \"private\" branch is at), and \"for-each-ref --contains\" still knows about\n> it.\n\nYou also have the unfortunate UX of having the refs spelled out entirely\n(\"refs/<special-place>/...\" instead of \"<special-place>/...\" like how\n\"refs/remotes/\" is dropped from remote refs) and not having special color.\nBut that's beside the point.\n\n> Now, that's a rather obscure use-case, and I suspect other \"special\n> refs\" are similarly obscure (e.g. GitLab's refs/keep-around/* comes to\n> mind).\n> \n> But I think this change is going about it the wrong way, let's have a\n> list of refs that Git knows about as magical, instead of assuming that\n> we can ignore everything that's not on a small list of things we're\n> including.\n> \n> Wouldn't that give you what you want, and not exclude these sorts of\n> custom refs unexpectedly for users?\n\nInstead of keeping track of an ever-growing list of exclusions, instead\nmaking a clear list of \"this is what most users will want for their\ndecorations\" is a better approach.\n\nUsers who know how to create custom refs outside of this space have the\ncapability to figure out how to show their special refs. My general ideas\nfor designing these kinds of features is to have a default that is focused\non the typical user while giving config options for experts to tweak those\ndefaults.\n\nYou're right that this series perhaps leaves something to be desired in\nthat second part, since there isn't an easy _config-based_ way to enable\nall decorations (or a small additional subset).\n\n>> I'm interested if anyone has another way around this issue, or if we\n>> consider adding the default filter as long as no --decorate=refs options are\n>> specified.\n> \n> I think the resulting UX here is bad, in that we ship hardcoded list of\n> these if you don't specify the config in 2/3. So I can do:\n> \n>       -c log.excludeDecoration=this-will-never-match\n> \n> To \"clear\" the list, but not this:\n> \n>       -c log.excludeDecoration=\n\nThe thing that I forgot to do, but had considered was adding a\n--decorate-all option to allow clearing the default filters from the\ncommand line. You can already do \"--decorate-refs=refs\" to get everything\n(except HEAD).\n\nAs far as config goes, we could also create a log.includeDecoration key,\nbut we'd want to consider it to populate the same part of the filtering\nalgorithm. Similar to having any instance of log.excludeDecoration, this\nwould clear the default list. To get all decorations again, you could add\nthis to your config file:\n\n\t[log]\n\t\tincludeDecoration = refs\n\t\tincludeDecoration = HEAD\n\nAlternatively, we could instead create a \"filter default\" option such as\n\"log.decorateFilter = (core|all)\" where \"core\" is the default set being\nconsidered by this series, and \"all\" is the empty filter.\n\nThanks,\n-Stolee\n"},{"id":"459995","messageId":"220726.868rofn23f.gmgdl@evledraar.gmail.com","threadId":"58226","inReplyTo":"c3b14045-01a1-e207-a60d-2e3290ab8001@github.com","subject":"Re: [PATCH 0/3] log: create tighter default decoration filter","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-07-26T18:19:40Z","receivedAt":"2022-07-26T18:47:08Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Jul 26 2022, Derrick Stolee wrote:\n\n> On 7/26/2022 10:44 AM, Ævar Arnfjörð Bjarmason wrote:\n>> \n>> On Tue, Jul 26 2022, Derrick Stolee via GitGitGadget wrote:\n>> \n>>> This was previously reduced by adding the log.excludeDecoration config\n>>> option and modifying that config in git maintenance's prefetch task (to hide\n>>> refs/prefetch/*). I then followed that pattern again for the bundle URI\n>>> feature [1], but this caught some reviewers by surprise as an unfortunate\n>>> side-effect. This series is a way to roll back the previous decision to use\n>>> log.excludeDecoration and instead use tighter filters by default.\n>>>\n>>> As noted in the last patch, the current design ignores the new filters if\n>>> there are any previously-specified filters. This includes the\n>>> log.excludeDecorations=refs/prefetch/ set by the git maintenance command.\n>>> This means that users who ran that command in their repo will not get the\n>>> benefits of the more strict filters. While we stop writing\n>>> log.excludeDecorations, we don't remove existing instances of it.\n>> \n>> Leaving aside the question of these magic refs, and if we need new ones\n>> (e.g. refs/bundle/*) I have sometimes made use of out-of-standard\n>> refspace refs.\n>> \n>> E.g. when I build git I create refs/built-tags/* tag object refs\n>> (i.e. not in refs/tags/*), which is a neat way to get \"git tag -l\" and\n>> the like to ignore it.\n>> \n>> But to still have it show decorated in logs (e.g. I'll see what my\n>> \"private\" branch is at), and \"for-each-ref --contains\" still knows about\n>> it.\n>\n> You also have the unfortunate UX of having the refs spelled out entirely\n> (\"refs/<special-place>/...\" instead of \"<special-place>/...\" like how\n> \"refs/remotes/\" is dropped from remote refs) and not having special color.\n> But that's beside the point.\n\nWhether that's unfortunate UX or not is debatable, since we expose the\n\"refs/\" prefix explicitly in other parts of the UX, and e.g. \"HEAD\" or\n\"ORIG_HEAD\" or whatever in in that \"/\"-relation to\n\"refs/heads/whatever\", and not \"heads/whatever\".\n\nE.g. try:\n\n\tmkdir .git/FOO &&\n\tgit rev-parse origin/seen >.git/FOO/BAR &&\n\tgit push origin FOO/BAR:refs/FOO/BAR\n\nAnd then:\n\n\tmkdir .git/refs/FOO &&\n\tgit rev-parse origin/next >.git/refs/FOO/BAR\n\t$ git rev-parse FOO/BAR\n\twarning: object-name.c:970: refname 'FOO/BAR' is ambiguous.\n\t[seen SHA1]\n\t$ git rev-parse refs/FOO/BAR\n\t[next SHA1]\n\nI.e. we really do understand FOO/BAR as meaning .git/FOO/BAR, as opposed\nto .git/refs/FOO/BAR. You really can't assume that you can strip a\n\"refs/\" from a multi-level ref and not end up with ambiguities. It's\n*not* the case that we just have the .git/<UPPER-CASE-HERE> and\n.git/refs/* namespaces, and nothing else.\n\nAre we *almost* there? Yes, I vaguely recall experimenting with trying\nto get us 100% of the way (just locally, didn't make it on-list) a long\ntime ago, and there were some tricky edge cases, and we don't know who\nin the wild is relying on it.\n\nI think it would be interesting to explore getting there, but I don't\nthink eliding information on the display end like that would be the\nright way to start.\n\nAlthough to be fair e.g. \"git for-each-ref\" excludes these entirely, but\nthat's a ref-filter.c specific edge-case, per the above try it on\ne.g. \"git push\", you'll find that you can push one or the other.\n\nI think I was poking at this at the time because I wanted to have \"git\nshow head\" mean the same as \"git show HEAD\", or at least for us to start\nenforcing the rule that thou shalt not use refnames that are head, HeAd\nor whatever mixed-case version we have of our magical all-upper special\nrefs. This matters because you have commands like \"git rev-parse head\"\nthat'll work on case-insensitive FS's that promptly fail on\ncase-sensitive FS's.\n\n>> Now, that's a rather obscure use-case, and I suspect other \"special\n>> refs\" are similarly obscure (e.g. GitLab's refs/keep-around/* comes to\n>> mind).\n>> \n>> But I think this change is going about it the wrong way, let's have a\n>> list of refs that Git knows about as magical, instead of assuming that\n>> we can ignore everything that's not on a small list of things we're\n>> including.\n>> \n>> Wouldn't that give you what you want, and not exclude these sorts of\n>> custom refs unexpectedly for users?\n>\n> Instead of keeping track of an ever-growing list of exclusions, instead\n> making a clear list of \"this is what most users will want for their\n> decorations\" is a better approach.\n>\n> Users who know how to create custom refs outside of this space have the\n> capability to figure out how to show their special refs. My general ideas\n> for designing these kinds of features is to have a default that is focused\n> on the typical user while giving config options for experts to tweak those\n> defaults.\n>\n> You're right that this series perhaps leaves something to be desired in\n> that second part, since there isn't an easy _config-based_ way to enable\n> all decorations (or a small additional subset).\n\nYes, but this is just side-stepping the issue. Your X-Y problem is that\nyou want to exclude certain refs that we're specifically creating.\n\nI think that's fair enough, but I don't see why we're not specifically\nexcluding just those then.\n\nIt'll just be these bundle refs, filter refs, or whatever other magic we\nwant excluded. Why would we extend that to refs that we don't know about?\n\nIt seems like a safe assumption that if we don't know what it is we\nshould include it.\n\nBoth because that's what we do now (least chance of breaking workflows\nin the wild), and because the entire point of the feature is to display\nthe log in relation to points on the ref namespace. If we don't *know*\nthat they're meaningless let's leave them out of the exclusion, no?\n\nI'd also think that we'd want to consider this holistically. I haven't\nchecked, but aside from HEAD (which I think is the only special-case,\nbut maybe I'm wrong) isn't there a one-to-one mapping between what we'll\nshow in decorations, and what \"git for-each-ref\" diplays?\n\n>>> I'm interested if anyone has another way around this issue, or if we\n>>> consider adding the default filter as long as no --decorate=refs options are\n>>> specified.\n>> \n>> I think the resulting UX here is bad, in that we ship hardcoded list of\n>> these if you don't specify the config in 2/3. So I can do:\n>> \n>>       -c log.excludeDecoration=this-will-never-match\n>> \n>> To \"clear\" the list, but not this:\n>> \n>>       -c log.excludeDecoration=\n>\n> The thing that I forgot to do, but had considered was adding a\n> --decorate-all option to allow clearing the default filters from the\n> command line. You can already do \"--decorate-refs=refs\" to get everything\n> (except HEAD).\n\n...and some other exclusions, e.g. it won't show ORIG_HEAD even with\n--decorate-refs=ORIG_HEAD, but perhaps I'm doing it the wrong way...\n\n> As far as config goes, we could also create a log.includeDecoration key,\n> but we'd want to consider it to populate the same part of the filtering\n> algorithm. Similar to having any instance of log.excludeDecoration, this\n> would clear the default list. To get all decorations again, you could add\n> this to your config file:\n>\n> \t[log]\n> \t\tincludeDecoration = refs\n> \t\tincludeDecoration = HEAD\n\nIf we're considering new config I'd think anything that worked like this\ninstead would be *much less* confusing:\n\n\tsome.config = refs/*\n\tsome.config = HEAD\n\nI.e. per the above your HEAD will presumably either match HEAD/BLAH, or\ntreat \"refs\" magically as \"refs/\" and not \"refs\".\n\nNow, I don't think you can delete .git/HEAD and/or make .git/refs a file\nand still have a functioning repository, but the same general rule\napplies to \"FOO\" v.s. \"FOO/BAR\" and \"custom-refs\" or whatever.\n\nWe use that wildcard syntax unambiguously for the refspec matching, we\ncould just use the same machinery to match this.\n\n> Alternatively, we could instead create a \"filter default\" option such as\n> \"log.decorateFilter = (core|all)\" where \"core\" is the default set being\n> considered by this series, and \"all\" is the empty filter.\n\nSure, for any key that takes N arguments we could have some way to say\n\"if you do this it's the same as enumerating these X values\", as long as\nit's not ambiguous whether you mean a special \"aggregate label\" or a\nname of your own...\n"},{"id":"460020","messageId":"69684d1e-ffda-367c-f0ae-2d4a3560be74@github.com","threadId":"58226","inReplyTo":"220726.868rofn23f.gmgdl@evledraar.gmail.com","subject":"Re: [PATCH 0/3] log: create tighter default decoration filter","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-07-27T13:41:15Z","receivedAt":"2022-07-27T13:41:25Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 7/26/22 2:19 PM, Ævar Arnfjörð Bjarmason wrote:\n> \n> On Tue, Jul 26 2022, Derrick Stolee wrote:\n> \n>> On 7/26/2022 10:44 AM, Ævar Arnfjörð Bjarmason wrote:\n\n>>> But I think this change is going about it the wrong way, let's have a\n>>> list of refs that Git knows about as magical, instead of assuming that\n>>> we can ignore everything that's not on a small list of things we're\n>>> including.\n>>>\n>>> Wouldn't that give you what you want, and not exclude these sorts of\n>>> custom refs unexpectedly for users?\n>>\n>> Instead of keeping track of an ever-growing list of exclusions, instead\n>> making a clear list of \"this is what most users will want for their\n>> decorations\" is a better approach.\n>>\n>> Users who know how to create custom refs outside of this space have the\n>> capability to figure out how to show their special refs. My general ideas\n>> for designing these kinds of features is to have a default that is focused\n>> on the typical user while giving config options for experts to tweak those\n>> defaults.\n>>\n>> You're right that this series perhaps leaves something to be desired in\n>> that second part, since there isn't an easy _config-based_ way to enable\n>> all decorations (or a small additional subset).\n> \n> Yes, but this is just side-stepping the issue. Your X-Y problem is that\n> you want to exclude certain refs that we're specifically creating.\n> \n> I think that's fair enough, but I don't see why we're not specifically\n> excluding just those then.\n\nI'm advocating that we make a one-time change to have a set of \"known\nuseful refs\" as showing up in the decorations. Perhaps some users (like\nyourself) need to react to that change, but it happens _once_.\n\nChanging the rules repeatedly as new \"hidden\" namespaces are added is\nmore likely to cause confusion multiple times.\n\nThanks,\n-Stolee\n"},{"id":"460025","messageId":"xmqqczdqtxro.fsf@gitster.g","threadId":"58226","inReplyTo":"6b40b84773c70244bb13204ec566b713f1bdf865.1658844250.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 2/3] log: add default decoration filter","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-07-27T14:50:51Z","receivedAt":"2022-07-27T14:50:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Derrick Stolee <derrickstolee@github.com>\n>\n> When a user runs 'git log', they expect a certain set of helpful\n> decorations. This includes:\n>\n> * The HEAD ref\n\nOK.\n\n> * Branches (refs/heads/)\n\nOK.\n\n> * Notes (refs/notes/)\n\nQuestionable.  None of the notes commits are on the primary history,\nso it is unlikely to be even used for decoration, so it would not\nhurt to have them as part of possible decoration sources, but on the\nother hand, the value of using them is dubious.\n\n> * Stashes (refs/stash/)\n\nQuestionable, for the same reason as 'notes'.\n\n> * Tags (refs/tags/)\n\nAbolutely useful.\n\n> * Remote branches (refs/remotes/)\n\nDitto.\n\n>  --decorate-refs=<pattern>::\n>  --decorate-refs-exclude=<pattern>::\n> -\tIf no `--decorate-refs` is given, pretend as if all refs were\n> -\tincluded.  For each candidate, do not use it for decoration if it\n> +\tFor each candidate reference, do not use it for decoration if it\n>  \tmatches any patterns given to `--decorate-refs-exclude` or if it\n>  \tdoesn't match any of the patterns given to `--decorate-refs`. The\n>  \t`log.excludeDecoration` config option allows excluding refs from\n>  \tthe decorations, but an explicit `--decorate-refs` pattern will\n>  \toverride a match in `log.excludeDecoration`.\n> ++\n> +If none of these options or config settings are given, then references are\n> +used as decoration if they match `HEAD`, `refs/heads/`, `refs/notes/`,\n> +`refs/remotes/`, `refs/stash/`, or `refs/tags/`.\n>  \n>  --source::\n>  \tPrint out the ref name given on the command line by which each\n\nOK.\n\nThanks.\n\n"},{"id":"460026","messageId":"xmqq7d3ytxrm.fsf@gitster.g","threadId":"58226","inReplyTo":"84fbf16613daa0ff84e1f07d23654a96bd1a8315.1658844250.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 3/3] maintenance: stop writing log.excludeDecoration","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-07-27T14:50:53Z","receivedAt":"2022-07-27T14:51:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Derrick Stolee <derrickstolee@github.com>\n>\n> This reverts commit 96eaffebbf3d0 (maintenance: set\n> log.excludeDecoration durin prefetch, 2021-01-19).\n>\n> The previous change created a default decoration filter that does not\n> include refs/prefetch/, so this modification of the config is no longer\n> needed.\n>\n> One issue that can happen from this point on is that users who ran the\n> prefetch task on previous versions of Git will still have a\n> log.excludeDecoration value and that will prevent the new default\n> decoration filter from being active. Thus, when we add the refs/bundle/\n> namespace as part of the bundle URI feature, those users will see\n> refs/bundle/ decorations.\n>\n> Signed-off-by: Derrick Stolee <derrickstolee@github.com>\n> ---\n>  builtin/gc.c           |  6 ------\n>  t/t7900-maintenance.sh | 21 ---------------------\n>  2 files changed, 27 deletions(-)\n\nNice.\n"},{"id":"460031","messageId":"e437576e-537c-ecfb-9143-6e440f3bb893@github.com","threadId":"58226","inReplyTo":"xmqqczdqtxro.fsf@gitster.g","subject":"Re: [PATCH 2/3] log: add default decoration filter","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-07-27T19:07:08Z","receivedAt":"2022-07-27T19:17:31Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 7/27/2022 10:50 AM, Junio C Hamano wrote:\n> \"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n> \n>> From: Derrick Stolee <derrickstolee@github.com>\n>>\n>> When a user runs 'git log', they expect a certain set of helpful\n>> decorations. This includes:\n>>\n>> * The HEAD ref\n> \n> OK.\n> \n>> * Branches (refs/heads/)\n> \n> OK.\n> \n>> * Notes (refs/notes/)\n> \n> Questionable.  None of the notes commits are on the primary history,\n> so it is unlikely to be even used for decoration, so it would not\n> hurt to have them as part of possible decoration sources, but on the\n> other hand, the value of using them is dubious.\n\nI had originally left this out of the filter, but then noticed that test\n4013.102 (git log --decorate --all # magic is (not used)) includes an\ninstance of refs/notes/. Perhaps this is just old test cruft and could be\nchanged.\n\nI could remove this from the filter and change the old test to match the\nnew behavior.\n\n>> * Stashes (refs/stash/)\n> \n> Questionable, for the same reason as 'notes'.\n\nI had also left this out initially, but t4207-log-decoration-colors.sh\nfails, and it's because 'stash' is one of the supported \"slots\" in the\ncolor.decorate.<slot> config option. This elevates the importance of the\nstash refs. (Notes are not a slot in this config option, for instance.)\n\nThe other slot that isn't included in my list is \"grafted\". This includes\ngrafts _and_ replace-objects.  Grafts appear to add decorations in a\ndifferent path that side-steps this filter, but replace-objects are\nsubject to this filter. Things are a bit more complicated here because of\nthe GIT_REPLACE_REF_BASE environment variable.\n\nI'll add replace-objects in the next re-roll using the value of\nGIT_REPLACE_REF_BASE to construct the filter. I'll add some tests to keep\nthe existing behavior, too, especially around color.decorate.grafted.\n\n>> * Tags (refs/tags/)\n> \n> Abolutely useful.\n> \n>> * Remote branches (refs/remotes/)\n> \n> Ditto.\n\nThanks,\n-Stolee\n"},{"id":"460034","messageId":"xmqqk07ys5vu.fsf@gitster.g","threadId":"58226","inReplyTo":"e437576e-537c-ecfb-9143-6e440f3bb893@github.com","subject":"Re: [PATCH 2/3] log: add default decoration filter","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-07-27T19:38:29Z","receivedAt":"2022-07-27T19:38:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Derrick Stolee <derrickstolee@github.com> writes:\n\n>>> * Notes (refs/notes/)\n>> \n>> Questionable.  None of the notes commits are on the primary history,\n>> so it is unlikely to be even used for decoration, so it would not\n>> hurt to have them as part of possible decoration sources, but on the\n>> other hand, the value of using them is dubious.\n>\n> I had originally left this out of the filter, but then noticed that test\n> 4013.102 (git log --decorate --all # magic is (not used)) includes an\n> instance of refs/notes/. Perhaps this is just old test cruft and could be\n> changed.\n>\n> I could remove this from the filter and change the old test to match the\n> new behavior.\n\nI can summarize what I said to \"Keeping this will not hurt, but it\nis unclear if anybody depends on it\"---and I am OK to err on the\nsafe side, i.e. keep notes and stash in the default set.\n"},{"id":"460038","messageId":"220727.86edy6l1jm.gmgdl@evledraar.gmail.com","threadId":"58226","inReplyTo":"69684d1e-ffda-367c-f0ae-2d4a3560be74@github.com","subject":"Re: [PATCH 0/3] log: create tighter default decoration filter","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-07-27T20:40:21Z","receivedAt":"2022-07-27T20:54:11Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Wed, Jul 27 2022, Derrick Stolee wrote:\n\n> On 7/26/22 2:19 PM, Ævar Arnfjörð Bjarmason wrote:\n>> \n>> On Tue, Jul 26 2022, Derrick Stolee wrote:\n>> \n>>> On 7/26/2022 10:44 AM, Ævar Arnfjörð Bjarmason wrote:\n>\n>>>> But I think this change is going about it the wrong way, let's have a\n>>>> list of refs that Git knows about as magical, instead of assuming that\n>>>> we can ignore everything that's not on a small list of things we're\n>>>> including.\n>>>>\n>>>> Wouldn't that give you what you want, and not exclude these sorts of\n>>>> custom refs unexpectedly for users?\n>>>\n>>> Instead of keeping track of an ever-growing list of exclusions, instead\n>>> making a clear list of \"this is what most users will want for their\n>>> decorations\" is a better approach.\n>>>\n>>> Users who know how to create custom refs outside of this space have the\n>>> capability to figure out how to show their special refs. My general ideas\n>>> for designing these kinds of features is to have a default that is focused\n>>> on the typical user while giving config options for experts to tweak those\n>>> defaults.\n>>>\n>>> You're right that this series perhaps leaves something to be desired in\n>>> that second part, since there isn't an easy _config-based_ way to enable\n>>> all decorations (or a small additional subset).\n>> \n>> Yes, but this is just side-stepping the issue. Your X-Y problem is that\n>> you want to exclude certain refs that we're specifically creating.\n>> \n>> I think that's fair enough, but I don't see why we're not specifically\n>> excluding just those then.\n>\n> I'm advocating that we make a one-time change to have a set of \"known\n> useful refs\"\n\nYou can't know the set of known-useful refs. Unless we explicitly lay\nclaim to something in the namespace it's the user's.\n\nThis series seems to have started out by observing that \"git log\" is\nshowing certain \"useless\" refs added in another topic, since they're\nowned by git, and \"internal-only\", which is fair enough.\n\nBut I don't see how we can or should make the leap to things that are\nnot on a limited \"not-useless\" list git knows about should be the only\nthing we should display.\n\nWouldn't carrying a list of what to exclude achive the same goal (but\nsee below...).\n\n> as showing up in the decorations. Perhaps some users (like yourself)\n> need to react to that change, but it happens _once_.\n\nIt's long-established behavior, we try not to change that sort of\nthing. In this case I think we *could*, i.e. I don't imagine it would be\na *huge* disruption if we had a good reason, e.g. the use-cases of\nmachine-parsing this are fairly obscure.\n\nBut the disruption seems unwarranted if it's just to hide the likes of\nrefs/bundle/, when we can just address those specifically.\n\nAnd it's not \"once\", it's N times for each downstream user that'll run\ninto this, whereas not changing the behavior is effort among a small\ngroup of git developers...\n\n> Changing the rules repeatedly as new \"hidden\" namespaces are added is\n> more likely to cause confusion multiple times.\n\nI really don't see the worry about a maintenance burden of having a\nthing in refs.c (or whatever) that's just:\n\n\thide_from_decorate[] = {\n\t\t\"refs/bundle/*\"\n                [...],\n                NULL\n\t};\n\nWorst case we'll create another \"magic\" ref, forget to add to the list,\nand someone will notice and we'll add it.\n\nWhich at that point will be a one-line change, and preferrable to N\nusers having to chase down some new config which explains why their\nlocal refs aren't shown anymore with decorate...\n"},{"id":"460213","messageId":"2bd24a6d-24a0-3910-3418-34e111a11a21@github.com","threadId":"58226","inReplyTo":"220726.86lesfnc0y.gmgdl@evledraar.gmail.com","subject":"Re: [PATCH 1/3] refs: allow \"HEAD\" as decoration filter","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-07-29T13:23:29Z","receivedAt":"2022-07-29T13:23:35Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 7/26/2022 11:10 AM, Ævar Arnfjörð Bjarmason wrote:\n> \n> On Tue, Jul 26 2022, Derrick Stolee via GitGitGadget wrote:\n>>  \tif (prefix) {\n>>  \t\tstrbuf_addstr(&normalized_pattern, prefix);\n>> -\t}\n>> -\telse if (!starts_with(pattern, \"refs/\"))\n>> +\t} else if (!starts_with(pattern, \"refs/\") &&\n>> +\t\t   strcmp(pattern, \"HEAD\"))\n>>  \t\tstrbuf_addstr(&normalized_pattern, \"refs/\");\n> \n> Arguably a digression for this series, but I think it would be very nice\n> to have a pre-step where we'd create some pre-step to centrally declare\n> these magical refs in some struct whose flags would cover these various\n> cases.\n> \n> E.g. we have this hardcoded in should_autocreate_reflog(), in log-tree.c\n> (which AFAICT is the reference to \"HEAD\" here), refs.c etc. etc.\n \nIt's a good idea to collect our known ref namespaces into a\nsingle place so we can update them together when a new feature\nis added. This could help avoid the inconsistencies that already\nexist (such as not filtering \"HEAD\" or not coloring \"refs/notes/\").\n\nThanks,\n-Stolee\n"},{"id":"460215","messageId":"5fb71f12-28c4-3e37-c6c7-e7074872658b@github.com","threadId":"58226","inReplyTo":"220726.86y1wglyuq.gmgdl@evledraar.gmail.com","subject":"Re: [PATCH 2/3] log: add default decoration filter","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-07-29T13:25:15Z","receivedAt":"2022-07-29T13:25:26Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 7/26/2022 10:39 AM, Ævar Arnfjörð Bjarmason wrote:\n> \n> On Tue, Jul 26 2022, Derrick Stolee via GitGitGadget wrote:\n> \n>> From: Derrick Stolee <derrickstolee@github.com>\n>> [...]\n>>  test_expect_success 'log.decorate config parsing' '\n>>  \tgit log --oneline --decorate=full >expect.full &&\n>>  \tgit log --oneline --decorate=short >expect.short &&\n>> @@ -2198,6 +2204,23 @@ test_expect_success 'log --decorate includes all levels of tag annotated tags' '\n>>  \ttest_cmp expect actual\n>>  '\n>>  \n>> +test_expect_success 'log --decorate does not include things outside filter' '\n>> +\treflist=\"refs/prefetch/ refs/rebase-merge/ refs/bundle/\" &&\n>> +\n>> +\tfor ref in $reflist\n>> +\tdo\n>> +\t\tmkdir -p .git/$ref &&\n> \n> Let's not use -p, and fail if .git doesn't exist?\n\nThe reflist contains multi-leveled refs. However, they don't go more than\none level beyond .git/refs/, so -p shouldn't be necessary since .git/refs/\nshould exist.\n \n>> +\t\techo $(git rev-parse HEAD) >.git/$ref/fake || return 1\n> \n> Hiding the exit code of the \"git rev-parse here, but aside fram that why\n> is the echo needed at all, can't we just:\n> \n> \tgit rev-parse HEAD >.git/ref/fake\n> \n> But even more generally can't we:\n> \n> \tgit update-ref $ref/fake HEAD\n> \n> ?\n\nThis was just a brain fart on my part.\n\n> If we need to manually munge the ref store let's add REFFILES prereq.\n\nWe don't. Thanks.\n\n-Stolee\n"},{"id":"460254","messageId":"c2e5a0b3a50237f3b7f5ceb5d05faa83fd41de68.1659122979.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v2.git.1659122979.gitgitgadget@gmail.com","subject":"[PATCH v2 01/10] refs: allow \"HEAD\" as decoration filter","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-29T19:29:30Z","receivedAt":"2022-07-29T19:29:47Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe normalize_glob_ref() method was introduced in 65516f586b693 (log:\nadd option to choose which refs to decorate, 2017-11-21) to help with\ndecoration filters such as --decorate-refs=<filter> and\n--decorate-refs-exclude=<filter>. The method has not been used anywhere\nelse.\n\nAt the moment, it is impossible to specify HEAD as a decoration filter\nsince normalize_glob_ref() prepends \"refs/\" to the filter if it isn't\nalready there.\n\nAllow adding HEAD as a decoration filter by allowing the exact string\n\"HEAD\" to not be prepended with \"refs/\". Add a test in t4202-log.sh that\nwould previously fail since the HEAD decoration would exist in the\noutput.\n\nIt is sufficient to only cover \"HEAD\" here and not include other special\nrefs like REBASE_HEAD. This is because HEAD is the only ref outside of\nrefs/* that is added to the list of decorations.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n refs.c         | 4 ++--\n t/t4202-log.sh | 6 ++++++\n 2 files changed, 8 insertions(+), 2 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 90bcb271687..ec3134e4842 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -457,8 +457,8 @@ void normalize_glob_ref(struct string_list_item *item, const char *prefix,\n \n \tif (prefix) {\n \t\tstrbuf_addstr(&normalized_pattern, prefix);\n-\t}\n-\telse if (!starts_with(pattern, \"refs/\"))\n+\t} else if (!starts_with(pattern, \"refs/\") &&\n+\t\t   strcmp(pattern, \"HEAD\"))\n \t\tstrbuf_addstr(&normalized_pattern, \"refs/\");\n \tstrbuf_addstr(&normalized_pattern, pattern);\n \tstrbuf_strip_suffix(&normalized_pattern, \"/\");\ndiff --git a/t/t4202-log.sh b/t/t4202-log.sh\nindex 6e663525582..6b7d8e269f7 100755\n--- a/t/t4202-log.sh\n+++ b/t/t4202-log.sh\n@@ -1025,6 +1025,12 @@ test_expect_success 'decorate-refs and simplify-by-decoration without output' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'decorate-refs-exclude HEAD' '\n+\tgit log --decorate=full --oneline \\\n+\t\t--decorate-refs-exclude=\"HEAD\" >actual &&\n+\t! grep HEAD actual\n+'\n+\n test_expect_success 'log.decorate config parsing' '\n \tgit log --oneline --decorate=full >expect.full &&\n \tgit log --oneline --decorate=short >expect.short &&\n-- \ngitgitgadget\n\n"},{"id":"460255","messageId":"pull.1301.v2.git.1659122979.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.git.1658844250.gitgitgadget@gmail.com","subject":"[PATCH v2 00/10] log: create tighter default decoration filter","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-29T19:29:29Z","receivedAt":"2022-07-29T19:29:49Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"When running 'git log', the default is to report any refs within refs/* as\ndecorations. This series reduces the default set to be more specific to a\nset of known-useful namespaces.\n\nThis was previously reduced by adding the log.excludeDecoration config\noption and modifying that config in git maintenance's prefetch task (to hide\nrefs/prefetch/*). I then followed that pattern again for the bundle URI\nfeature [1], but this caught some reviewers by surprise as an unfortunate\nside-effect. This series is a way to roll back the previous decision to use\nlog.excludeDecoration and instead use tighter filters by default.\n\n[1]\nhttps://lore.kernel.org/git/a217e9a0640b45d21ef971d6e91cee3f1993f383.1656535245.git.gitgitgadget@gmail.com/\n\nThe current design ignores the new filters if there are any\npreviously-specified filters. This includes the\nlog.excludeDecorations=refs/prefetch/ set by the git maintenance command.\nThis means that users who ran that command in their repo will not get the\nbenefits of the more strict filters. While we stop writing\nlog.excludeDecorations, we don't remove existing instances of it. This\nshould be fine at least for the refs/bundles/ namespace in the future, since\nthose refs will typically be created for new clones that have not yet had\nthe log.excludeDecoration setting.\n\nTo make it easy for users to opt-in to the previous behavior, add a new git\nlog --decorate-all option and log.decorateFilter=all config option.\n\n\nUpdates in v2\n=============\n\n * As discussed in the previous version, there are a lot of places that care\n   about different subsets of the special ref namespaces. This version\n   creates a new ref_namespaces array that centralizes and describes how\n   these known ref namespaces interact with other Git features.\n\n * Some patches are added to help centralize previously-unrelated features\n   onto the ref_namespaces array.\n\n * One thing that I noticed while doing this work was that notes come from a\n   commit history that is pointed by a single ref, not multiple refs in a\n   namespace. Also, that ref can change based on config and environment\n   variables. This version updates that knowledge to allow our\n   ref_namespaces[NAMESPACE_NOTES] value change with these settings. Since\n   there is only one ref, I also chose to remove it from the default\n   decorations. As Junio mentioned, this should not make any difference\n   since a user won't see it unless they purposefully start git log from the\n   notes ref.\n\n * Despite feedback to the opposite, I maintain my opinion that this default\n   filter should be a small list of known-useful namespaces. For expert\n   users who use other namespaces, I added patches that make it easier to\n   show custom namespaces (specifically --decorate-all and\n   log.decorateFilter=all). The logic for creating the default filter now\n   uses the ref_namespaces array in such a way that it would be simple to\n   reverse this decision, and I include that alternate implementation in a\n   commit message.\n\n * This version includes several code and test style improvements.\n\n * The final patch demonstrates how we can remove some duplicate string\n   literals for these namespaces. It is focused on the prefetch namespace\n   (and an adjacent use of the tags namespace) because of how this series\n   changes our handling of that namespace in particular. This makes it\n   easier for a future change to modify the namespace via config or\n   environment variables. There are opportunities to do this kind of update\n   more widely, but I don't want to set that as a critical refactor to do\n   right now.\n\nThanks, -Stolee\n\nDerrick Stolee (10):\n  refs: allow \"HEAD\" as decoration filter\n  t4207: test coloring of grafted decorations\n  refs: add array of ref namespaces\n  refs: use ref_namespaces for replace refs base\n  log-tree: use ref_namespaces instead of if/else-if\n  log: add default decoration filter\n  log: add --decorate-all option\n  log: create log.decorateFilter=all\n  maintenance: stop writing log.excludeDecoration\n  fetch: use ref_namespaces during prefetch\n\n Documentation/config/log.txt                  |   5 +\n Documentation/git-log.txt                     |  14 +-\n builtin/fetch.c                               |   6 +-\n builtin/gc.c                                  |   6 -\n builtin/log.c                                 |  87 +++++++++---\n builtin/replace.c                             |   3 +\n cache.h                                       |   1 -\n environment.c                                 |   5 +-\n log-tree.c                                    |  28 ++--\n notes.c                                       |   1 +\n refs.c                                        |  88 +++++++++++-\n refs.h                                        |  46 ++++++\n t/t4013-diff-various.sh                       |   2 +\n t/t4013/diff.log_--decorate=full_--all        |   2 +-\n ...f.log_--decorate=full_--decorate-all_--all |  61 ++++++++\n t/t4013/diff.log_--decorate_--all             |   2 +-\n .../diff.log_--decorate_--decorate-all_--all  |  61 ++++++++\n t/t4202-log.sh                                | 134 +++++++++++++++++-\n t/t4207-log-decoration-colors.sh              |  59 ++++++++\n t/t7900-maintenance.sh                        |  21 ---\n t/t9902-completion.sh                         |   3 +\n 21 files changed, 568 insertions(+), 67 deletions(-)\n create mode 100644 t/t4013/diff.log_--decorate=full_--decorate-all_--all\n create mode 100644 t/t4013/diff.log_--decorate_--decorate-all_--all\n\n\nbase-commit: 6a475b71f8c4ce708d69fdc9317aefbde3769e25\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1301%2Fderrickstolee%2Fdecorations-v2\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1301/derrickstolee/decorations-v2\nPull-Request: https://github.com/gitgitgadget/git/pull/1301\n\nRange-diff vs v1:\n\n  1:  c2e5a0b3a50 =  1:  c2e5a0b3a50 refs: allow \"HEAD\" as decoration filter\n  -:  ----------- >  2:  b5eb110958b t4207: test coloring of grafted decorations\n  -:  ----------- >  3:  d7486390d57 refs: add array of ref namespaces\n  -:  ----------- >  4:  8da0b0a3181 refs: use ref_namespaces for replace refs base\n  -:  ----------- >  5:  53b15a0b793 log-tree: use ref_namespaces instead of if/else-if\n  2:  6b40b84773c !  6:  bec532fb8c6 log: add default decoration filter\n     @@ Commit message\n      \n          * The HEAD ref\n          * Branches (refs/heads/)\n     -    * Notes (refs/notes/)\n     -    * Stashes (refs/stash/)\n     +    * Stashes (refs/stash)\n          * Tags (refs/tags/)\n          * Remote branches (refs/remotes/)\n     +    * Replace refs (refs/replace/ or $GIT_REPLACE_REF_BASE)\n     +\n     +    Each of these namespaces was selected due to existing test cases that\n     +    verify these namespaces appear in the decorations. In particular,\n     +    stashes and replace refs can have custom colors from the\n     +    color.decorate.<slot> config option.\n     +\n     +    While one test checks for a decoration from notes, it only applies to\n     +    the tip of refs/notes/commit (or its configured ref name). Notes form\n     +    their own kind of decoration instead. Modify the expected output for the\n     +    tests in t4013 that expect this note decoration.  There are several\n     +    tests throughout the codebase that verify that --decorate-refs,\n     +    --decorate-refs-exclude, and log.excludeDecoration work as designed and\n     +    the tests continue to pass without intervention.\n      \n          However, there are other refs that are less helpful to show as\n          decoration:\n     @@ Commit message\n          * Rebase refs (refs/rebase-merge/ and refs/rebase-apply/)\n          * Bundle refs (refs/bundle/) [!]\n      \n     +    [!] The bundle refs are part of a parallel series that bootstraps a repo\n     +        from a bundle file, storing the bundle's refs into the repo's\n     +        refs/bundle/ namespace.\n     +\n          In the case of prefetch refs, 96eaffebbf3d0 (maintenance: set\n          log.excludeDecoration durin prefetch, 2021-01-19) added logic to add\n          refs/prefetch/ to the log.excludeDecoration config option. Additional\n     @@ Commit message\n          from log.excludeDecoration, then checks if the list of pattern\n          modifications are empty. If none are specified, then the default set is\n          restricted to the set of inclusions mentioned earlier (HEAD, branches,\n     -    etc.).\n     +    etc.).  A previous change introduced the ref_namespaces array, which\n     +    includes all of these currently-used namespaces. The 'decoration' value\n     +    is non-zero when that namespace is associated with a special coloring\n     +    and fits into the list of \"expected\" decorations as described above,\n     +    which makes the implementation of this filter very simple.\n      \n          Note that the logic in ref_filter_match() in log-tree.c follows this\n          matching pattern:\n     @@ Commit message\n          refs outside of the defaults while also excluding some using\n          log.excludeDecoration.\n      \n     +    Another alternative would be to exclude the known namespaces that are\n     +    not intended to be shown. This would reduce the visible effect of the\n     +    change for expert users who use their own custom ref namespaces. The\n     +    implementation change would be very simple to swap due to our use of\n     +    ref_namespaces:\n     +\n     +            int i;\n     +            struct string_list *exclude = decoration_filter->exclude_ref_pattern;\n     +\n     +            /*\n     +             * No command-line or config options were given, so\n     +             * populate with sensible defaults.\n     +             */\n     +            for (i = 0; i < NAMESPACE__COUNT; i++) {\n     +                    if (ref_namespaces[i].decoration)\n     +                            continue;\n     +\n     +                    string_list_append(exclude, ref_namespaces[i].ref);\n     +            }\n     +\n     +    The main downside of this approach is that we expect to add new hidden\n     +    namespaces in the future, and that means that Git versions will be less\n     +    stable in how they behave as those namespaces are added.\n     +\n     +    It is critical that we provide ways for expert users to disable this\n     +    behavior change via command-line options and config keys. These changes\n     +    will be implemented in a future change.\n     +\n          Add a test that checks that the defaults are not added when\n          --decorate-refs is specified. We verify this by showing that HEAD is not\n          included as it normally would.  Also add a test that shows that the\n     @@ Commit message\n          refs/rebase-merge,\n          and refs/bundle.\n      \n     -    There are several tests throughout the codebase that verify that\n     -    --decorate-refs, --decorate-refs-exclude, and log.excludeDecoration work\n     -    as designed and the tests continue to pass without intervention.\n     -\n     -    [!] The bundle refs are part of a parallel series that bootstraps a repo\n     -    from a bundle file, storing the bundle's refs into the repo's\n     -    refs/bundle/ namespace.\n     -\n          Signed-off-by: Derrick Stolee <derrickstolee@github.com>\n      \n       ## Documentation/git-log.txt ##\n     @@ Documentation/git-log.txt: OPTIONS\n       \toverride a match in `log.excludeDecoration`.\n      ++\n      +If none of these options or config settings are given, then references are\n     -+used as decoration if they match `HEAD`, `refs/heads/`, `refs/notes/`,\n     -+`refs/remotes/`, `refs/stash/`, or `refs/tags/`.\n     ++used as decoration if they match `HEAD`, `refs/heads/`, `refs/remotes/`,\n     ++`refs/stash/`, or `refs/tags/`.\n       \n       --source::\n       \tPrint out the ref name given on the command line by which each\n     @@ builtin/log.c: static void cmd_log_init_defaults(struct rev_info *rev)\n       \n      +static void set_default_decoration_filter(struct decoration_filter *decoration_filter)\n      +{\n     ++\tint i;\n     ++\tstruct string_list *include = decoration_filter->include_ref_pattern;\n      +\tconst struct string_list *config_exclude =\n     -+\t\trepo_config_get_value_multi(the_repository, \"log.excludeDecoration\");\n     ++\t\t\tgit_config_get_value_multi(\"log.excludeDecoration\");\n      +\n      +\tif (config_exclude) {\n      +\t\tstruct string_list_item *item;\n     @@ builtin/log.c: static void cmd_log_init_defaults(struct rev_info *rev)\n      +\t\t\t\t\t   item->string);\n      +\t}\n      +\n     -+\tif (!decoration_filter->exclude_ref_pattern->nr &&\n     -+\t    !decoration_filter->include_ref_pattern->nr &&\n     -+\t    !decoration_filter->exclude_ref_config_pattern->nr) {\n     -+\t\t/*\n     -+\t\t * No command-line or config options were given, so\n     -+\t\t * populate with sensible defaults.\n     -+\t\t */\n     -+\t\tstring_list_append(decoration_filter->include_ref_pattern,\n     -+\t\t\t\t   \"refs/heads/\");\n     -+\t\tstring_list_append(decoration_filter->include_ref_pattern,\n     -+\t\t\t\t   \"refs/notes/\");\n     -+\t\tstring_list_append(decoration_filter->include_ref_pattern,\n     -+\t\t\t\t   \"refs/stash/\");\n     -+\t\tstring_list_append(decoration_filter->include_ref_pattern,\n     -+\t\t\t\t   \"refs/tags/\");\n     -+\t\tstring_list_append(decoration_filter->include_ref_pattern,\n     -+\t\t\t\t   \"refs/remotes/\");\n     -+\t\tstring_list_append(decoration_filter->include_ref_pattern,\n     -+\t\t\t\t   \"HEAD\");\n     ++\tif (decoration_filter->exclude_ref_pattern->nr ||\n     ++\t    decoration_filter->include_ref_pattern->nr ||\n     ++\t    decoration_filter->exclude_ref_config_pattern->nr)\n     ++\t\treturn;\n     ++\n     ++\t/*\n     ++\t * No command-line or config options were given, so\n     ++\t * populate with sensible defaults.\n     ++\t */\n     ++\tfor (i = 0; i < NAMESPACE__COUNT; i++) {\n     ++\t\tif (!ref_namespaces[i].decoration)\n     ++\t\t\tcontinue;\n     ++\n     ++\t\tstring_list_append(include, ref_namespaces[i].ref);\n      +\t}\n      +}\n      +\n     @@ builtin/log.c: static void cmd_log_init_finish(int argc, const char **argv, cons\n       \t\tif (decoration_style)\n       \t\t\trev->show_decorations = 1;\n      \n     + ## t/t4013/diff.log_--decorate=full_--all ##\n     +@@ t/t4013/diff.log_--decorate=full_--all: Date:   Mon Jun 26 00:06:00 2006 +0000\n     + \n     +     Rearranged lines in dir/sub\n     + \n     +-commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n     ++commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0\n     + Author: A U Thor <author@example.com>\n     + Date:   Mon Jun 26 00:06:00 2006 +0000\n     + \n     +\n     + ## t/t4013/diff.log_--decorate_--all ##\n     +@@ t/t4013/diff.log_--decorate_--all: Date:   Mon Jun 26 00:06:00 2006 +0000\n     + \n     +     Rearranged lines in dir/sub\n     + \n     +-commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n     ++commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0\n     + Author: A U Thor <author@example.com>\n     + Date:   Mon Jun 26 00:06:00 2006 +0000\n     + \n     +\n       ## t/t4202-log.sh ##\n      @@ t/t4202-log.sh: test_expect_success 'decorate-refs-exclude HEAD' '\n       \t! grep HEAD actual\n     @@ t/t4202-log.sh: test_expect_success 'log --decorate includes all levels of tag a\n       '\n       \n      +test_expect_success 'log --decorate does not include things outside filter' '\n     -+\treflist=\"refs/prefetch/ refs/rebase-merge/ refs/bundle/\" &&\n     ++\treflist=\"refs/prefetch refs/rebase-merge refs/bundle\" &&\n      +\n      +\tfor ref in $reflist\n      +\tdo\n     -+\t\tmkdir -p .git/$ref &&\n     -+\t\techo $(git rev-parse HEAD) >.git/$ref/fake || return 1\n     ++\t\tgit update-ref $ref/fake HEAD || return 1\n      +\tdone &&\n      +\n      +\tgit log --decorate=full --oneline >actual &&\n  -:  ----------- >  7:  64ee889369d log: add --decorate-all option\n  -:  ----------- >  8:  8142b32f023 log: create log.decorateFilter=all\n  3:  84fbf16613d =  9:  318269dfe27 maintenance: stop writing log.excludeDecoration\n  -:  ----------- > 10:  8599bb55045 fetch: use ref_namespaces during prefetch\n\n-- \ngitgitgadget\n"},{"id":"460256","messageId":"b5eb110958baa80b72a345b3c850f1dfceabf076.1659122979.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v2.git.1659122979.gitgitgadget@gmail.com","subject":"[PATCH v2 02/10] t4207: test coloring of grafted decorations","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-29T19:29:31Z","receivedAt":"2022-07-29T19:29:50Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe color.decorate.<slot> config option added the 'grafted' slot in\n09c4ba410b0f (log-tree: allow to customize 'grafted' color, 2018-05-26)\nbut included no tests for this behavior. When modifying some logic\naround decorations, this ref namespace was ignored and could have been\nlost as a default namespace for 'git log' decorations by default.\n\nAdd two tests to t4207 that check that the replaced objects are\ncorrectly decorated. Use \"black\" as the color since it is distinct from\nthe other colors already in the test. The first test uses regular\nreplace-objects while the second creates a commit graft.\n\nBe sure to test both modes with GIT_REPLACE_REF_BASE unset and set to an\nalternative base.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n t/t4207-log-decoration-colors.sh | 59 ++++++++++++++++++++++++++++++++\n 1 file changed, 59 insertions(+)\n\ndiff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh\nindex 36ac6aff1e4..69f8ac602d6 100755\n--- a/t/t4207-log-decoration-colors.sh\n+++ b/t/t4207-log-decoration-colors.sh\n@@ -18,6 +18,7 @@ test_expect_success setup '\n \tgit config color.decorate.tag \"reverse bold yellow\" &&\n \tgit config color.decorate.stash magenta &&\n \tgit config color.decorate.HEAD cyan &&\n+\tgit config color.decorate.grafted black &&\n \n \tc_reset=\"<RESET>\" &&\n \n@@ -27,6 +28,7 @@ test_expect_success setup '\n \tc_tag=\"<BOLD;REVERSE;YELLOW>\" &&\n \tc_stash=\"<MAGENTA>\" &&\n \tc_HEAD=\"<CYAN>\" &&\n+\tc_grafted=\"<BLACK>\" &&\n \n \ttest_commit A &&\n \tgit clone . other &&\n@@ -63,4 +65,61 @@ test_expect_success 'Commit Decorations Colored Correctly' '\n \ttest_cmp expected out\n '\n \n+cat >expected <<EOF\n+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD ->\\\n+ ${c_reset}${c_branch}main${c_reset}${c_commit},\\\n+ ${c_reset}${c_tag}tag: D${c_reset}${c_commit})${c_reset} D\n+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: C${c_reset}${c_commit},\\\n+ ${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} B\n+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A\n+EOF\n+\n+test_expect_success 'test coloring with replace-objects' '\n+\ttest_when_finished rm -rf .git/refs/replace* &&\n+\ttest_commit C &&\n+\ttest_commit D &&\n+\n+\tgit replace HEAD~1 HEAD~2 &&\n+\tgit log --first-parent --abbrev=10 --decorate --oneline --color=always HEAD |\n+\tsed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n+\ttest_decode_color >out &&\n+\ttest_cmp expected out &&\n+\tgit replace -d HEAD~1 &&\n+\n+\tGIT_REPLACE_REF_BASE=refs/replace2/ git replace HEAD~1 HEAD~2 &&\n+\tGIT_REPLACE_REF_BASE=refs/replace2/ git log --first-parent --abbrev=10 \\\n+\t\t--decorate --oneline --color=always HEAD |\n+\tsed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n+\ttest_decode_color >out &&\n+\ttest_cmp expected out\n+'\n+\n+cat >expected <<EOF\n+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD ->\\\n+ ${c_reset}${c_branch}main${c_reset}${c_commit},\\\n+ ${c_reset}${c_tag}tag: D${c_reset}${c_commit},\\\n+ ${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} D\n+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit},\\\n+ ${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B\n+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A\n+EOF\n+\n+test_expect_success 'test coloring with grafted commit' '\n+\ttest_when_finished rm -rf .git/refs/replace* &&\n+\n+\tgit replace --graft HEAD HEAD~2 &&\n+\tgit log --first-parent --abbrev=10 --decorate --oneline --color=always HEAD |\n+\tsed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n+\ttest_decode_color >out &&\n+\ttest_cmp expected out &&\n+\tgit replace -d HEAD &&\n+\n+\tGIT_REPLACE_REF_BASE=refs/replace2/ git replace --graft HEAD HEAD~2 &&\n+\tGIT_REPLACE_REF_BASE=refs/replace2/ git log --first-parent --abbrev=10 \\\n+\t\t--decorate --oneline --color=always HEAD |\n+\tsed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n+\ttest_decode_color >out &&\n+\ttest_cmp expected out\n+'\n+\n test_done\n-- \ngitgitgadget\n\n"},{"id":"460257","messageId":"d7486390d57849971ee6a4ac27a0a784c41623ee.1659122979.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v2.git.1659122979.gitgitgadget@gmail.com","subject":"[PATCH v2 03/10] refs: add array of ref namespaces","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-29T19:29:32Z","receivedAt":"2022-07-29T19:29:54Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nGit interprets different meanings to different refs based on their\nnames. Some meanings are cosmetic, like how refs in  'refs/remotes/*'\nare colored differently from refs in 'refs/heads/*'. Others are more\ncritical, such as how replace refs are interpreted.\n\nBefore making behavior changes based on ref namespaces, collect all\nknown ref namespaces into a array of ref_namespace_info structs. This\narray is indexed by the new ref_namespace enum for quick access.\n\nAs of this change, this array is purely documentation. Future changes\nwill add dependencies on this array.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n environment.c |  2 ++\n notes.c       |  1 +\n refs.c        | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++\n refs.h        | 46 ++++++++++++++++++++++++++++\n 4 files changed, 132 insertions(+)\n\ndiff --git a/environment.c b/environment.c\nindex b3296ce7d15..9eb22f975c7 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -185,6 +185,8 @@ void setup_git_env(const char *git_dir)\n \tfree(git_replace_ref_base);\n \tgit_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base\n \t\t\t\t\t\t\t  : \"refs/replace/\");\n+\tupdate_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);\n+\n \tfree(git_namespace);\n \tgit_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));\n \tshallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);\ndiff --git a/notes.c b/notes.c\nindex 7452e71cc8d..7bade6d8f69 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -1005,6 +1005,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,\n \n \tif (!notes_ref)\n \t\tnotes_ref = default_notes_ref();\n+\tupdate_ref_namespace(NAMESPACE_NOTES, xstrdup(notes_ref));\n \n \tif (!combine_notes)\n \t\tcombine_notes = combine_notes_concatenate;\ndiff --git a/refs.c b/refs.c\nindex ec3134e4842..8e87cc7efb0 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -20,6 +20,7 @@\n #include \"repository.h\"\n #include \"sigchain.h\"\n #include \"date.h\"\n+#include \"commit.h\"\n \n /*\n  * List of all available backends\n@@ -56,6 +57,88 @@ static unsigned char refname_disposition[256] = {\n \t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4\n };\n \n+struct ref_namespace_info ref_namespaces[] = {\n+\t[NAMESPACE_HEAD] = {\n+\t\t.ref = \"HEAD\",\n+\t\t.decoration = DECORATION_REF_HEAD,\n+\t\t.exact = 1,\n+\t},\n+\t[NAMESPACE_BRANCHES] = {\n+\t\t.ref = \"refs/heads/\",\n+\t\t.decoration = DECORATION_REF_LOCAL,\n+\t},\n+\t[NAMESPACE_TAGS] = {\n+\t\t.ref = \"refs/tags/\",\n+\t\t.decoration = DECORATION_REF_TAG,\n+\t},\n+\t[NAMESPACE_REMOTE_REFS] = {\n+\t\t/*\n+\t\t * The default refspec for new remotes copies refs from\n+\t\t * refs/heads/ on the remote into refs/remotes/<remote>/.\n+\t\t * As such, \"refs/remotes/\" has special handling.\n+\t\t */\n+\t\t.ref = \"refs/remotes/\",\n+\t\t.decoration = DECORATION_REF_REMOTE,\n+\t},\n+\t[NAMESPACE_STASH] = {\n+\t\t/*\n+\t\t * The single ref \"refs/stash\" stores the latest stash.\n+\t\t * Older stashes can be found in the reflog.\n+\t\t */\n+\t\t.ref = \"refs/stash\",\n+\t\t.exact = 1,\n+\t\t.decoration = DECORATION_REF_STASH,\n+\t},\n+\t[NAMESPACE_REPLACE] = {\n+\t\t/*\n+\t\t * This namespace allows Git to act as if one object ID\n+\t\t * points to the content of another. Unlike the other\n+\t\t * ref namespaces, this one can be changed by the\n+\t\t * GIT_REPLACE_REF_BASE environment variable. This\n+\t\t * .namespace value will be overwritten in setup_git_env().\n+\t\t */\n+\t\t.ref = \"refs/replace/\",\n+\t\t.decoration = DECORATION_GRAFTED,\n+\t},\n+\t[NAMESPACE_NOTES] = {\n+\t\t/*\n+\t\t * The refs/notes/commit ref points to the tip of a\n+\t\t * parallel commit history that adds metadata to commits\n+\t\t * in the normal history. This branch can be overwritten\n+\t\t * by the core.notesRef config variable or the\n+\t\t * GIT_NOTES_REFS environment variable.\n+\t\t */\n+\t\t.ref = \"refs/notes/commit\",\n+\t\t.exact = 1,\n+\t},\n+\t[NAMESPACE_PREFETCH] = {\n+\t\t/*\n+\t\t * Prefetch refs are written by the background 'fetch'\n+\t\t * maintenance task. It allows faster foreground fetches\n+\t\t * by advertising these previously-downloaded tips without\n+\t\t * updating refs/remotes/ without user intervention.\n+\t\t */\n+\t\t.ref = \"refs/prefetch/\",\n+\t},\n+\t[NAMESPACE_REWRITTEN] = {\n+\t\t/*\n+\t\t * Rewritten refs are used by the 'label' command in the\n+\t\t * sequencer. These are particularly useful during an\n+\t\t * interactive rebase that uses the 'merge' command.\n+\t\t */\n+\t\t.ref = \"refs/rewritten/\",\n+\t},\n+};\n+\n+void update_ref_namespace(enum ref_namespace namespace, char *ref)\n+{\n+\tstruct ref_namespace_info *info = &ref_namespaces[namespace];\n+\tif (info->ref_updated)\n+\t\tfree(info->ref);\n+\tinfo->ref = ref;\n+\tinfo->ref_updated = 1;\n+}\n+\n /*\n  * Try to read one refname component from the front of refname.\n  * Return the length of the component found, or -1 if the component is\ndiff --git a/refs.h b/refs.h\nindex 47cb9edbaa8..94e8dedf939 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -2,6 +2,7 @@\n #define REFS_H\n \n #include \"cache.h\"\n+#include \"commit.h\"\n \n struct object_id;\n struct ref_store;\n@@ -930,4 +931,49 @@ struct ref_store *get_main_ref_store(struct repository *r);\n struct ref_store *get_submodule_ref_store(const char *submodule);\n struct ref_store *get_worktree_ref_store(const struct worktree *wt);\n \n+/*\n+ * Some of the names specified by refs have special meaning to Git.\n+ * Organize these namespaces in a comon 'ref_namespaces' array for\n+ * reference from multiple places in the codebase.\n+ */\n+\n+struct ref_namespace_info {\n+\tchar *ref;\n+\tenum decoration_type decoration;\n+\n+\t/*\n+\t * If 'exact' is true, then we must match the 'ref' exactly.\n+\t * Otherwise, use a prefix match.\n+\t *\n+\t * 'orig_ref' is for internal use. It represents whether the\n+\t * 'ref' value was replaced from its original literal version.\n+\t */\n+\tunsigned exact:1,\n+\t\t ref_updated:1;\n+};\n+\n+enum ref_namespace {\n+\tNAMESPACE_HEAD,\n+\tNAMESPACE_BRANCHES,\n+\tNAMESPACE_TAGS,\n+\tNAMESPACE_REMOTE_REFS,\n+\tNAMESPACE_STASH,\n+\tNAMESPACE_REPLACE,\n+\tNAMESPACE_NOTES,\n+\tNAMESPACE_PREFETCH,\n+\tNAMESPACE_REWRITTEN,\n+\n+\t/* Must be last */\n+\tNAMESPACE__COUNT\n+};\n+\n+/* See refs.c for the contents of this array. */\n+extern struct ref_namespace_info ref_namespaces[];\n+\n+/*\n+ * Some ref namespaces can be modified by config values or environment\n+ * variables. Modify a namespace as specified by its ref_namespace key.\n+ */\n+void update_ref_namespace(enum ref_namespace namespace, char *ref);\n+\n #endif /* REFS_H */\n-- \ngitgitgadget\n\n"},{"id":"460258","messageId":"8da0b0a31810c8221ad3ab13b8c41cf1a266c2c0.1659122979.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v2.git.1659122979.gitgitgadget@gmail.com","subject":"[PATCH v2 04/10] refs: use ref_namespaces for replace refs base","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-29T19:29:33Z","receivedAt":"2022-07-29T19:29:55Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe git_replace_ref_base global is used to store the value of the\nGIT_REPLACE_REF_BASE environment variable or the default of\n\"refs/replace/\". This is initialized within setup_git_env().\n\nThe ref_namespaces array is a new centralized location for information\nsuch as the ref namespace used for replace refs. Instead of having this\nnamespace stored in two places, use the ref_namespaces array instead.\n\nFor simplicity, create a local git_replace_ref_base variable wherever\nthe global was previously used.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n builtin/replace.c | 3 +++\n cache.h           | 1 -\n environment.c     | 3 +--\n log-tree.c        | 2 ++\n refs.c            | 1 +\n 5 files changed, 7 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 583702a0980..6b97ef2348b 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -106,6 +106,7 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn)\n \tsize_t base_len;\n \tint had_error = 0;\n \tstruct object_id oid;\n+\tconst char *git_replace_ref_base = ref_namespaces[NAMESPACE_REPLACE].ref;\n \n \tstrbuf_addstr(&ref, git_replace_ref_base);\n \tbase_len = ref.len;\n@@ -147,6 +148,8 @@ static int check_ref_valid(struct object_id *object,\n \t\t\t    struct strbuf *ref,\n \t\t\t    int force)\n {\n+\tconst char *git_replace_ref_base = ref_namespaces[NAMESPACE_REPLACE].ref;\n+\n \tstrbuf_reset(ref);\n \tstrbuf_addf(ref, \"%s%s\", git_replace_ref_base, oid_to_hex(object));\n \tif (check_refname_format(ref->buf, 0))\ndiff --git a/cache.h b/cache.h\nindex ac5ab4ef9d3..631a4f388d6 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1008,7 +1008,6 @@ void reset_shared_repository(void);\n  * commands that do not want replace references to be active.\n  */\n extern int read_replace_refs;\n-extern char *git_replace_ref_base;\n \n /*\n  * These values are used to help identify parts of a repository to fsync.\ndiff --git a/environment.c b/environment.c\nindex 9eb22f975c7..b2004437dce 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -56,7 +56,6 @@ const char *askpass_program;\n const char *excludes_file;\n enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;\n int read_replace_refs = 1;\n-char *git_replace_ref_base;\n enum eol core_eol = EOL_UNSET;\n int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;\n char *check_roundtrip_encoding = \"SHIFT-JIS\";\n@@ -162,6 +161,7 @@ const char *getenv_safe(struct strvec *argv, const char *name)\n \n void setup_git_env(const char *git_dir)\n {\n+\tchar *git_replace_ref_base;\n \tconst char *shallow_file;\n \tconst char *replace_ref_base;\n \tstruct set_gitdir_args args = { NULL };\n@@ -182,7 +182,6 @@ void setup_git_env(const char *git_dir)\n \tif (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))\n \t\tread_replace_refs = 0;\n \treplace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);\n-\tfree(git_replace_ref_base);\n \tgit_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base\n \t\t\t\t\t\t\t  : \"refs/replace/\");\n \tupdate_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);\ndiff --git a/log-tree.c b/log-tree.c\nindex d0ac0a6327a..bb80f1a94d2 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -141,10 +141,12 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,\n \tenum object_type objtype;\n \tenum decoration_type deco_type = DECORATION_NONE;\n \tstruct decoration_filter *filter = (struct decoration_filter *)cb_data;\n+\tconst char *git_replace_ref_base;\n \n \tif (filter && !ref_filter_match(refname, filter))\n \t\treturn 0;\n \n+\tgit_replace_ref_base = ref_namespaces[NAMESPACE_REPLACE].ref;\n \tif (starts_with(refname, git_replace_ref_base)) {\n \t\tstruct object_id original_oid;\n \t\tif (!read_replace_refs)\ndiff --git a/refs.c b/refs.c\nindex 8e87cc7efb0..0da089d760b 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1607,6 +1607,7 @@ int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,\n \n int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data)\n {\n+\tconst char *git_replace_ref_base = ref_namespaces[NAMESPACE_REPLACE].ref;\n \treturn do_for_each_repo_ref(r, git_replace_ref_base, fn,\n \t\t\t\t    strlen(git_replace_ref_base),\n \t\t\t\t    DO_FOR_EACH_INCLUDE_BROKEN, cb_data);\n-- \ngitgitgadget\n\n"},{"id":"460259","messageId":"53b15a0b7932f892505d07a509909b62c473037e.1659122979.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v2.git.1659122979.gitgitgadget@gmail.com","subject":"[PATCH v2 05/10] log-tree: use ref_namespaces instead of if/else-if","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-29T19:29:34Z","receivedAt":"2022-07-29T19:30:04Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe add_ref_decoration() method uses an if/else-if chain to determine if\na ref matches a known ref namespace that has a special decoration\ncategory. That decoration type is later used to assign a color when\nwriting to stdout.\n\nThe newly-added ref_namespaces array contains all namespaces, along\nwith information about their decoration type. Check this array instead\nof this if/else-if chain. This reduces our dependency on string literals\nbeing embedded in the decoration logic.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n log-tree.c | 26 ++++++++++++++++----------\n 1 file changed, 16 insertions(+), 10 deletions(-)\n\ndiff --git a/log-tree.c b/log-tree.c\nindex bb80f1a94d2..6075bdd334e 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -137,6 +137,7 @@ static int ref_filter_match(const char *refname,\n static int add_ref_decoration(const char *refname, const struct object_id *oid,\n \t\t\t      int flags, void *cb_data)\n {\n+\tint i;\n \tstruct object *obj;\n \tenum object_type objtype;\n \tenum decoration_type deco_type = DECORATION_NONE;\n@@ -167,16 +168,21 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,\n \t\treturn 0;\n \tobj = lookup_object_by_type(the_repository, oid, objtype);\n \n-\tif (starts_with(refname, \"refs/heads/\"))\n-\t\tdeco_type = DECORATION_REF_LOCAL;\n-\telse if (starts_with(refname, \"refs/remotes/\"))\n-\t\tdeco_type = DECORATION_REF_REMOTE;\n-\telse if (starts_with(refname, \"refs/tags/\"))\n-\t\tdeco_type = DECORATION_REF_TAG;\n-\telse if (!strcmp(refname, \"refs/stash\"))\n-\t\tdeco_type = DECORATION_REF_STASH;\n-\telse if (!strcmp(refname, \"HEAD\"))\n-\t\tdeco_type = DECORATION_REF_HEAD;\n+\tfor (i = 0; i < NAMESPACE__COUNT; i++) {\n+\t\tstruct ref_namespace_info *info = &ref_namespaces[i];\n+\n+\t\tif (!info->decoration)\n+\t\t\tcontinue;\n+\t\tif (info->exact) {\n+\t\t\tif (!strcmp(refname, info->ref)) {\n+\t\t\t\tdeco_type = info->decoration;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t} else if (starts_with(refname, info->ref)) {\n+\t\t\tdeco_type = info->decoration;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n \n \tadd_name_decoration(deco_type, refname, obj);\n \twhile (obj->type == OBJ_TAG) {\n-- \ngitgitgadget\n\n"},{"id":"460260","messageId":"bec532fb8c63b3ae784d442f438687a4f0bbad37.1659122979.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v2.git.1659122979.gitgitgadget@gmail.com","subject":"[PATCH v2 06/10] log: add default decoration filter","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-29T19:29:35Z","receivedAt":"2022-07-29T19:30:10Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nWhen a user runs 'git log', they expect a certain set of helpful\ndecorations. This includes:\n\n* The HEAD ref\n* Branches (refs/heads/)\n* Stashes (refs/stash)\n* Tags (refs/tags/)\n* Remote branches (refs/remotes/)\n* Replace refs (refs/replace/ or $GIT_REPLACE_REF_BASE)\n\nEach of these namespaces was selected due to existing test cases that\nverify these namespaces appear in the decorations. In particular,\nstashes and replace refs can have custom colors from the\ncolor.decorate.<slot> config option.\n\nWhile one test checks for a decoration from notes, it only applies to\nthe tip of refs/notes/commit (or its configured ref name). Notes form\ntheir own kind of decoration instead. Modify the expected output for the\ntests in t4013 that expect this note decoration.  There are several\ntests throughout the codebase that verify that --decorate-refs,\n--decorate-refs-exclude, and log.excludeDecoration work as designed and\nthe tests continue to pass without intervention.\n\nHowever, there are other refs that are less helpful to show as\ndecoration:\n\n* Prefetch refs (refs/prefetch/)\n* Rebase refs (refs/rebase-merge/ and refs/rebase-apply/)\n* Bundle refs (refs/bundle/) [!]\n\n[!] The bundle refs are part of a parallel series that bootstraps a repo\n    from a bundle file, storing the bundle's refs into the repo's\n    refs/bundle/ namespace.\n\nIn the case of prefetch refs, 96eaffebbf3d0 (maintenance: set\nlog.excludeDecoration durin prefetch, 2021-01-19) added logic to add\nrefs/prefetch/ to the log.excludeDecoration config option. Additional\nfeedback pointed out that having such a side-effect can be confusing and\nperhaps not helpful to users. Instead, we should hide these ref\nnamespaces that are being used by Git for internal reasons but are not\nhelpful for the users to see.\n\nThe way to provide a seamless user experience without setting the config\nis to modify the default decoration filters to match our expectation of\nwhat refs the user actually wants to see.\n\nIn builtin/log.c, after parsing the --decorate-refs and\n--decorate-refs-exclude options from the command-line, call\nset_default_decoration_filter(). This method populates the exclusions\nfrom log.excludeDecoration, then checks if the list of pattern\nmodifications are empty. If none are specified, then the default set is\nrestricted to the set of inclusions mentioned earlier (HEAD, branches,\netc.).  A previous change introduced the ref_namespaces array, which\nincludes all of these currently-used namespaces. The 'decoration' value\nis non-zero when that namespace is associated with a special coloring\nand fits into the list of \"expected\" decorations as described above,\nwhich makes the implementation of this filter very simple.\n\nNote that the logic in ref_filter_match() in log-tree.c follows this\nmatching pattern:\n\n 1. If there are exclusion patterns and the ref matches one, then ignore\n    the decoration.\n\n 2. If there are inclusion patterns and the ref matches one, then\n    definitely include the decoration.\n\n 3. If there are config-based exclusions from log.excludeDecoration and\n    the ref matches one, then ignore the decoration.\n\nWith this logic in mind, we need to ensure that we do not populate our\nnew defaults if any of these filters are manually set. Specifically, if\na user runs\n\n\tgit -c log.excludeDecoration=HEAD log\n\nthen we expect the HEAD decoration to not appear. If we left the default\ninclusions in the set, then HEAD would match that inclusion before\nreaching the config-based exclusions.\n\nA potential alternative would be to check the list of default inclusions\nat the end, after the config-based exclusions. This would still create a\nbehavior change for some uses of --decorate-refs-exclude=<X>, and could\nbe overwritten somewhat with --decorate-refs=refs/ and\n--decorate-refs=HEAD. However, it no longer becomes possible to include\nrefs outside of the defaults while also excluding some using\nlog.excludeDecoration.\n\nAnother alternative would be to exclude the known namespaces that are\nnot intended to be shown. This would reduce the visible effect of the\nchange for expert users who use their own custom ref namespaces. The\nimplementation change would be very simple to swap due to our use of\nref_namespaces:\n\n\tint i;\n\tstruct string_list *exclude = decoration_filter->exclude_ref_pattern;\n\n\t/*\n\t * No command-line or config options were given, so\n\t * populate with sensible defaults.\n\t */\n\tfor (i = 0; i < NAMESPACE__COUNT; i++) {\n\t\tif (ref_namespaces[i].decoration)\n\t\t\tcontinue;\n\n\t\tstring_list_append(exclude, ref_namespaces[i].ref);\n\t}\n\nThe main downside of this approach is that we expect to add new hidden\nnamespaces in the future, and that means that Git versions will be less\nstable in how they behave as those namespaces are added.\n\nIt is critical that we provide ways for expert users to disable this\nbehavior change via command-line options and config keys. These changes\nwill be implemented in a future change.\n\nAdd a test that checks that the defaults are not added when\n--decorate-refs is specified. We verify this by showing that HEAD is not\nincluded as it normally would.  Also add a test that shows that the\ndefault filter avoids the unwanted decorations from refs/prefetch,\nrefs/rebase-merge,\nand refs/bundle.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n Documentation/git-log.txt              |  7 ++--\n builtin/log.c                          | 50 +++++++++++++++++++-------\n t/t4013/diff.log_--decorate=full_--all |  2 +-\n t/t4013/diff.log_--decorate_--all      |  2 +-\n t/t4202-log.sh                         | 22 ++++++++++++\n 5 files changed, 66 insertions(+), 17 deletions(-)\n\ndiff --git a/Documentation/git-log.txt b/Documentation/git-log.txt\nindex 20e87cecf49..b2ac89dfafc 100644\n--- a/Documentation/git-log.txt\n+++ b/Documentation/git-log.txt\n@@ -45,13 +45,16 @@ OPTIONS\n \n --decorate-refs=<pattern>::\n --decorate-refs-exclude=<pattern>::\n-\tIf no `--decorate-refs` is given, pretend as if all refs were\n-\tincluded.  For each candidate, do not use it for decoration if it\n+\tFor each candidate reference, do not use it for decoration if it\n \tmatches any patterns given to `--decorate-refs-exclude` or if it\n \tdoesn't match any of the patterns given to `--decorate-refs`. The\n \t`log.excludeDecoration` config option allows excluding refs from\n \tthe decorations, but an explicit `--decorate-refs` pattern will\n \toverride a match in `log.excludeDecoration`.\n++\n+If none of these options or config settings are given, then references are\n+used as decoration if they match `HEAD`, `refs/heads/`, `refs/remotes/`,\n+`refs/stash/`, or `refs/tags/`.\n \n --source::\n \tPrint out the ref name given on the command line by which each\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 88a5e98875a..0b5efc9434c 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -162,6 +162,37 @@ static void cmd_log_init_defaults(struct rev_info *rev)\n \t\tparse_date_format(default_date_mode, &rev->date_mode);\n }\n \n+static void set_default_decoration_filter(struct decoration_filter *decoration_filter)\n+{\n+\tint i;\n+\tstruct string_list *include = decoration_filter->include_ref_pattern;\n+\tconst struct string_list *config_exclude =\n+\t\t\tgit_config_get_value_multi(\"log.excludeDecoration\");\n+\n+\tif (config_exclude) {\n+\t\tstruct string_list_item *item;\n+\t\tfor_each_string_list_item(item, config_exclude)\n+\t\t\tstring_list_append(decoration_filter->exclude_ref_config_pattern,\n+\t\t\t\t\t   item->string);\n+\t}\n+\n+\tif (decoration_filter->exclude_ref_pattern->nr ||\n+\t    decoration_filter->include_ref_pattern->nr ||\n+\t    decoration_filter->exclude_ref_config_pattern->nr)\n+\t\treturn;\n+\n+\t/*\n+\t * No command-line or config options were given, so\n+\t * populate with sensible defaults.\n+\t */\n+\tfor (i = 0; i < NAMESPACE__COUNT; i++) {\n+\t\tif (!ref_namespaces[i].decoration)\n+\t\t\tcontinue;\n+\n+\t\tstring_list_append(include, ref_namespaces[i].ref);\n+\t}\n+}\n+\n static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\t\t struct rev_info *rev, struct setup_revision_opt *opt)\n {\n@@ -171,9 +202,11 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \tstatic struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n \tstatic struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;\n \tstatic struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n-\tstruct decoration_filter decoration_filter = {&decorate_refs_include,\n-\t\t\t\t\t\t      &decorate_refs_exclude,\n-\t\t\t\t\t\t      &decorate_refs_exclude_config};\n+\tstruct decoration_filter decoration_filter = {\n+\t\t.exclude_ref_pattern = &decorate_refs_exclude,\n+\t\t.include_ref_pattern = &decorate_refs_include,\n+\t\t.exclude_ref_config_pattern = &decorate_refs_exclude_config,\n+\t};\n \tstatic struct revision_sources revision_sources;\n \n \tconst struct option builtin_log_options[] = {\n@@ -265,16 +298,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t}\n \n \tif (decoration_style || rev->simplify_by_decoration) {\n-\t\tconst struct string_list *config_exclude =\n-\t\t\trepo_config_get_value_multi(the_repository,\n-\t\t\t\t\t\t    \"log.excludeDecoration\");\n-\n-\t\tif (config_exclude) {\n-\t\t\tstruct string_list_item *item;\n-\t\t\tfor_each_string_list_item(item, config_exclude)\n-\t\t\t\tstring_list_append(&decorate_refs_exclude_config,\n-\t\t\t\t\t\t   item->string);\n-\t\t}\n+\t\tset_default_decoration_filter(&decoration_filter);\n \n \t\tif (decoration_style)\n \t\t\trev->show_decorations = 1;\ndiff --git a/t/t4013/diff.log_--decorate=full_--all b/t/t4013/diff.log_--decorate=full_--all\nindex 3f9b872eceb..6b0b334a5d6 100644\n--- a/t/t4013/diff.log_--decorate=full_--all\n+++ b/t/t4013/diff.log_--decorate=full_--all\n@@ -20,7 +20,7 @@ Date:   Mon Jun 26 00:06:00 2006 +0000\n \n     Rearranged lines in dir/sub\n \n-commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n+commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0\n Author: A U Thor <author@example.com>\n Date:   Mon Jun 26 00:06:00 2006 +0000\n \ndiff --git a/t/t4013/diff.log_--decorate_--all b/t/t4013/diff.log_--decorate_--all\nindex f5e20e1e14a..c7df1f58141 100644\n--- a/t/t4013/diff.log_--decorate_--all\n+++ b/t/t4013/diff.log_--decorate_--all\n@@ -20,7 +20,7 @@ Date:   Mon Jun 26 00:06:00 2006 +0000\n \n     Rearranged lines in dir/sub\n \n-commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n+commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0\n Author: A U Thor <author@example.com>\n Date:   Mon Jun 26 00:06:00 2006 +0000\n \ndiff --git a/t/t4202-log.sh b/t/t4202-log.sh\nindex 6b7d8e269f7..9ea9e835d43 100755\n--- a/t/t4202-log.sh\n+++ b/t/t4202-log.sh\n@@ -1031,6 +1031,12 @@ test_expect_success 'decorate-refs-exclude HEAD' '\n \t! grep HEAD actual\n '\n \n+test_expect_success 'decorate-refs focus from default' '\n+\tgit log --decorate=full --oneline \\\n+\t\t--decorate-refs=\"refs/heads\" >actual &&\n+\t! grep HEAD actual\n+'\n+\n test_expect_success 'log.decorate config parsing' '\n \tgit log --oneline --decorate=full >expect.full &&\n \tgit log --oneline --decorate=short >expect.short &&\n@@ -2198,6 +2204,22 @@ test_expect_success 'log --decorate includes all levels of tag annotated tags' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'log --decorate does not include things outside filter' '\n+\treflist=\"refs/prefetch refs/rebase-merge refs/bundle\" &&\n+\n+\tfor ref in $reflist\n+\tdo\n+\t\tgit update-ref $ref/fake HEAD || return 1\n+\tdone &&\n+\n+\tgit log --decorate=full --oneline >actual &&\n+\n+\tfor ref in $reflist\n+\tdo\n+\t\t! grep $ref/fake actual || return 1\n+\tdone\n+'\n+\n test_expect_success 'log --end-of-options' '\n        git update-ref refs/heads/--source HEAD &&\n        git log --end-of-options --source >actual &&\n-- \ngitgitgadget\n\n"},{"id":"460261","messageId":"8142b32f023685c78936a618d7b93aaf86ba77fb.1659122979.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v2.git.1659122979.gitgitgadget@gmail.com","subject":"[PATCH v2 08/10] log: create log.decorateFilter=all","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-29T19:29:37Z","receivedAt":"2022-07-29T19:30:15Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe previous change introduced the --decorate-all option for users who\ndo not want their decorations limited to a narrow set of ref namespaces.\n\nAdd a config option that is equivalent to specifying --decorate-all by\ndefault.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n Documentation/config/log.txt |  5 +++++\n Documentation/git-log.txt    |  4 +++-\n builtin/log.c                | 12 ++++++++++++\n t/t4202-log.sh               |  3 +++\n t/t9902-completion.sh        |  3 +++\n 5 files changed, 26 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/config/log.txt b/Documentation/config/log.txt\nindex 456eb07800c..615cb26e5c9 100644\n--- a/Documentation/config/log.txt\n+++ b/Documentation/config/log.txt\n@@ -18,6 +18,11 @@ log.decorate::\n \tnames are shown. This is the same as the `--decorate` option\n \tof the `git log`.\n \n+log.decorateFilter::\n+\tBy default, `git log` only shows decorations for certain known ref\n+\tnamespaces. If 'all' is specified, then show all possible ref\n+\tdecorations. Default value is 'default'.\n+\n log.excludeDecoration::\n \tExclude the specified patterns from the log decorations. This is\n \tsimilar to the `--decorate-refs-exclude` command-line option, but\ndiff --git a/Documentation/git-log.txt b/Documentation/git-log.txt\nindex 633705bde90..c35f9b8ad9e 100644\n--- a/Documentation/git-log.txt\n+++ b/Documentation/git-log.txt\n@@ -59,7 +59,9 @@ used as decoration if they match `HEAD`, `refs/heads/`, `refs/remotes/`,\n --decorate-all::\n \tWhen specified, this option clears all previous `--decorate-refs`\n \tor `--decorate-refs-exclude` options and relaxes the default\n-\tdecoration filter to include all possible decoration refs.\n+\tdecoration filter to include all possible decoration refs. This\n+\toption is assumed if the config value `log.decorateFilter` is set\n+\tto `all`.\n \n --source::\n \tPrint out the ref name given on the command line by which each\ndiff --git a/builtin/log.c b/builtin/log.c\nindex b7fc4946c35..961fe3ae45b 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -184,6 +184,7 @@ static void cmd_log_init_defaults(struct rev_info *rev)\n static void set_default_decoration_filter(struct decoration_filter *decoration_filter)\n {\n \tint i;\n+\tchar *value = NULL;\n \tstruct string_list *include = decoration_filter->include_ref_pattern;\n \tconst struct string_list *config_exclude =\n \t\t\tgit_config_get_value_multi(\"log.excludeDecoration\");\n@@ -195,6 +196,17 @@ static void set_default_decoration_filter(struct decoration_filter *decoration_f\n \t\t\t\t\t   item->string);\n \t}\n \n+\t/*\n+\t * By default, decorate_all is disabled. Enable it if\n+\t * log.decorateMode=all. Don't ever disable it by config, since\n+\t * the command-line takes precedent.\n+\t */\n+\tif (!decorate_all &&\n+\t    !git_config_get_string(\"log.decoratefilter\", &value) &&\n+\t    !strcmp(\"all\", value))\n+\t\tdecorate_all = 1;\n+\tfree(value);\n+\n \tif (decorate_all ||\n \t    decoration_filter->exclude_ref_pattern->nr ||\n \t    decoration_filter->include_ref_pattern->nr ||\ndiff --git a/t/t4202-log.sh b/t/t4202-log.sh\nindex e939ed34ff7..6d96710fdfa 100755\n--- a/t/t4202-log.sh\n+++ b/t/t4202-log.sh\n@@ -1090,6 +1090,9 @@ test_expect_success '--decorate-all overrides defaults' '\n \tEOF\n \tgit log --decorate=full --pretty=\"tformat:%f%d\" \\\n \t\t--decorate-all >actual &&\n+\ttest_cmp expect.all actual &&\n+\tgit -c log.decorateFilter=all log \\\n+\t\t--decorate=full --pretty=\"tformat:%f%d\" >actual &&\n \ttest_cmp expect.all actual\n '\n \ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 31526e6b641..7a0c7b3c372 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -2489,6 +2489,7 @@ test_expect_success 'git config - variable name' '\n \ttest_completion \"git config log.d\" <<-\\EOF\n \tlog.date Z\n \tlog.decorate Z\n+\tlog.decorateFilter Z\n \tlog.diffMerges Z\n \tEOF\n '\n@@ -2511,6 +2512,7 @@ test_expect_success 'git -c - variable name' '\n \ttest_completion \"git -c log.d\" <<-\\EOF\n \tlog.date=Z\n \tlog.decorate=Z\n+\tlog.decorateFilter=Z\n \tlog.diffMerges=Z\n \tEOF\n '\n@@ -2533,6 +2535,7 @@ test_expect_success 'git clone --config= - variable name' '\n \ttest_completion \"git clone --config=log.d\" <<-\\EOF\n \tlog.date=Z\n \tlog.decorate=Z\n+\tlog.decorateFilter=Z\n \tlog.diffMerges=Z\n \tEOF\n '\n-- \ngitgitgadget\n\n"},{"id":"460262","messageId":"8599bb550457ea0edb3c412e84ee688061883e7f.1659122979.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v2.git.1659122979.gitgitgadget@gmail.com","subject":"[PATCH v2 10/10] fetch: use ref_namespaces during prefetch","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-29T19:29:39Z","receivedAt":"2022-07-29T19:30:17Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe \"refs/prefetch/\" namespace is used by 'git fetch --prefetch' as a\nreplacement of the destination of the refpsec for a remote. Git also\nremoves refspecs that include tags.\n\nInstead of using string literals for the 'refs/tags/ and\n'refs/prefetch/' namespaces, use the entries in the ref_namespaces\narray.\n\nThis kind of change could be done in many places around the codebase,\nbut we are isolating only to this change because of the way the\nrefs/prefetch/ namespace somewhat motivated the creation of the\nref_namespaces array.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n builtin/fetch.c | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/fetch.c b/builtin/fetch.c\nindex fc5cecb4835..004d92b3554 100644\n--- a/builtin/fetch.c\n+++ b/builtin/fetch.c\n@@ -490,7 +490,9 @@ static void filter_prefetch_refspec(struct refspec *rs)\n \t\t\tcontinue;\n \t\tif (!rs->items[i].dst ||\n \t\t    (rs->items[i].src &&\n-\t\t     !strncmp(rs->items[i].src, \"refs/tags/\", 10))) {\n+\t\t     !strncmp(rs->items[i].src,\n+\t\t\t      ref_namespaces[NAMESPACE_TAGS].ref,\n+\t\t\t      strlen(ref_namespaces[NAMESPACE_TAGS].ref)))) {\n \t\t\tint j;\n \n \t\t\tfree(rs->items[i].src);\n@@ -506,7 +508,7 @@ static void filter_prefetch_refspec(struct refspec *rs)\n \t\t}\n \n \t\told_dst = rs->items[i].dst;\n-\t\tstrbuf_addstr(&new_dst, \"refs/prefetch/\");\n+\t\tstrbuf_addstr(&new_dst, ref_namespaces[NAMESPACE_PREFETCH].ref);\n \n \t\t/*\n \t\t * If old_dst starts with \"refs/\", then place\n-- \ngitgitgadget\n"},{"id":"460263","messageId":"64ee889369dd4044a4acd967876476ea6cfff1c3.1659122979.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v2.git.1659122979.gitgitgadget@gmail.com","subject":"[PATCH v2 07/10] log: add --decorate-all option","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-29T19:29:36Z","receivedAt":"2022-07-29T19:30:20Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n Documentation/git-log.txt                     |   5 +\n builtin/log.c                                 |  27 ++++-\n t/t4013-diff-various.sh                       |   2 +\n ...f.log_--decorate=full_--decorate-all_--all |  61 +++++++++++\n .../diff.log_--decorate_--decorate-all_--all  |  61 +++++++++++\n t/t4202-log.sh                                | 103 +++++++++++++++++-\n 6 files changed, 252 insertions(+), 7 deletions(-)\n create mode 100644 t/t4013/diff.log_--decorate=full_--decorate-all_--all\n create mode 100644 t/t4013/diff.log_--decorate_--decorate-all_--all\n\ndiff --git a/Documentation/git-log.txt b/Documentation/git-log.txt\nindex b2ac89dfafc..633705bde90 100644\n--- a/Documentation/git-log.txt\n+++ b/Documentation/git-log.txt\n@@ -56,6 +56,11 @@ If none of these options or config settings are given, then references are\n used as decoration if they match `HEAD`, `refs/heads/`, `refs/remotes/`,\n `refs/stash/`, or `refs/tags/`.\n \n+--decorate-all::\n+\tWhen specified, this option clears all previous `--decorate-refs`\n+\tor `--decorate-refs-exclude` options and relaxes the default\n+\tdecoration filter to include all possible decoration refs.\n+\n --source::\n \tPrint out the ref name given on the command line by which each\n \tcommit was reached.\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 0b5efc9434c..b7fc4946c35 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -101,6 +101,25 @@ static int parse_decoration_style(const char *value)\n \treturn -1;\n }\n \n+static int decorate_all;\n+static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n+static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;\n+static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n+\n+static int decorate_all_callback(const struct option *opt,\n+\t\t\t\t const char *arg, int unset)\n+{\n+\tif (unset) {\n+\t\tdecorate_all = 0;\n+\t\treturn 0;\n+\t}\n+\n+\tstring_list_clear(&decorate_refs_include, 0);\n+\tstring_list_clear(&decorate_refs_exclude, 0);\n+\tdecorate_all = 1;\n+\treturn 0;\n+}\n+\n static int decorate_callback(const struct option *opt, const char *arg, int unset)\n {\n \tif (unset)\n@@ -176,7 +195,8 @@ static void set_default_decoration_filter(struct decoration_filter *decoration_f\n \t\t\t\t\t   item->string);\n \t}\n \n-\tif (decoration_filter->exclude_ref_pattern->nr ||\n+\tif (decorate_all ||\n+\t    decoration_filter->exclude_ref_pattern->nr ||\n \t    decoration_filter->include_ref_pattern->nr ||\n \t    decoration_filter->exclude_ref_config_pattern->nr)\n \t\treturn;\n@@ -199,9 +219,6 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \tstruct userformat_want w;\n \tint quiet = 0, source = 0, mailmap;\n \tstatic struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};\n-\tstatic struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n-\tstatic struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;\n-\tstatic struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n \tstruct decoration_filter decoration_filter = {\n \t\t.exclude_ref_pattern = &decorate_refs_exclude,\n \t\t.include_ref_pattern = &decorate_refs_include,\n@@ -214,6 +231,8 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\tOPT_BOOL(0, \"source\", &source, N_(\"show source\")),\n \t\tOPT_BOOL(0, \"use-mailmap\", &mailmap, N_(\"use mail map file\")),\n \t\tOPT_ALIAS(0, \"mailmap\", \"use-mailmap\"),\n+\t\tOPT_CALLBACK_F(0, \"decorate-all\", NULL, NULL, N_(\"how all ref decorations\"),\n+\t\t\t       PARSE_OPT_NOARG, decorate_all_callback),\n \t\tOPT_STRING_LIST(0, \"decorate-refs\", &decorate_refs_include,\n \t\t\t\tN_(\"pattern\"), N_(\"only decorate refs that match <pattern>\")),\n \t\tOPT_STRING_LIST(0, \"decorate-refs-exclude\", &decorate_refs_exclude,\ndiff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh\nindex 056e922164d..577221c71ed 100755\n--- a/t/t4013-diff-various.sh\n+++ b/t/t4013-diff-various.sh\n@@ -352,6 +352,8 @@ log -GF -p --pickaxe-all master\n log -IA -IB -I1 -I2 -p master\n log --decorate --all\n log --decorate=full --all\n+log --decorate --decorate-all --all\n+log --decorate=full --decorate-all --all\n \n rev-list --parents HEAD\n rev-list --children HEAD\ndiff --git a/t/t4013/diff.log_--decorate=full_--decorate-all_--all b/t/t4013/diff.log_--decorate=full_--decorate-all_--all\nnew file mode 100644\nindex 00000000000..d6e79287846\n--- /dev/null\n+++ b/t/t4013/diff.log_--decorate=full_--decorate-all_--all\n@@ -0,0 +1,61 @@\n+$ git log --decorate=full --decorate-all --all\n+commit b7e0bc69303b488b47deca799a7d723971dfa6cd (refs/heads/mode)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    update mode\n+\n+commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (refs/heads/note)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    update mode (file2)\n+\n+Notes:\n+    note\n+\n+commit cd4e72fd96faed3f0ba949dc42967430374e2290 (refs/heads/rearrange)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    Rearranged lines in dir/sub\n+\n+commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    Notes added by 'git notes add'\n+\n+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master)\n+Merge: 9a6d494 c7a2ab9\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:04:00 2006 +0000\n+\n+    Merge branch 'side'\n+\n+commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:03:00 2006 +0000\n+\n+    Side\n+\n+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:02:00 2006 +0000\n+\n+    Third\n+\n+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:01:00 2006 +0000\n+\n+    Second\n+    \n+    This is the second commit.\n+\n+commit 444ac553ac7612cc88969031b02b3767fb8a353a (refs/heads/initial)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:00:00 2006 +0000\n+\n+    Initial\n+$\ndiff --git a/t/t4013/diff.log_--decorate_--decorate-all_--all b/t/t4013/diff.log_--decorate_--decorate-all_--all\nnew file mode 100644\nindex 00000000000..5d22618bb60\n--- /dev/null\n+++ b/t/t4013/diff.log_--decorate_--decorate-all_--all\n@@ -0,0 +1,61 @@\n+$ git log --decorate --decorate-all --all\n+commit b7e0bc69303b488b47deca799a7d723971dfa6cd (mode)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    update mode\n+\n+commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (note)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    update mode (file2)\n+\n+Notes:\n+    note\n+\n+commit cd4e72fd96faed3f0ba949dc42967430374e2290 (rearrange)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    Rearranged lines in dir/sub\n+\n+commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    Notes added by 'git notes add'\n+\n+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master)\n+Merge: 9a6d494 c7a2ab9\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:04:00 2006 +0000\n+\n+    Merge branch 'side'\n+\n+commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:03:00 2006 +0000\n+\n+    Side\n+\n+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:02:00 2006 +0000\n+\n+    Third\n+\n+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:01:00 2006 +0000\n+\n+    Second\n+    \n+    This is the second commit.\n+\n+commit 444ac553ac7612cc88969031b02b3767fb8a353a (initial)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:00:00 2006 +0000\n+\n+    Initial\n+$\ndiff --git a/t/t4202-log.sh b/t/t4202-log.sh\nindex 9ea9e835d43..e939ed34ff7 100755\n--- a/t/t4202-log.sh\n+++ b/t/t4202-log.sh\n@@ -704,9 +704,12 @@ test_expect_success 'set up more tangled history' '\n \tgit checkout -b tangle HEAD~6 &&\n \ttest_commit tangle-a tangle-a a &&\n \tgit merge main~3 &&\n+\tgit update-ref refs/prefetch/merge HEAD &&\n \tgit merge side~1 &&\n+\tgit update-ref refs/rewritten/merge HEAD &&\n \tgit checkout main &&\n \tgit merge tangle &&\n+\tgit update-ref refs/hidden/tangle HEAD &&\n \tgit checkout -b reach &&\n \ttest_commit reach &&\n \tgit checkout main &&\n@@ -974,9 +977,9 @@ test_expect_success 'decorate-refs-exclude and simplify-by-decoration' '\n \tMerge-tag-reach (HEAD -> main)\n \treach (tag: reach, reach)\n \tseventh (tag: seventh)\n-\tMerge-branch-tangle\n-\tMerge-branch-side-early-part-into-tangle (tangle)\n-\ttangle-a (tag: tangle-a)\n+\tMerge-branch-tangle (refs/hidden/tangle)\n+\tMerge-branch-side-early-part-into-tangle (refs/rewritten/merge, tangle)\n+\tMerge-branch-main-early-part-into-tangle (refs/prefetch/merge)\n \tEOF\n \tgit log -n6 --decorate=short --pretty=\"tformat:%f%d\" \\\n \t\t--decorate-refs-exclude=\"*octopus*\" \\\n@@ -1037,6 +1040,100 @@ test_expect_success 'decorate-refs focus from default' '\n \t! grep HEAD actual\n '\n \n+test_expect_success '--decorate-all overrides defaults' '\n+\tcat >expect.default <<-\\EOF &&\n+\tMerge-tag-reach (HEAD -> refs/heads/main)\n+\tMerge-tags-octopus-a-and-octopus-b\n+\tseventh (tag: refs/tags/seventh)\n+\toctopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)\n+\toctopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)\n+\treach (tag: refs/tags/reach, refs/heads/reach)\n+\tMerge-branch-tangle\n+\tMerge-branch-side-early-part-into-tangle (refs/heads/tangle)\n+\tMerge-branch-main-early-part-into-tangle\n+\ttangle-a (tag: refs/tags/tangle-a)\n+\tMerge-branch-side\n+\tside-2 (tag: refs/tags/side-2, refs/heads/side)\n+\tside-1 (tag: refs/tags/side-1)\n+\tSecond\n+\tsixth\n+\tfifth\n+\tfourth\n+\tthird\n+\tsecond\n+\tinitial\n+\tEOF\n+\tgit log --decorate=full --pretty=\"tformat:%f%d\" >actual &&\n+\ttest_cmp expect.default actual &&\n+\n+\tcat >expect.all <<-\\EOF &&\n+\tMerge-tag-reach (HEAD -> refs/heads/main)\n+\tMerge-tags-octopus-a-and-octopus-b\n+\tseventh (tag: refs/tags/seventh)\n+\toctopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)\n+\toctopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)\n+\treach (tag: refs/tags/reach, refs/heads/reach)\n+\tMerge-branch-tangle (refs/hidden/tangle)\n+\tMerge-branch-side-early-part-into-tangle (refs/rewritten/merge, refs/heads/tangle)\n+\tMerge-branch-main-early-part-into-tangle (refs/prefetch/merge)\n+\ttangle-a (tag: refs/tags/tangle-a)\n+\tMerge-branch-side\n+\tside-2 (tag: refs/tags/side-2, refs/heads/side)\n+\tside-1 (tag: refs/tags/side-1)\n+\tSecond\n+\tsixth\n+\tfifth\n+\tfourth\n+\tthird\n+\tsecond\n+\tinitial\n+\tEOF\n+\tgit log --decorate=full --pretty=\"tformat:%f%d\" \\\n+\t\t--decorate-all >actual &&\n+\ttest_cmp expect.all actual\n+'\n+\n+test_expect_success '--decorate-all clears previous exclusions' '\n+\tcat >expect.all <<-\\EOF &&\n+\tMerge-tag-reach (HEAD -> refs/heads/main)\n+\treach (tag: refs/tags/reach, refs/heads/reach)\n+\tMerge-tags-octopus-a-and-octopus-b\n+\toctopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)\n+\toctopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)\n+\tseventh (tag: refs/tags/seventh)\n+\tMerge-branch-tangle (refs/hidden/tangle)\n+\tMerge-branch-side-early-part-into-tangle (refs/rewritten/merge, refs/heads/tangle)\n+\tMerge-branch-main-early-part-into-tangle (refs/prefetch/merge)\n+\ttangle-a (tag: refs/tags/tangle-a)\n+\tside-2 (tag: refs/tags/side-2, refs/heads/side)\n+\tside-1 (tag: refs/tags/side-1)\n+\tinitial\n+\tEOF\n+\n+\tgit log --decorate=full --pretty=\"tformat:%f%d\" \\\n+\t\t--simplify-by-decoration \\\n+\t\t--decorate-refs-exclude=\"heads/octopus*\" \\\n+\t\t--decorate-refs=\"heads\" \\\n+\t\t--decorate-all >actual &&\n+\ttest_cmp expect.all actual &&\n+\n+\tcat >expect.filtered <<-\\EOF &&\n+\tMerge-tags-octopus-a-and-octopus-b\n+\toctopus-b (refs/heads/octopus-b)\n+\toctopus-a (refs/heads/octopus-a)\n+\tinitial\n+\tEOF\n+\n+\tgit log --decorate=full --pretty=\"tformat:%f%d\" \\\n+\t\t--simplify-by-decoration \\\n+\t\t--decorate-refs-exclude=\"heads/octopus\" \\\n+\t\t--decorate-refs=\"heads\" \\\n+\t\t--decorate-all \\\n+\t\t--decorate-refs-exclude=\"tags/\" \\\n+\t\t--decorate-refs=\"heads/octopus*\" >actual &&\n+\ttest_cmp expect.filtered actual\n+'\n+\n test_expect_success 'log.decorate config parsing' '\n \tgit log --oneline --decorate=full >expect.full &&\n \tgit log --oneline --decorate=short >expect.short &&\n-- \ngitgitgadget\n\n"},{"id":"460264","messageId":"318269dfe27a56d4c85b8723fbd9853159e9d096.1659122979.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v2.git.1659122979.gitgitgadget@gmail.com","subject":"[PATCH v2 09/10] maintenance: stop writing log.excludeDecoration","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-07-29T19:29:38Z","receivedAt":"2022-07-29T19:30:24Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThis reverts commit 96eaffebbf3d0 (maintenance: set\nlog.excludeDecoration durin prefetch, 2021-01-19).\n\nThe previous change created a default decoration filter that does not\ninclude refs/prefetch/, so this modification of the config is no longer\nneeded.\n\nOne issue that can happen from this point on is that users who ran the\nprefetch task on previous versions of Git will still have a\nlog.excludeDecoration value and that will prevent the new default\ndecoration filter from being active. Thus, when we add the refs/bundle/\nnamespace as part of the bundle URI feature, those users will see\nrefs/bundle/ decorations.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n builtin/gc.c           |  6 ------\n t/t7900-maintenance.sh | 21 ---------------------\n 2 files changed, 27 deletions(-)\n\ndiff --git a/builtin/gc.c b/builtin/gc.c\nindex eeff2b760e0..6c222052177 100644\n--- a/builtin/gc.c\n+++ b/builtin/gc.c\n@@ -910,12 +910,6 @@ static int fetch_remote(struct remote *remote, void *cbdata)\n \n static int maintenance_task_prefetch(struct maintenance_run_opts *opts)\n {\n-\tgit_config_set_multivar_gently(\"log.excludedecoration\",\n-\t\t\t\t\t\"refs/prefetch/\",\n-\t\t\t\t\t\"refs/prefetch/\",\n-\t\t\t\t\tCONFIG_FLAGS_FIXED_VALUE |\n-\t\t\t\t\tCONFIG_FLAGS_MULTI_REPLACE);\n-\n \tif (for_each_remote(fetch_remote, opts)) {\n \t\terror(_(\"failed to prefetch remotes\"));\n \t\treturn 1;\ndiff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh\nindex 74aa6384755..62ed694a404 100755\n--- a/t/t7900-maintenance.sh\n+++ b/t/t7900-maintenance.sh\n@@ -162,7 +162,6 @@ test_expect_success 'prefetch multiple remotes' '\n \ttest_cmp_rev refs/remotes/remote1/one refs/prefetch/remotes/remote1/one &&\n \ttest_cmp_rev refs/remotes/remote2/two refs/prefetch/remotes/remote2/two &&\n \n-\ttest_cmp_config refs/prefetch/ log.excludedecoration &&\n \tgit log --oneline --decorate --all >log &&\n \t! grep \"prefetch\" log &&\n \n@@ -173,26 +172,6 @@ test_expect_success 'prefetch multiple remotes' '\n \ttest_subcommand git fetch remote2 $fetchargs <skip-remote1.txt\n '\n \n-test_expect_success 'prefetch and existing log.excludeDecoration values' '\n-\tgit config --unset-all log.excludeDecoration &&\n-\tgit config log.excludeDecoration refs/remotes/remote1/ &&\n-\tgit maintenance run --task=prefetch &&\n-\n-\tgit config --get-all log.excludeDecoration >out &&\n-\tgrep refs/remotes/remote1/ out &&\n-\tgrep refs/prefetch/ out &&\n-\n-\tgit log --oneline --decorate --all >log &&\n-\t! grep \"prefetch\" log &&\n-\t! grep \"remote1\" log &&\n-\tgrep \"remote2\" log &&\n-\n-\t# a second run does not change the config\n-\tgit maintenance run --task=prefetch &&\n-\tgit log --oneline --decorate --all >log2 &&\n-\ttest_cmp log log2\n-'\n-\n test_expect_success 'loose-objects task' '\n \t# Repack everything so we know the state of the object dir\n \tgit repack -adk &&\n-- \ngitgitgadget\n\n"},{"id":"460269","messageId":"YuRD9Uu/yAGg6roj@coredump.intra.peff.net","threadId":"58226","inReplyTo":"xmqqczdqtxro.fsf@gitster.g","subject":"Re: [PATCH 2/3] log: add default decoration filter","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2022-07-29T20:32:53Z","receivedAt":"2022-07-29T20:33:01Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jul 27, 2022 at 07:50:51AM -0700, Junio C Hamano wrote:\n\n> > * Notes (refs/notes/)\n> \n> Questionable.  None of the notes commits are on the primary history,\n> so it is unlikely to be even used for decoration, so it would not\n> hurt to have them as part of possible decoration sources, but on the\n> other hand, the value of using them is dubious.\n> \n> > * Stashes (refs/stash/)\n> \n> Questionable, for the same reason as 'notes'.\n\nEven more so, IMHO, because we are not even decorating all of the\nstashes. Because the stash is kept in a reflog, it is really just\ndecorating stash@{0}.\n\nAs you said elsewhere, I'm OK with keeping it in the name of \"it's\nprobably not hurting\", but I'd be really surprised if it has ever helped\nanyone.\n\n-Peff\n"},{"id":"460533","messageId":"xmqqedxxeued.fsf@gitster.g","threadId":"58226","inReplyTo":"c2e5a0b3a50237f3b7f5ceb5d05faa83fd41de68.1659122979.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 01/10] refs: allow \"HEAD\" as decoration filter","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-08-03T06:03:06Z","receivedAt":"2022-08-03T06:03:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n>  \tif (prefix) {\n>  \t\tstrbuf_addstr(&normalized_pattern, prefix);\n> -\t}\n> -\telse if (!starts_with(pattern, \"refs/\"))\n> +\t} else if (!starts_with(pattern, \"refs/\") &&\n> +\t\t   strcmp(pattern, \"HEAD\"))\n\nPerhaps leave a needswork comment to remind us to later consider\ncovering all the pseudorefs like MERGE_HEAD, CHERRY_PICK_HEAD etc.?\n\n>  \t\tstrbuf_addstr(&normalized_pattern, \"refs/\");\n\nStyle:\n\nIf you plan to add more code to the bodies of this if/elseif, then\nhave {} around all arms.  Otherwise, let's lose the {} around the\nbody of \"if (prefix)\".\n\n\n"},{"id":"460534","messageId":"xmqqzggldf7y.fsf@gitster.g","threadId":"58226","inReplyTo":"d7486390d57849971ee6a4ac27a0a784c41623ee.1659122979.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 03/10] refs: add array of ref namespaces","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-08-03T06:16:17Z","receivedAt":"2022-08-03T06:16:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> +\t[NAMESPACE_REPLACE] = {\n> +\t\t/*\n> +\t\t * This namespace allows Git to act as if one object ID\n> +\t\t * points to the content of another. Unlike the other\n> +\t\t * ref namespaces, this one can be changed by the\n> +\t\t * GIT_REPLACE_REF_BASE environment variable. This\n> +\t\t * .namespace value will be overwritten in setup_git_env().\n> +\t\t */\n\nThanks---it is a shame that we have unnecessary flexibility that\nrequires us to have this code.\n\n> +\t\t.ref = \"refs/replace/\",\n> +\t\t.decoration = DECORATION_GRAFTED,\n> +\t},\n> +\t[NAMESPACE_NOTES] = {\n> +\t\t/*\n> +\t\t * The refs/notes/commit ref points to the tip of a\n> +\t\t * parallel commit history that adds metadata to commits\n> +\t\t * in the normal history. This branch can be overwritten\n\nThis is not \"branch\" but is a ref.\n\n\n> +\t\t * by the core.notesRef config variable or the\n> +\t\t * GIT_NOTES_REFS environment variable.\n> +\t\t */\n> +\t\t.ref = \"refs/notes/commit\",\n> +\t\t.exact = 1,\n\nAllowing just \"the default\" to be replaced by another \"custom\ndefault\" is a good start, but we probably want to support more than\none notes refs, to parallel how \"struct display_notes_opt\" has\nextra_notes_refs to allow multiple notes refs to decorate objects.\n\n"},{"id":"460535","messageId":"220803.86y1w5g7r0.gmgdl@evledraar.gmail.com","threadId":"58226","inReplyTo":"b5eb110958baa80b72a345b3c850f1dfceabf076.1659122979.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 02/10] t4207: test coloring of grafted decorations","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-08-03T06:25:30Z","receivedAt":"2022-08-03T06:29:35Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Jul 29 2022, Derrick Stolee via GitGitGadget wrote:\n\n> From: Derrick Stolee <derrickstolee@github.com>\n>\n> The color.decorate.<slot> config option added the 'grafted' slot in\n> 09c4ba410b0f (log-tree: allow to customize 'grafted' color, 2018-05-26)\n> but included no tests for this behavior. When modifying some logic\n> around decorations, this ref namespace was ignored and could have been\n> lost as a default namespace for 'git log' decorations by default.\n>\n> Add two tests to t4207 that check that the replaced objects are\n> correctly decorated. Use \"black\" as the color since it is distinct from\n> the other colors already in the test. The first test uses regular\n> replace-objects while the second creates a commit graft.\n>\n> Be sure to test both modes with GIT_REPLACE_REF_BASE unset and set to an\n> alternative base.\n>\n> Signed-off-by: Derrick Stolee <derrickstolee@github.com>\n> ---\n>  t/t4207-log-decoration-colors.sh | 59 ++++++++++++++++++++++++++++++++\n>  1 file changed, 59 insertions(+)\n>\n> diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh\n> index 36ac6aff1e4..69f8ac602d6 100755\n> --- a/t/t4207-log-decoration-colors.sh\n> +++ b/t/t4207-log-decoration-colors.sh\n> @@ -18,6 +18,7 @@ test_expect_success setup '\n>  \tgit config color.decorate.tag \"reverse bold yellow\" &&\n>  \tgit config color.decorate.stash magenta &&\n>  \tgit config color.decorate.HEAD cyan &&\n> +\tgit config color.decorate.grafted black &&\n>  \n>  \tc_reset=\"<RESET>\" &&\n>  \n> @@ -27,6 +28,7 @@ test_expect_success setup '\n>  \tc_tag=\"<BOLD;REVERSE;YELLOW>\" &&\n>  \tc_stash=\"<MAGENTA>\" &&\n>  \tc_HEAD=\"<CYAN>\" &&\n> +\tc_grafted=\"<BLACK>\" &&\n>  \n>  \ttest_commit A &&\n>  \tgit clone . other &&\n> @@ -63,4 +65,61 @@ test_expect_success 'Commit Decorations Colored Correctly' '\n>  \ttest_cmp expected out\n>  '\n>  \n> +cat >expected <<EOF\n> +${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD ->\\\n> + ${c_reset}${c_branch}main${c_reset}${c_commit},\\\n> + ${c_reset}${c_tag}tag: D${c_reset}${c_commit})${c_reset} D\n> +${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: C${c_reset}${c_commit},\\\n> + ${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} B\n> +${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A\n> +EOF\n\nI see this is used by (one) existing test, but for new test code let's\nadd such setup in the test_expect_success block.\n\nA small issue, but e.g. if the partition our trash directories is on\nfills up this sort of thing outside of test_expect_success hides the\nsource of the \"first\" error.\n\nMore generally (just eyeballing this v.s. the existing one) maybe we can\ncombine them a bit & share some of these lines?\n\n> +test_expect_success 'test coloring with replace-objects' '\n> +\ttest_when_finished rm -rf .git/refs/replace* &&\n> +\ttest_commit C &&\n> +\ttest_commit D &&\n> +\n> +\tgit replace HEAD~1 HEAD~2 &&\n> +\tgit log --first-parent --abbrev=10 --decorate --oneline --color=always HEAD |\n\nThis hides segfaults, abort() etc. in git log, let's use an intermediate\nfile rather than git on the LHS of a pipe.\n\n> +\tsed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n\n{10,10} in a regex is just {10}, no?\n\n> +\ttest_decode_color >out &&\n> +\ttest_cmp expected out &&\n> +\tgit replace -d HEAD~1 &&\n> +\n> +\tGIT_REPLACE_REF_BASE=refs/replace2/ git replace HEAD~1 HEAD~2 &&\n> +\tGIT_REPLACE_REF_BASE=refs/replace2/ git log --first-parent --abbrev=10 \\\n> +\t\t--decorate --oneline --color=always HEAD |\n\nDitto LHS.\n\n> +\tsed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n\nDitto RX, but at this point I see it's copy/pasted from the existing\ntest in the file, might be worth starting by factoring the duplicate\nbits out into a function...\n\n> +\ttest_decode_color >out &&\n> +\ttest_cmp expected out\n> +'\n> +\n> +cat >expected <<EOF\n> +${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD ->\\\n> + ${c_reset}${c_branch}main${c_reset}${c_commit},\\\n> + ${c_reset}${c_tag}tag: D${c_reset}${c_commit},\\\n> + ${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} D\n> +${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit},\\\n> + ${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B\n> +${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A\n> +EOF\n> +\n> +test_expect_success 'test coloring with grafted commit' '\n> +\ttest_when_finished rm -rf .git/refs/replace* &&\n> +\n> +\tgit replace --graft HEAD HEAD~2 &&\n> +\tgit log --first-parent --abbrev=10 --decorate --oneline --color=always HEAD |\n> +\tsed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n> +\ttest_decode_color >out &&\n> +\ttest_cmp expected out &&\n> +\tgit replace -d HEAD &&\n> +\n> +\tGIT_REPLACE_REF_BASE=refs/replace2/ git replace --graft HEAD HEAD~2 &&\n> +\tGIT_REPLACE_REF_BASE=refs/replace2/ git log --first-parent --abbrev=10 \\\n> +\t\t--decorate --oneline --color=always HEAD |\n> +\tsed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n> +\ttest_decode_color >out &&\n> +\ttest_cmp expected out\n> +'\n> +\n>  test_done\n\n...as we had one of these, and now have 3x...\n"},{"id":"460536","messageId":"xmqqv8r9dei7.fsf@gitster.g","threadId":"58226","inReplyTo":"53b15a0b7932f892505d07a509909b62c473037e.1659122979.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 05/10] log-tree: use ref_namespaces instead of if/else-if","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-08-03T06:31:44Z","receivedAt":"2022-08-03T06:31:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Derrick Stolee <derrickstolee@github.com>\n>\n> The add_ref_decoration() method uses an if/else-if chain to determine if\n> a ref matches a known ref namespace that has a special decoration\n> category. That decoration type is later used to assign a color when\n> writing to stdout.\n>\n> The newly-added ref_namespaces array contains all namespaces, along\n> with information about their decoration type. Check this array instead\n> of this if/else-if chain. This reduces our dependency on string literals\n> being embedded in the decoration logic.\n>\n> Signed-off-by: Derrick Stolee <derrickstolee@github.com>\n> ---\n>  log-tree.c | 26 ++++++++++++++++----------\n>  1 file changed, 16 insertions(+), 10 deletions(-)\n>\n> diff --git a/log-tree.c b/log-tree.c\n> index bb80f1a94d2..6075bdd334e 100644\n> --- a/log-tree.c\n> +++ b/log-tree.c\n> @@ -137,6 +137,7 @@ static int ref_filter_match(const char *refname,\n>  static int add_ref_decoration(const char *refname, const struct object_id *oid,\n>  \t\t\t      int flags, void *cb_data)\n>  {\n> +\tint i;\n>  \tstruct object *obj;\n>  \tenum object_type objtype;\n>  \tenum decoration_type deco_type = DECORATION_NONE;\n> @@ -167,16 +168,21 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,\n>  \t\treturn 0;\n>  \tobj = lookup_object_by_type(the_repository, oid, objtype);\n>  \n> -\tif (starts_with(refname, \"refs/heads/\"))\n> -\t\tdeco_type = DECORATION_REF_LOCAL;\n> -\telse if (starts_with(refname, \"refs/remotes/\"))\n> -\t\tdeco_type = DECORATION_REF_REMOTE;\n> -\telse if (starts_with(refname, \"refs/tags/\"))\n> -\t\tdeco_type = DECORATION_REF_TAG;\n> -\telse if (!strcmp(refname, \"refs/stash\"))\n> -\t\tdeco_type = DECORATION_REF_STASH;\n> -\telse if (!strcmp(refname, \"HEAD\"))\n> -\t\tdeco_type = DECORATION_REF_HEAD;\n> +\tfor (i = 0; i < NAMESPACE__COUNT; i++) {\n> +\t\tstruct ref_namespace_info *info = &ref_namespaces[i];\n> +\n> +\t\tif (!info->decoration)\n> +\t\t\tcontinue;\n> +\t\tif (info->exact) {\n> +\t\t\tif (!strcmp(refname, info->ref)) {\n> +\t\t\t\tdeco_type = info->decoration;\n> +\t\t\t\tbreak;\n> +\t\t\t}\n> +\t\t} else if (starts_with(refname, info->ref)) {\n> +\t\t\tdeco_type = info->decoration;\n> +\t\t\tbreak;\n> +\t\t}\n> +\t}\n\nVery nice.  The double-dash in the NAMESPACE__COUNT constant somehow\nlooks strange.  As we scan through ref_namespace[] array densely,\n\n\tfor (i = 0; i < ARRAY_SIZE(ref_namespace); i++)\n\t\t...\n\nwithout having to use the constant would probably be more in line\nwith the way how the rest of the codebase works.\n"},{"id":"460537","messageId":"xmqqr11xdeb0.fsf@gitster.g","threadId":"58226","inReplyTo":"318269dfe27a56d4c85b8723fbd9853159e9d096.1659122979.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 09/10] maintenance: stop writing log.excludeDecoration","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-08-03T06:36:03Z","receivedAt":"2022-08-03T06:36:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Derrick Stolee <derrickstolee@github.com>\n>\n> This reverts commit 96eaffebbf3d0 (maintenance: set\n> log.excludeDecoration durin prefetch, 2021-01-19).\n>\n> The previous change created a default decoration filter that does not\n> include refs/prefetch/, so this modification of the config is no longer\n> needed.\n>\n> One issue that can happen from this point on is that users who ran the\n> prefetch task on previous versions of Git will still have a\n> log.excludeDecoration value and that will prevent the new default\n> decoration filter from being active. Thus, when we add the refs/bundle/\n> namespace as part of the bundle URI feature, those users will see\n> refs/bundle/ decorations.\n\nYup, and if they find it disturbing, they can fix it, but it is\nunlikely to be a problem, I would think, since decoration works only\nfor exact point in history.  If this topic were to choose what refs\nthe \"describe\" abbreviation uses, it would have been much more\nannoying to see some unwanted refs used.\n"},{"id":"460538","messageId":"CAPig+cTUTXuBov4m0xvxehVFbbPjVPrAHAFfPWO5Yv4C9imyaQ@mail.gmail.com","threadId":"58226","inReplyTo":"220803.86y1w5g7r0.gmgdl@evledraar.gmail.com","subject":"Re: [PATCH v2 02/10] t4207: test coloring of grafted decorations","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2022-08-03T06:44:16Z","receivedAt":"2022-08-03T06:44:34Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Aug 3, 2022 at 2:32 AM Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:\n> On Fri, Jul 29 2022, Derrick Stolee via GitGitGadget wrote:\n> > +     sed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n>\n> {10,10} in a regex is just {10}, no?\n\nI'm more than a little surprised that this regex repeat-count notation\nworks on macOS `sed` which, in the BSD tradition, is rather feature\npoor. Testing it, though, I find that it does work, even on my\nrelatively old version of macOS. However, I'd still worry about other\nBSD `sed`s in the wild.\n\nInstead of using the repeat-count notation, we could model this after\nthe way `OID_REGEX` is defined in t/test-lib.sh which, through\nautomation, defines a highly portable regex. Alternatively, just use\n\"$_x05$_x05\", also from test-lib.sh, to define a regex matcher for ten\nhex digits.\n"},{"id":"460543","messageId":"220803.86les5fpfg.gmgdl@evledraar.gmail.com","threadId":"58226","inReplyTo":"CAPig+cTUTXuBov4m0xvxehVFbbPjVPrAHAFfPWO5Yv4C9imyaQ@mail.gmail.com","subject":"Re: [PATCH v2 02/10] t4207: test coloring of grafted decorations","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-08-03T13:03:30Z","receivedAt":"2022-08-03T13:05:24Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Wed, Aug 03 2022, Eric Sunshine wrote:\n\n> On Wed, Aug 3, 2022 at 2:32 AM Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:\n>> On Fri, Jul 29 2022, Derrick Stolee via GitGitGadget wrote:\n>> > +     sed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n>>\n>> {10,10} in a regex is just {10}, no?\n>\n> I'm more than a little surprised that this regex repeat-count notation\n> works on macOS `sed` which, in the BSD tradition, is rather feature\n> poor. Testing it, though, I find that it does work, even on my\n> relatively old version of macOS. However, I'd still worry about other\n> BSD `sed`s in the wild.\n\nIt seems you missed it but we already have this code tested \"in the\nwild\", i.e. the \"new\" code here is really just copy/pasting test setup\nfrom above.\n\nSo maybe we want to change (and you have some good suggestions here),\nbut it's already shown itself to be portable enough. We've had this\n\"sed\" command since v1.7.2, or 567102819ac (Add test for correct\ncoloring of git log --decoration, 2010-06-29).\n"},{"id":"460580","messageId":"Yur49obfOHwu2B5t@google.com","threadId":"58226","inReplyTo":"8da0b0a31810c8221ad3ab13b8c41cf1a266c2c0.1659122979.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 04/10] refs: use ref_namespaces for replace refs base","fromName":"Josh Steadmon","fromEmail":"steadmon@google.com","sentAt":"2022-08-03T22:38:46Z","receivedAt":"2022-08-03T22:38:57Z","isPatch":true,"sender":{"key":"steadmon@google.com","avatar":"https://avatars.githubusercontent.com/u/2654920?v=4"},"body":"On 2022.07.29 19:29, Derrick Stolee via GitGitGadget wrote:\n> diff --git a/log-tree.c b/log-tree.c\n> index d0ac0a6327a..bb80f1a94d2 100644\n> --- a/log-tree.c\n> +++ b/log-tree.c\n> @@ -141,10 +141,12 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,\n>  \tenum object_type objtype;\n>  \tenum decoration_type deco_type = DECORATION_NONE;\n>  \tstruct decoration_filter *filter = (struct decoration_filter *)cb_data;\n> +\tconst char *git_replace_ref_base;\n>  \n>  \tif (filter && !ref_filter_match(refname, filter))\n>  \t\treturn 0;\n>  \n> +\tgit_replace_ref_base = ref_namespaces[NAMESPACE_REPLACE].ref;\n\nIs there a reason not to initialize this as soon as we declare it?\n\n\n>  \tif (starts_with(refname, git_replace_ref_base)) {\n>  \t\tstruct object_id original_oid;\n>  \t\tif (!read_replace_refs)\n"},{"id":"460581","messageId":"Yur5OmTAYDx0ifsp@google.com","threadId":"58226","inReplyTo":"d7486390d57849971ee6a4ac27a0a784c41623ee.1659122979.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 03/10] refs: add array of ref namespaces","fromName":"Josh Steadmon","fromEmail":"steadmon@google.com","sentAt":"2022-08-03T22:39:54Z","receivedAt":"2022-08-03T22:40:05Z","isPatch":true,"sender":{"key":"steadmon@google.com","avatar":"https://avatars.githubusercontent.com/u/2654920?v=4"},"body":"On 2022.07.29 19:29, Derrick Stolee via GitGitGadget wrote:\n> diff --git a/refs.h b/refs.h\n> index 47cb9edbaa8..94e8dedf939 100644\n> --- a/refs.h\n> +++ b/refs.h\n> @@ -2,6 +2,7 @@\n>  #define REFS_H\n>  \n>  #include \"cache.h\"\n> +#include \"commit.h\"\n>  \n>  struct object_id;\n>  struct ref_store;\n> @@ -930,4 +931,49 @@ struct ref_store *get_main_ref_store(struct repository *r);\n>  struct ref_store *get_submodule_ref_store(const char *submodule);\n>  struct ref_store *get_worktree_ref_store(const struct worktree *wt);\n>  \n> +/*\n> + * Some of the names specified by refs have special meaning to Git.\n> + * Organize these namespaces in a comon 'ref_namespaces' array for\n> + * reference from multiple places in the codebase.\n> + */\n> +\n> +struct ref_namespace_info {\n> +\tchar *ref;\n> +\tenum decoration_type decoration;\n> +\n> +\t/*\n> +\t * If 'exact' is true, then we must match the 'ref' exactly.\n> +\t * Otherwise, use a prefix match.\n> +\t *\n> +\t * 'orig_ref' is for internal use. It represents whether the\n\ns/orig_ref/ref_updated/ here I think.\n\n\n> +\t * 'ref' value was replaced from its original literal version.\n> +\t */\n> +\tunsigned exact:1,\n> +\t\t ref_updated:1;\n> +};\n> +\n> +enum ref_namespace {\n> +\tNAMESPACE_HEAD,\n> +\tNAMESPACE_BRANCHES,\n> +\tNAMESPACE_TAGS,\n> +\tNAMESPACE_REMOTE_REFS,\n> +\tNAMESPACE_STASH,\n> +\tNAMESPACE_REPLACE,\n> +\tNAMESPACE_NOTES,\n> +\tNAMESPACE_PREFETCH,\n> +\tNAMESPACE_REWRITTEN,\n> +\n> +\t/* Must be last */\n> +\tNAMESPACE__COUNT\n> +};\n> +\n> +/* See refs.c for the contents of this array. */\n> +extern struct ref_namespace_info ref_namespaces[];\n> +\n> +/*\n> + * Some ref namespaces can be modified by config values or environment\n> + * variables. Modify a namespace as specified by its ref_namespace key.\n> + */\n> +void update_ref_namespace(enum ref_namespace namespace, char *ref);\n> +\n>  #endif /* REFS_H */\n> -- \n> gitgitgadget\n> \n"},{"id":"460582","messageId":"Yur5wXXiBtKRO/Y5@google.com","threadId":"58226","inReplyTo":"8142b32f023685c78936a618d7b93aaf86ba77fb.1659122979.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 08/10] log: create log.decorateFilter=all","fromName":"Josh Steadmon","fromEmail":"steadmon@google.com","sentAt":"2022-08-03T22:42:09Z","receivedAt":"2022-08-03T22:42:21Z","isPatch":true,"sender":{"key":"steadmon@google.com","avatar":"https://avatars.githubusercontent.com/u/2654920?v=4"},"body":"On 2022.07.29 19:29, Derrick Stolee via GitGitGadget wrote:\n> From: Derrick Stolee <derrickstolee@github.com>\n> \n> The previous change introduced the --decorate-all option for users who\n> do not want their decorations limited to a narrow set of ref namespaces.\n> \n> Add a config option that is equivalent to specifying --decorate-all by\n> default.\n> \n> Signed-off-by: Derrick Stolee <derrickstolee@github.com>\n> ---\n>  Documentation/config/log.txt |  5 +++++\n>  Documentation/git-log.txt    |  4 +++-\n>  builtin/log.c                | 12 ++++++++++++\n>  t/t4202-log.sh               |  3 +++\n>  t/t9902-completion.sh        |  3 +++\n>  5 files changed, 26 insertions(+), 1 deletion(-)\n> \n> diff --git a/Documentation/config/log.txt b/Documentation/config/log.txt\n> index 456eb07800c..615cb26e5c9 100644\n> --- a/Documentation/config/log.txt\n> +++ b/Documentation/config/log.txt\n> @@ -18,6 +18,11 @@ log.decorate::\n>  \tnames are shown. This is the same as the `--decorate` option\n>  \tof the `git log`.\n>  \n> +log.decorateFilter::\n> +\tBy default, `git log` only shows decorations for certain known ref\n> +\tnamespaces. If 'all' is specified, then show all possible ref\n> +\tdecorations. Default value is 'default'.\n> +\n\nCould we make it more clear here that \"all\" is the only supported value?\nIIUC any other value will just get the default behavior. Just reading\nthe doc as-is, I worry that users might expect that they can add\nspecific refs / ref-patterns that would be added to the filter.\n"},{"id":"460597","messageId":"CAPig+cSjHf3d6xKT71biR8Cd0iKHqBpQ6Q9_bd_w9Hgg_uE=0g@mail.gmail.com","threadId":"58226","inReplyTo":"220803.86les5fpfg.gmgdl@evledraar.gmail.com","subject":"Re: [PATCH v2 02/10] t4207: test coloring of grafted decorations","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2022-08-04T04:05:22Z","receivedAt":"2022-08-04T04:05:38Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Aug 3, 2022 at 9:05 AM Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:\n> On Wed, Aug 03 2022, Eric Sunshine wrote:\n> > On Wed, Aug 3, 2022 at 2:32 AM Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:\n> >> On Fri, Jul 29 2022, Derrick Stolee via GitGitGadget wrote:\n> >> > +     sed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n> >>\n> >> {10,10} in a regex is just {10}, no?\n> >\n> > I'm more than a little surprised that this regex repeat-count notation\n> > works on macOS `sed` which, in the BSD tradition, is rather feature\n> > poor. Testing it, though, I find that it does work, even on my\n> > relatively old version of macOS. However, I'd still worry about other\n> > BSD `sed`s in the wild.\n>\n> It seems you missed it but we already have this code tested \"in the\n> wild\", i.e. the \"new\" code here is really just copy/pasting test setup\n> from above.\n>\n> So maybe we want to change (and you have some good suggestions here),\n> but it's already shown itself to be portable enough. We've had this\n> \"sed\" command since v1.7.2, or 567102819ac (Add test for correct\n> coloring of git log --decoration, 2010-06-29).\n\nNo, I didn't miss it; I saw your mention that it was copied from\nexisting code in the script, but I assumed the existing code was\nrecent -- hence my surprise. Since it's been around so long, I agree,\nit's hardly a cause for concern at this point (though, I still\nreflexively write the more portable notation as used by `OID_REGEX`\nand `_x05`, etc.).\n"},{"id":"460604","messageId":"220804.86iln8e9hl.gmgdl@evledraar.gmail.com","threadId":"58226","inReplyTo":"bec532fb8c63b3ae784d442f438687a4f0bbad37.1659122979.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 06/10] log: add default decoration filter","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-08-04T07:08:04Z","receivedAt":"2022-08-04T07:47:09Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Jul 29 2022, Derrick Stolee via GitGitGadget wrote:\n\n> From: Derrick Stolee <derrickstolee@github.com>\n\nThanks for the re-roll in general, there's a lot of good stuff here & I\nhope I find more time to comment on it in more detail, but just focusing\non things that would be hard to back out of once changed:\n\n> [...]\n> Another alternative would be to exclude the known namespaces that are\n> not intended to be shown. This would reduce the visible effect of the\n> change for expert users who use their own custom ref namespaces. The\n> implementation change would be very simple to swap due to our use of\n> ref_namespaces:\n>\n> \tint i;\n> \tstruct string_list *exclude = decoration_filter->exclude_ref_pattern;\n>\n> \t/*\n> \t * No command-line or config options were given, so\n> \t * populate with sensible defaults.\n> \t */\n> \tfor (i = 0; i < NAMESPACE__COUNT; i++) {\n> \t\tif (ref_namespaces[i].decoration)\n> \t\t\tcontinue;\n>\n> \t\tstring_list_append(exclude, ref_namespaces[i].ref);\n> \t}\n>\n> The main downside of this approach is that we expect to add new hidden\n> namespaces in the future, and that means that Git versions will be less\n> stable in how they behave as those namespaces are added.\n\nI see that as a feature, and not a downside. If we simply explain this\nin the documentation as e.g.:\n\n\tWhen adding decorations git will by default exclude certain\n\t\"internal\" ref namespaces that it treats specially, such as\n\trefs/magical-1/*, refs/magical-2/* (or whatever). Other such\n\tspecial namespaces may be reserved in the future.\n\nThere's no lack of \"stability\", because the ref hiding only act on\nwhat's known to be something we can ignore, because our git version\nknows about it.\n\nIf git v2.40 knows about refs/magical-1/* but not refs/magical-2/*, but\ngit v2.50 knows about both it's not a lack of stability that v2.40 shows\none decorated by default, but v2.50 shows neither.\n\nTo v2.40 one of them isn't a magical \"I know what this is, it's internal\n& I can hide it\" ref.\n\nI'm aware that we disagree, and some of this was discussed in v1. I'm\nnot intending to just repeat what I said before.\n\nBut it's not just that I disagree, I genuinely don't get your POV\nhere. We:\n\n * Know that we have (admittedly probably rare) in-the-wild use of\n   non-standard and custom namespaces, and that this series would change\n   long-standing log output.\n\n   If I could see a good reason to change the existing \"log\" behavior\n   here I'd probably be sold on it. We try not to change existing output\n   in general, but this part isn't \"plumbing\", and arguably not a very\n   \"stable\" part of the log output either (decorations being optional\n   etc).\n\n   But it does rub me the wrong way to sell a change in the name of\n   \"stability\" when it's from the outset doing the exact opposite,\n   to....\n\n * ... are willing to make that one-time change so that we can have\n   stability for users that are relying on \"decorate\" working\n   consistently across versions once we're in the new world order,\n   because we *might* add new magical refs.\n\nSince the latter group of users don't exist today by definition (this\nhaving not been integrated) why isn't it a better win-win solution to\ngive those users some --decorate-only-known-refs option/config?\n\nThey'd get their \"stability\" going forward, and without the needless\nbreaking of existing behavior, no?\n\n> +test_expect_success 'log --decorate does not include things outside filter' '\n> +\treflist=\"refs/prefetch refs/rebase-merge refs/bundle\" &&\n> +\n> +\tfor ref in $reflist\n> +\tdo\n> +\t\tgit update-ref $ref/fake HEAD || return 1\n> +\tdone &&\n> +\n> +\tgit log --decorate=full --oneline >actual &&\n> +\n> +\tfor ref in $reflist\n> +\tdo\n> +\t\t! grep $ref/fake actual || return 1\n> +\tdone\n\nI haven't tested, but isn't that last for-loop replacable with:\n\n\t! grep /fake actual\n\n?\n\nOr do we have other \"/fake\" refs we want to include?\n"},{"id":"460612","messageId":"d5cc4280-3f17-ceec-ac96-97e896898a91@github.com","threadId":"58226","inReplyTo":"xmqqedxxeued.fsf@gitster.g","subject":"Re: [PATCH v2 01/10] refs: allow \"HEAD\" as decoration filter","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-08-04T13:22:50Z","receivedAt":"2022-08-04T13:22:57Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/3/2022 2:03 AM, Junio C Hamano wrote:\n> \"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n> \n>>  \tif (prefix) {\n>>  \t\tstrbuf_addstr(&normalized_pattern, prefix);\n>> -\t}\n>> -\telse if (!starts_with(pattern, \"refs/\"))\n>> +\t} else if (!starts_with(pattern, \"refs/\") &&\n>> +\t\t   strcmp(pattern, \"HEAD\"))\n> \n> Perhaps leave a needswork comment to remind us to later consider\n> covering all the pseudorefs like MERGE_HEAD, CHERRY_PICK_HEAD etc.?\n\nA comment is a good idea. We should leave it for later because it\nwould make a visible change from the user's perspective.\n\n>>  \t\tstrbuf_addstr(&normalized_pattern, \"refs/\");\n> \n> Style:\n> \n> If you plan to add more code to the bodies of this if/elseif, then\n> have {} around all arms.  Otherwise, let's lose the {} around the\n> body of \"if (prefix)\".\n\nYes, thanks for the close eyes.\n\nThanks,\n-Stolee\n"},{"id":"460613","messageId":"9d60ae93-5acf-cf26-f0ab-cc2aa0808f7e@github.com","threadId":"58226","inReplyTo":"xmqqzggldf7y.fsf@gitster.g","subject":"Re: [PATCH v2 03/10] refs: add array of ref namespaces","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-08-04T13:29:06Z","receivedAt":"2022-08-04T13:29:13Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/3/2022 2:16 AM, Junio C Hamano wrote:\n> \"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n> \n>> +\t[NAMESPACE_REPLACE] = {\n>> +\t\t/*\n>> +\t\t * This namespace allows Git to act as if one object ID\n>> +\t\t * points to the content of another. Unlike the other\n>> +\t\t * ref namespaces, this one can be changed by the\n>> +\t\t * GIT_REPLACE_REF_BASE environment variable. This\n>> +\t\t * .namespace value will be overwritten in setup_git_env().\n>> +\t\t */\n> \n> Thanks---it is a shame that we have unnecessary flexibility that\n> requires us to have this code.\n> \n>> +\t\t.ref = \"refs/replace/\",\n>> +\t\t.decoration = DECORATION_GRAFTED,\n>> +\t},\n>> +\t[NAMESPACE_NOTES] = {\n>> +\t\t/*\n>> +\t\t * The refs/notes/commit ref points to the tip of a\n>> +\t\t * parallel commit history that adds metadata to commits\n>> +\t\t * in the normal history. This branch can be overwritten\n> \n> This is not \"branch\" but is a ref.\n\nThanks!\n\n>> +\t\t * by the core.notesRef config variable or the\n>> +\t\t * GIT_NOTES_REFS environment variable.\n>> +\t\t */\n>> +\t\t.ref = \"refs/notes/commit\",\n>> +\t\t.exact = 1,\n> \n> Allowing just \"the default\" to be replaced by another \"custom\n> default\" is a good start, but we probably want to support more than\n> one notes refs, to parallel how \"struct display_notes_opt\" has\n> extra_notes_refs to allow multiple notes refs to decorate objects.\n\nI imagine that if we allowed multiple notes refs, then we would need\nto use a ref prefix to define a namespace. If we relaxed that, then\nwe could modify this as follows:\n\n\t.ref = \"refs/notes/\",\n\t/* .exact = 0, */\n\n(The comment is included just to illustrate the change.)\n\nThere is additional logic in init_notes() to track multiple notes\nrefs, but the change to things that use ref_namespaces would be\nminimal.\n\nThanks,\n-Stolee\n"},{"id":"460614","messageId":"cba0dc06-9fc5-772a-53fd-3ec22c04153e@github.com","threadId":"58226","inReplyTo":"Yur5OmTAYDx0ifsp@google.com","subject":"Re: [PATCH v2 03/10] refs: add array of ref namespaces","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-08-04T13:29:53Z","receivedAt":"2022-08-04T13:30:01Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/3/2022 6:39 PM, Josh Steadmon wrote:\n> On 2022.07.29 19:29, Derrick Stolee via GitGitGadget wrote:\n\n>> +\t/*\n>> +\t * If 'exact' is true, then we must match the 'ref' exactly.\n>> +\t * Otherwise, use a prefix match.\n>> +\t *\n>> +\t * 'orig_ref' is for internal use. It represents whether the\n> \n> s/orig_ref/ref_updated/ here I think.\n\nThanks!\n-Stolee\n"},{"id":"460615","messageId":"d77c25f6-aab1-58e3-faae-36cfa3204925@github.com","threadId":"58226","inReplyTo":"Yur49obfOHwu2B5t@google.com","subject":"Re: [PATCH v2 04/10] refs: use ref_namespaces for replace refs base","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-08-04T13:30:52Z","receivedAt":"2022-08-04T13:30:58Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/3/2022 6:38 PM, Josh Steadmon wrote:\n> On 2022.07.29 19:29, Derrick Stolee via GitGitGadget wrote:\n>> diff --git a/log-tree.c b/log-tree.c\n>> index d0ac0a6327a..bb80f1a94d2 100644\n>> --- a/log-tree.c\n>> +++ b/log-tree.c\n>> @@ -141,10 +141,12 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,\n>>  \tenum object_type objtype;\n>>  \tenum decoration_type deco_type = DECORATION_NONE;\n>>  \tstruct decoration_filter *filter = (struct decoration_filter *)cb_data;\n>> +\tconst char *git_replace_ref_base;\n>>  \n>>  \tif (filter && !ref_filter_match(refname, filter))\n>>  \t\treturn 0;\n>>  \n>> +\tgit_replace_ref_base = ref_namespaces[NAMESPACE_REPLACE].ref;\n> \n> Is there a reason not to initialize this as soon as we declare it?\n\nNo, there is not. Thanks!\n-Stolee\n"},{"id":"460616","messageId":"b4f07dd1-b59d-864b-f881-110c9bf87202@github.com","threadId":"58226","inReplyTo":"xmqqv8r9dei7.fsf@gitster.g","subject":"Re: [PATCH v2 05/10] log-tree: use ref_namespaces instead of if/else-if","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-08-04T13:31:41Z","receivedAt":"2022-08-04T13:31:46Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/3/2022 2:31 AM, Junio C Hamano wrote:\n> \"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n> \n>> From: Derrick Stolee <derrickstolee@github.com>\n>> +\tfor (i = 0; i < NAMESPACE__COUNT; i++) {\n>> +\t\tstruct ref_namespace_info *info = &ref_namespaces[i];\n>> +\n>> +\t\tif (!info->decoration)\n>> +\t\t\tcontinue;\n>> +\t\tif (info->exact) {\n>> +\t\t\tif (!strcmp(refname, info->ref)) {\n>> +\t\t\t\tdeco_type = info->decoration;\n>> +\t\t\t\tbreak;\n>> +\t\t\t}\n>> +\t\t} else if (starts_with(refname, info->ref)) {\n>> +\t\t\tdeco_type = info->decoration;\n>> +\t\t\tbreak;\n>> +\t\t}\n>> +\t}\n> \n> Very nice.  The double-dash in the NAMESPACE__COUNT constant somehow\n> looks strange.  As we scan through ref_namespace[] array densely,\n> \n> \tfor (i = 0; i < ARRAY_SIZE(ref_namespace); i++)\n> \t\t...\n> \n> without having to use the constant would probably be more in line\n> with the way how the rest of the codebase works.\n\nAh, I did not know about that trick. Thanks!\n\n-Stolee\n"},{"id":"460617","messageId":"bf77e4cb-6205-36d3-d7e9-e2ea989ea637@github.com","threadId":"58226","inReplyTo":"Yur5wXXiBtKRO/Y5@google.com","subject":"Re: [PATCH v2 08/10] log: create log.decorateFilter=all","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-08-04T13:38:11Z","receivedAt":"2022-08-04T13:38:17Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/3/2022 6:42 PM, Josh Steadmon wrote:\n> On 2022.07.29 19:29, Derrick Stolee via GitGitGadget wrote:\n\n>> +log.decorateFilter::\n>> +\tBy default, `git log` only shows decorations for certain known ref\n>> +\tnamespaces. If 'all' is specified, then show all possible ref\n>> +\tdecorations. Default value is 'default'.\n>> +\n> \n> Could we make it more clear here that \"all\" is the only supported value?\n> IIUC any other value will just get the default behavior. Just reading\n> the doc as-is, I worry that users might expect that they can add\n> specific refs / ref-patterns that would be added to the filter.\n\nPerhaps that's a sign that the config key is poorly named. I had\nconsidered other options:\n\n* log.decorateFilterMode (seemed too long)\n* log.decorateMode (hard to distinguish from log.decorate)\n\nPerhaps we could leave this as a boolean config with the name\n'log.decorateHiddenRefs' with default being 'false'? I'd love to\nexplore other options.\n\nThanks,\n-Stolee\n"},{"id":"460620","messageId":"2d24b539-a5b8-ed7d-2320-97588854eb5b@github.com","threadId":"58226","inReplyTo":"b4f07dd1-b59d-864b-f881-110c9bf87202@github.com","subject":"Re: [PATCH v2 05/10] log-tree: use ref_namespaces instead of if/else-if","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-08-04T14:34:36Z","receivedAt":"2022-08-04T14:34:42Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/4/2022 9:31 AM, Derrick Stolee wrote:\n> On 8/3/2022 2:31 AM, Junio C Hamano wrote:\n>> \"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>>\n>>> From: Derrick Stolee <derrickstolee@github.com>\n>>> +\tfor (i = 0; i < NAMESPACE__COUNT; i++) {\n>>> +\t\tstruct ref_namespace_info *info = &ref_namespaces[i];\n>>> +\n>>> +\t\tif (!info->decoration)\n>>> +\t\t\tcontinue;\n>>> +\t\tif (info->exact) {\n>>> +\t\t\tif (!strcmp(refname, info->ref)) {\n>>> +\t\t\t\tdeco_type = info->decoration;\n>>> +\t\t\t\tbreak;\n>>> +\t\t\t}\n>>> +\t\t} else if (starts_with(refname, info->ref)) {\n>>> +\t\t\tdeco_type = info->decoration;\n>>> +\t\t\tbreak;\n>>> +\t\t}\n>>> +\t}\n>>\n>> Very nice.  The double-dash in the NAMESPACE__COUNT constant somehow\n>> looks strange.  As we scan through ref_namespace[] array densely,\n>>\n>> \tfor (i = 0; i < ARRAY_SIZE(ref_namespace); i++)\n>> \t\t...\n>>\n>> without having to use the constant would probably be more in line\n>> with the way how the rest of the codebase works.\n> \n> Ah, I did not know about that trick. Thanks!\n\n...except that it doesn't work because the array is declared as\n'extern' so we don't know its size outside of refs.c.\n\nThis motivates the use of NAMESPACE__COUNT (and the double\nunderscores differentiates the \"COUNT\" from other namespaces, so\nthere is no confusion about \"COUNT\" being a namespace). If there\nis another way around this, then I would love to hear it!\n\nThanks,\n-Stolee\n"},{"id":"460622","messageId":"96cf691b-5190-5ba7-d612-e8473055c45c@github.com","threadId":"58226","inReplyTo":"2d24b539-a5b8-ed7d-2320-97588854eb5b@github.com","subject":"Re: [PATCH v2 05/10] log-tree: use ref_namespaces instead of if/else-if","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-08-04T14:50:57Z","receivedAt":"2022-08-04T14:51:02Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/4/2022 10:34 AM, Derrick Stolee wrote:\n> On 8/4/2022 9:31 AM, Derrick Stolee wrote:\n>> On 8/3/2022 2:31 AM, Junio C Hamano wrote:\n\n>>> Very nice.  The double-dash in the NAMESPACE__COUNT constant somehow\n>>> looks strange.  As we scan through ref_namespace[] array densely,\n>>>\n>>> \tfor (i = 0; i < ARRAY_SIZE(ref_namespace); i++)\n>>> \t\t...\n>>>\n>>> without having to use the constant would probably be more in line\n>>> with the way how the rest of the codebase works.\n>>\n>> Ah, I did not know about that trick. Thanks!\n> \n> ...except that it doesn't work because the array is declared as\n> 'extern' so we don't know its size outside of refs.c.\n> \n> This motivates the use of NAMESPACE__COUNT (and the double\n> underscores differentiates the \"COUNT\" from other namespaces, so\n> there is no confusion about \"COUNT\" being a namespace). If there\n> is another way around this, then I would love to hear it!\n\nMy current workaround is to define the size of the array in the\nheader file:\n\n---\n\nenum ref_namespace {\n\tNAMESPACE_HEAD,\n\tNAMESPACE_BRANCHES,\n\tNAMESPACE_TAGS,\n\tNAMESPACE_REMOTE_REFS,\n\tNAMESPACE_STASH,\n\tNAMESPACE_REPLACE,\n\tNAMESPACE_NOTES,\n\tNAMESPACE_PREFETCH,\n\tNAMESPACE_REWRITTEN,\n\n\t/* Must be last */\n\tNAMESPACE__COUNT\n};\n\n/* See refs.c for the contents of this array. */\nextern struct ref_namespace_info ref_namespaces[NAMESPACE__COUNT];\n\n---\n\nThen ARRAY_SIZE(ref_namespaces) works properly.\n\nThanks,\n-Stolee\n"},{"id":"460629","messageId":"xmqqles46l2n.fsf@gitster.g","threadId":"58226","inReplyTo":"9d60ae93-5acf-cf26-f0ab-cc2aa0808f7e@github.com","subject":"Re: [PATCH v2 03/10] refs: add array of ref namespaces","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-08-04T16:16:16Z","receivedAt":"2022-08-04T16:16:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Derrick Stolee <derrickstolee@github.com> writes:\n\n>>> +\t\t * by the core.notesRef config variable or the\n>>> +\t\t * GIT_NOTES_REFS environment variable.\n>>> +\t\t */\n>>> +\t\t.ref = \"refs/notes/commit\",\n>>> +\t\t.exact = 1,\n>> \n>> Allowing just \"the default\" to be replaced by another \"custom\n>> default\" is a good start, but we probably want to support more than\n>> one notes refs, to parallel how \"struct display_notes_opt\" has\n>> extra_notes_refs to allow multiple notes refs to decorate objects.\n>\n> I imagine that if we allowed multiple notes refs, then we would need\n> to use a ref prefix to define a namespace. If we relaxed that, then\n> we could modify this as follows:\n>\n> \t.ref = \"refs/notes/\",\n> \t/* .exact = 0, */\n>\n> (The comment is included just to illustrate the change.)\n\nAs I do not think it is so bad to decorate a commit with, say,\nrefs/notes/amlog in \"git log --notes\" (not \"git log --notes=amlog\")\noutput if such a commit happens to appear, so limiting to the single\nnotes ref that is given by notes.displayRef and ignoring others like\nthe posted patch felt like an over-engineering that may result in\neven a negative gain.  Treating it just like \"tags\" and \"remotes\"\nhierarchy would match intuition better for people, I suspect.\n\nThanks.\n\n\n"},{"id":"460645","messageId":"xmqqczdg6j5q.fsf@gitster.g","threadId":"58226","inReplyTo":"64ee889369dd4044a4acd967876476ea6cfff1c3.1659122979.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 07/10] log: add --decorate-all option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-08-04T16:57:37Z","receivedAt":"2022-08-04T16:57:47Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> +static int decorate_all;\n> +static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n> +static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;\n> +static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n> +\n> +static int decorate_all_callback(const struct option *opt,\n> +\t\t\t\t const char *arg, int unset)\n> +{\n> +\tif (unset) {\n> +\t\tdecorate_all = 0;\n> +\t\treturn 0;\n> +\t}\n> +\n> +\tstring_list_clear(&decorate_refs_include, 0);\n> +\tstring_list_clear(&decorate_refs_exclude, 0);\n> +\tdecorate_all = 1;\n\nHere, we clear include and exclude list, and set the flag.\n\n> +\treturn 0;\n> +}\n> +\n>  static int decorate_callback(const struct option *opt, const char *arg, int unset)\n>  {\n>  \tif (unset)\n> @@ -176,7 +195,8 @@ static void set_default_d\n>  \t\t\t\t\t   item->string);\n>  \t}\n>  \n> -\tif (decoration_filter->exclude_ref_pattern->nr ||\n> +\tif (decorate_all ||\n> +\t    decoration_filter->exclude_ref_pattern->nr ||\n>  \t    decoration_filter->include_ref_pattern->nr ||\n>  \t    decoration_filter->exclude_ref_config_pattern->nr)\n>  \t\treturn;\n\nIn the pre-context of this hunk, we still pay attention to the\nconfiguration variable log.excludedDecoration and stuff them in\nexclude_ref_config_pattern.  Presense of decorate_all option makes\nus leave early from this function, skipping the addition of\nhardcoded default patterns from the ref_namespace[] array.\n\nMost notably, clearing of exclude_ref_pattern and\ninclude_ref_pattern is done when \"--decorate-all\" was parsed, and\nnot here.  So we may have patterns there if \n\n\tgit log --decorate-all \\\n\t\t--decorate-refs=<pattern> \\\n\t\t--decorate-refs-exclude=<pattern>\n\nLater, log-tree.c::load_ref_decoration() uses these patterns to\ndecide what to exclude and to include.\n\nSo to me, this command option does not look like \"all\" at all.  It\nis more like \"clear\", with a side effect visible and noticeable only\nto implementors.\n\nIf we explain the decoration feature to end users in such a way to\nform this mental model, then this option becomes truly \"clear the\ninclusion and exclusion patterns for ref decoration\".\n\n    \"log --decorate\" uses lists of include and exclude patterns to\n    decide which refs are used for decoration.  Before the user\n    gives any patterns, the system adds the default include and\n    exclude patterns in the list.  The user can use --decorate-refs\n    and --decorate-refs-exclude options to add more of them to the\n    lists.\n\nThen this option can be explained to \"clear what has been\naccumulated in the lists of include and exclude patterns\" and that\nalso gets rid of what the system adds by default.\n\nI am not sure what to call and how to explain the corresponding\nconfiguration variable introduced in the next step, though.\n\nThanks.\n"},{"id":"460648","messageId":"xmqqsfmb6hxx.fsf@gitster.g","threadId":"58226","inReplyTo":"CAPig+cSjHf3d6xKT71biR8Cd0iKHqBpQ6Q9_bd_w9Hgg_uE=0g@mail.gmail.com","subject":"Re: [PATCH v2 02/10] t4207: test coloring of grafted decorations","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-08-04T17:23:54Z","receivedAt":"2022-08-04T17:24:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Sunshine <sunshine@sunshineco.com> writes:\n\n> it's hardly a cause for concern at this point (though, I still\n> reflexively write the more portable notation as used by `OID_REGEX`\n> and `_x05`, etc.).\n\nYeah, use of predefined constants we have in our test framework\nreleaves us from having to worry about the issue, which is why\nI too am in favor of using them.\n"},{"id":"460650","messageId":"xmqq8ro36h5i.fsf@gitster.g","threadId":"58226","inReplyTo":"96cf691b-5190-5ba7-d612-e8473055c45c@github.com","subject":"Re: [PATCH v2 05/10] log-tree: use ref_namespaces instead of if/else-if","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-08-04T17:40:57Z","receivedAt":"2022-08-04T17:41:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Derrick Stolee <derrickstolee@github.com> writes:\n\n> My current workaround is to define the size of the array in the\n> header file:\n>\n> ---\n>\n> enum ref_namespace {\n> \tNAMESPACE_HEAD,\n> \tNAMESPACE_BRANCHES,\n> \tNAMESPACE_TAGS,\n> \tNAMESPACE_REMOTE_REFS,\n> \tNAMESPACE_STASH,\n> \tNAMESPACE_REPLACE,\n> \tNAMESPACE_NOTES,\n> \tNAMESPACE_PREFETCH,\n> \tNAMESPACE_REWRITTEN,\n>\n> \t/* Must be last */\n> \tNAMESPACE__COUNT\n> };\n>\n> /* See refs.c for the contents of this array. */\n> extern struct ref_namespace_info ref_namespaces[NAMESPACE__COUNT];\n\nBecause there is no reason why we want to keep the size of the array\nopaque in this particular case, it may even be preferrable over the\noriginal ref_namespace[] array of unspecified size.  Nice.\n\nBTW, I prefer to name my arrays with a singular noun, when the\npredominant use of it in the code that is an API customer is to name\nan individual element and use it.\n\nIn this case, many API users do things like\n\n   ref_namespace[NAMESPACE_NOTES}.ref = ...;\n\nso a singular name would be more appropriate.  thing[4] that means\nthe fourth thing feels more intuitive than things[4], at least to\nme.\n\nOn the other hand, when API customers mostly pass the whole thing\naround as an almost opaque collection to the API function, then a\nplural name is more appropriate.  The reason why I focus on API\ncustomers is because API implementation of course has to go in to\neach individual element of the array and work on it at some level,\nand \"individual access means singular name\" rule would become non\nworkable.  The names are mostly to help API customers, so if an\narray is perceived by them as mostly a collection of things, then\nnaming it in plural would make it more natural.\n"},{"id":"460659","messageId":"94705746-809a-48ee-2aae-6f2878222f95@github.com","threadId":"58226","inReplyTo":"xmqq8ro36h5i.fsf@gitster.g","subject":"Re: [PATCH v2 05/10] log-tree: use ref_namespaces instead of if/else-if","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-08-04T20:17:15Z","receivedAt":"2022-08-04T20:17:22Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/4/2022 1:40 PM, Junio C Hamano wrote:\n> Derrick Stolee <derrickstolee@github.com> writes:\n> \n>> My current workaround is to define the size of the array in the\n>> header file:\n>>\n>> ---\n>>\n>> enum ref_namespace {\n>> \tNAMESPACE_HEAD,\n>> \tNAMESPACE_BRANCHES,\n>> \tNAMESPACE_TAGS,\n>> \tNAMESPACE_REMOTE_REFS,\n>> \tNAMESPACE_STASH,\n>> \tNAMESPACE_REPLACE,\n>> \tNAMESPACE_NOTES,\n>> \tNAMESPACE_PREFETCH,\n>> \tNAMESPACE_REWRITTEN,\n>>\n>> \t/* Must be last */\n>> \tNAMESPACE__COUNT\n>> };\n>>\n>> /* See refs.c for the contents of this array. */\n>> extern struct ref_namespace_info ref_namespaces[NAMESPACE__COUNT];\n> \n> Because there is no reason why we want to keep the size of the array\n> opaque in this particular case, it may even be preferrable over the\n> original ref_namespace[] array of unspecified size.  Nice.\n> \n> BTW, I prefer to name my arrays with a singular noun, when the\n> predominant use of it in the code that is an API customer is to name\n> an individual element and use it.\n> \n> In this case, many API users do things like\n> \n>    ref_namespace[NAMESPACE_NOTES}.ref = ...;\n> \n> so a singular name would be more appropriate.  thing[4] that means\n> the fourth thing feels more intuitive than things[4], at least to\n> me.\n\nThis makes sense to me.\n\n> On the other hand, when API customers mostly pass the whole thing\n> around as an almost opaque collection to the API function, then a\n> plural name is more appropriate.  The reason why I focus on API\n> customers is because API implementation of course has to go in to\n> each individual element of the array and work on it at some level,\n> and \"individual access means singular name\" rule would become non\n> workable.  The names are mostly to help API customers, so if an\n> array is perceived by them as mostly a collection of things, then\n> naming it in plural would make it more natural.\n\nUnderstood. I think this array does not seem to fit this second\ncase, so I will change it to be singular.\n\nThanks,\n-Stolee\n"},{"id":"460708","messageId":"f999258e-1822-bf38-dd2a-e553f1d796b7@github.com","threadId":"58226","inReplyTo":"xmqqsfmb6hxx.fsf@gitster.g","subject":"Re: [PATCH v2 02/10] t4207: test coloring of grafted decorations","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-08-05T14:21:49Z","receivedAt":"2022-08-05T14:21:59Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/4/2022 1:23 PM, Junio C Hamano wrote:\n> Eric Sunshine <sunshine@sunshineco.com> writes:\n> \n>> it's hardly a cause for concern at this point (though, I still\n>> reflexively write the more portable notation as used by `OID_REGEX`\n>> and `_x05`, etc.).\n> \n> Yeah, use of predefined constants we have in our test framework\n> releaves us from having to worry about the issue, which is why\n> I too am in favor of using them.\n\nThanks. Using $OID_REGEX (along with --no-abbrev) will work\nperfectly for this script.\n\n-Stolee\n"},{"id":"460710","messageId":"ac7b3a81-7ca6-05d3-6633-4204066aa933@github.com","threadId":"58226","inReplyTo":"220804.86iln8e9hl.gmgdl@evledraar.gmail.com","subject":"Re: [PATCH v2 06/10] log: add default decoration filter","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-08-05T14:27:51Z","receivedAt":"2022-08-05T14:27:58Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/4/2022 3:08 AM, Ævar Arnfjörð Bjarmason wrote:\n\n> There's no lack of \"stability\", because the ref hiding only act on\n> what's known to be something we can ignore, because our git version\n> knows about it.\n> \n> If git v2.40 knows about refs/magical-1/* but not refs/magical-2/*, but\n> git v2.50 knows about both it's not a lack of stability that v2.40 shows\n> one decorated by default, but v2.50 shows neither.\n\nYou are describing how the behavior changes between these versions on\nthe same repository. That's what I mean by lack of stability.\n\n> But it's not just that I disagree, I genuinely don't get your POV\n> here.\n\nI'm optimizing for non-experts who never need any refs outside of the\nstandard set. Now that this version removed the notes ref from the\ndecoration, the stance for inclusion is simple:\n\n  If Git offers to color the namespace with color.decoration.<slot>,\n  then Git decorates with that namespace by default.\n\n>> +test_expect_success 'log --decorate does not include things outside filter' '\n>> +\treflist=\"refs/prefetch refs/rebase-merge refs/bundle\" &&\n>> +\n>> +\tfor ref in $reflist\n>> +\tdo\n>> +\t\tgit update-ref $ref/fake HEAD || return 1\n>> +\tdone &&\n>> +\n>> +\tgit log --decorate=full --oneline >actual &&\n>> +\n>> +\tfor ref in $reflist\n>> +\tdo\n>> +\t\t! grep $ref/fake actual || return 1\n>> +\tdone\n> \n> I haven't tested, but isn't that last for-loop replacable with:\n> \n> \t! grep /fake actual\n> \n> ?\n> \n> Or do we have other \"/fake\" refs we want to include?\n\nThis is a nice efficient replacement. Thanks.\n\n-Stolee\n"},{"id":"460712","messageId":"220805.86zggirb7b.gmgdl@evledraar.gmail.com","threadId":"58226","inReplyTo":"ac7b3a81-7ca6-05d3-6633-4204066aa933@github.com","subject":"Re: [PATCH v2 06/10] log: add default decoration filter","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-08-05T14:50:11Z","receivedAt":"2022-08-05T14:56:25Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Aug 05 2022, Derrick Stolee wrote:\n\n> On 8/4/2022 3:08 AM, Ævar Arnfjörð Bjarmason wrote:\n>\n>> There's no lack of \"stability\", because the ref hiding only act on\n>> what's known to be something we can ignore, because our git version\n>> knows about it.\n>> \n>> If git v2.40 knows about refs/magical-1/* but not refs/magical-2/*, but\n>> git v2.50 knows about both it's not a lack of stability that v2.40 shows\n>> one decorated by default, but v2.50 shows neither.\n>\n> You are describing how the behavior changes between these versions on\n> the same repository. That's what I mean by lack of stability.\n\nIf you want that forward-stability wouldn't another way to accomplish\nthis to put all of these new magical refs in the same refs/git-internal/\nnamespace, e.g. refs/git-internal/foo/, refs/git-internal/bar/?\n\n>> But it's not just that I disagree, I genuinely don't get your POV\n>> here.\n>\n> I'm optimizing for non-experts who never need any refs outside of the\n> standard set.\n\nClearly, I'm wondering if we can find a way forward that doesn't change\nexisting long-statnding behavior and caters to the \"stability\" of future\ninter-version behavior with this new class of refs.\n\n> Now that this version removed the notes ref from the\n> decoration, the stance for inclusion is simple:\n>\n>   If Git offers to color the namespace with color.decoration.<slot>,\n>   then Git decorates with that namespace by default.\n\nI'm a bit confused, sorry.\n\nSo aside from \"notes\", if we have a color.decoration.<slot> applying to\na ref now, it's a bug in your series if it's not showing up anymore?\n\nI still find that inclusion criteria to be a bit odd, we've usually\nconsidered colors optional sugar. Just because nobody bothered to add a\ncoloring config for it doesn't seem like a good reason to not show\nsomething at all.\n"},{"id":"460713","messageId":"2184ffe4-4fde-878f-052f-e7dcdebe8161@github.com","threadId":"58226","inReplyTo":"220805.86zggirb7b.gmgdl@evledraar.gmail.com","subject":"Re: [PATCH v2 06/10] log: add default decoration filter","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-08-05T15:09:37Z","receivedAt":"2022-08-05T15:09:43Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/5/2022 10:50 AM, Ævar Arnfjörð Bjarmason wrote:\n> \n> On Fri, Aug 05 2022, Derrick Stolee wrote:\n\n>> Now that this version removed the notes ref from the\n>> decoration, the stance for inclusion is simple:\n>>\n>>   If Git offers to color the namespace with color.decoration.<slot>,\n>>   then Git decorates with that namespace by default.\n> \n> I'm a bit confused, sorry.\n> \n> So aside from \"notes\", if we have a color.decoration.<slot> applying to\n> a ref now, it's a bug in your series if it's not showing up anymore?\n\nThe possible slots are:\n\n * branch (refs/heads/)\n * remoteBranch (refs/remotes/)\n * tag (refs/tags/)\n * stash (refs/stash)\n * HEAD (HEAD)\n * grafted (refs/replace/ or GIT_REPLACE_REF_BASE)\n\nThese are exactly the namespaces that are now shown by default in\nthis series.\n\nIf someone adds a new color slot, then that would need to be\njustified with a reason why that slot is important. We've already\nhad discussions as to why showing a decoration for notes is not\nvaluable to an end user. The stability of this config option (the\nlast addition of 'grafted' was in 2011) is good evidence that this\ncore set of namespaces is all users will need.\n\nBy contrast, the use of \"hidden\" namespaces is relatively new and\nis expected to increase in the near future.\n\n-Stolee\n"},{"id":"460723","messageId":"pull.1301.v3.git.1659722323.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v2.git.1659122979.gitgitgadget@gmail.com","subject":"[PATCH v3 00/11] log: create tighter default decoration filter","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-08-05T17:58:32Z","receivedAt":"2022-08-05T17:59:01Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"When running 'git log', the default is to report any refs within refs/* as\ndecorations. This series reduces the default set to be more specific to a\nset of known-useful namespaces.\n\nThis was previously reduced by adding the log.excludeDecoration config\noption and modifying that config in git maintenance's prefetch task (to hide\nrefs/prefetch/*). I then followed that pattern again for the bundle URI\nfeature [1], but this caught some reviewers by surprise as an unfortunate\nside-effect. This series is a way to roll back the previous decision to use\nlog.excludeDecoration and instead use tighter filters by default.\n\n[1]\nhttps://lore.kernel.org/git/a217e9a0640b45d21ef971d6e91cee3f1993f383.1656535245.git.gitgitgadget@gmail.com/\n\nThe current design ignores the new filters if there are any\npreviously-specified filters. This includes the\nlog.excludeDecorations=refs/prefetch/ set by the git maintenance command.\nThis means that users who ran that command in their repo will not get the\nbenefits of the more strict filters. While we stop writing\nlog.excludeDecorations, we don't remove existing instances of it. This\nshould be fine at least for the refs/bundles/ namespace in the future, since\nthose refs will typically be created for new clones that have not yet had\nthe log.excludeDecoration setting.\n\nTo make it easy for users to opt-in to the previous behavior, add a new git\nlog --decorate-all option and log.decorateFilter=all config option.\n\n\nUpdates in v3\n=============\n\n * Fixed braces in if/else-if in patch 1. Also added a NEEDSWORK comment.\n * Added a patch that modernizes t4207 and converts some logic to a helper.\n * Updated the new tests in t4207 to use the new helper.\n * Used singular ref_namespace instead of ref_namespaces.\n * Update definition of refs_namespace to have fixed size so we can use\n   ARRAY_SIZE() in a loop.\n * Renamed the CLI option to --clear-decorations and the config option to\n   log.initialDecorationSet.\n * Several recommended style updates and typo fixes.\n\n\nUpdates in v2\n=============\n\n * As discussed in the previous version, there are a lot of places that care\n   about different subsets of the special ref namespaces. This version\n   creates a new ref_namespaces array that centralizes and describes how\n   these known ref namespaces interact with other Git features.\n\n * Some patches are added to help centralize previously-unrelated features\n   onto the ref_namespaces array.\n\n * One thing that I noticed while doing this work was that notes come from a\n   commit history that is pointed by a single ref, not multiple refs in a\n   namespace. Also, that ref can change based on config and environment\n   variables. This version updates that knowledge to allow our\n   ref_namespaces[NAMESPACE_NOTES] value change with these settings. Since\n   there is only one ref, I also chose to remove it from the default\n   decorations. As Junio mentioned, this should not make any difference\n   since a user won't see it unless they purposefully start git log from the\n   notes ref.\n\n * Despite feedback to the opposite, I maintain my opinion that this default\n   filter should be a small list of known-useful namespaces. For expert\n   users who use other namespaces, I added patches that make it easier to\n   show custom namespaces (specifically --decorate-all and\n   log.decorateFilter=all). The logic for creating the default filter now\n   uses the ref_namespaces array in such a way that it would be simple to\n   reverse this decision, and I include that alternate implementation in a\n   commit message.\n\n * This version includes several code and test style improvements.\n\n * The final patch demonstrates how we can remove some duplicate string\n   literals for these namespaces. It is focused on the prefetch namespace\n   (and an adjacent use of the tags namespace) because of how this series\n   changes our handling of that namespace in particular. This makes it\n   easier for a future change to modify the namespace via config or\n   environment variables. There are opportunities to do this kind of update\n   more widely, but I don't want to set that as a critical refactor to do\n   right now.\n\nThanks, -Stolee\n\nDerrick Stolee (11):\n  refs: allow \"HEAD\" as decoration filter\n  t4207: modernize test\n  t4207: test coloring of grafted decorations\n  refs: add array of ref namespaces\n  refs: use ref_namespaces for replace refs base\n  log-tree: use ref_namespaces instead of if/else-if\n  log: add default decoration filter\n  log: add --clear-decorations option\n  log: create log.initialDecorationSet=all\n  maintenance: stop writing log.excludeDecoration\n  fetch: use ref_namespaces during prefetch\n\n Documentation/config/log.txt                  |   5 +\n Documentation/git-log.txt                     |  14 +-\n builtin/fetch.c                               |   6 +-\n builtin/gc.c                                  |   6 -\n builtin/log.c                                 |  84 ++++++++---\n builtin/replace.c                             |   3 +\n cache.h                                       |   1 -\n environment.c                                 |   5 +-\n log-tree.c                                    |  27 ++--\n notes.c                                       |   1 +\n refs.c                                        |  95 ++++++++++++-\n refs.h                                        |  46 ++++++\n t/t4013-diff-various.sh                       |   2 +\n t/t4013/diff.log_--decorate=full_--all        |   2 +-\n ..._--decorate=full_--clear-decorations_--all |  61 ++++++++\n ...f.log_--decorate=full_--decorate-all_--all |  61 ++++++++\n t/t4013/diff.log_--decorate_--all             |   2 +-\n ...f.log_--decorate_--clear-decorations_--all |  61 ++++++++\n .../diff.log_--decorate_--decorate-all_--all  |  61 ++++++++\n t/t4202-log.sh                                | 132 +++++++++++++++++-\n t/t4207-log-decoration-colors.sh              |  90 +++++++++---\n t/t7900-maintenance.sh                        |  21 ---\n 22 files changed, 701 insertions(+), 85 deletions(-)\n create mode 100644 t/t4013/diff.log_--decorate=full_--clear-decorations_--all\n create mode 100644 t/t4013/diff.log_--decorate=full_--decorate-all_--all\n create mode 100644 t/t4013/diff.log_--decorate_--clear-decorations_--all\n create mode 100644 t/t4013/diff.log_--decorate_--decorate-all_--all\n\n\nbase-commit: 6a475b71f8c4ce708d69fdc9317aefbde3769e25\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-1301%2Fderrickstolee%2Fdecorations-v3\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1301/derrickstolee/decorations-v3\nPull-Request: https://github.com/gitgitgadget/git/pull/1301\n\nRange-diff vs v2:\n\n  1:  c2e5a0b3a50 !  1:  1522889352f refs: allow \"HEAD\" as decoration filter\n     @@ Commit message\n      \n          It is sufficient to only cover \"HEAD\" here and not include other special\n          refs like REBASE_HEAD. This is because HEAD is the only ref outside of\n     -    refs/* that is added to the list of decorations.\n     +    refs/* that is added to the list of decorations. However, we may want to\n     +    special-case these other refs in normalize_glob_ref() in the future.\n     +    Leave a NEEDSWORK comment for now.\n      \n          Signed-off-by: Derrick Stolee <derrickstolee@github.com>\n      \n       ## refs.c ##\n      @@ refs.c: void normalize_glob_ref(struct string_list_item *item, const char *prefix,\n     + \tif (*pattern == '/')\n     + \t\tBUG(\"pattern must not start with '/'\");\n       \n     - \tif (prefix) {\n     +-\tif (prefix) {\n     ++\tif (prefix)\n       \t\tstrbuf_addstr(&normalized_pattern, prefix);\n      -\t}\n      -\telse if (!starts_with(pattern, \"refs/\"))\n     -+\t} else if (!starts_with(pattern, \"refs/\") &&\n     ++\telse if (!starts_with(pattern, \"refs/\") &&\n      +\t\t   strcmp(pattern, \"HEAD\"))\n       \t\tstrbuf_addstr(&normalized_pattern, \"refs/\");\n     ++\t/*\n     ++\t * NEEDSWORK: Special case other symrefs such as REBASE_HEAD,\n     ++\t * MERGE_HEAD, etc.\n     ++\t */\n     ++\n       \tstrbuf_addstr(&normalized_pattern, pattern);\n       \tstrbuf_strip_suffix(&normalized_pattern, \"/\");\n     + \n      \n       ## t/t4202-log.sh ##\n      @@ t/t4202-log.sh: test_expect_success 'decorate-refs and simplify-by-decoration without output' '\n  -:  ----------- >  2:  0633f8403db t4207: modernize test\n  2:  b5eb110958b !  3:  fafe20c1e82 t4207: test coloring of grafted decorations\n     @@ Commit message\n      \n       ## t/t4207-log-decoration-colors.sh ##\n      @@ t/t4207-log-decoration-colors.sh: test_expect_success setup '\n     + \tgit config color.decorate.remoteBranch red &&\n       \tgit config color.decorate.tag \"reverse bold yellow\" &&\n       \tgit config color.decorate.stash magenta &&\n     - \tgit config color.decorate.HEAD cyan &&\n      +\tgit config color.decorate.grafted black &&\n     + \tgit config color.decorate.HEAD cyan &&\n       \n       \tc_reset=\"<RESET>\" &&\n     - \n      @@ t/t4207-log-decoration-colors.sh: test_expect_success setup '\n       \tc_tag=\"<BOLD;REVERSE;YELLOW>\" &&\n       \tc_stash=\"<MAGENTA>\" &&\n     @@ t/t4207-log-decoration-colors.sh: test_expect_success setup '\n       \n       \ttest_commit A &&\n       \tgit clone . other &&\n     -@@ t/t4207-log-decoration-colors.sh: test_expect_success 'Commit Decorations Colored Correctly' '\n     - \ttest_cmp expected out\n     +@@ t/t4207-log-decoration-colors.sh: On main: Changes to A.t\n     + \tcmp_filtered_decorations\n       '\n       \n     -+cat >expected <<EOF\n     -+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD ->\\\n     -+ ${c_reset}${c_branch}main${c_reset}${c_commit},\\\n     -+ ${c_reset}${c_tag}tag: D${c_reset}${c_commit})${c_reset} D\n     -+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: C${c_reset}${c_commit},\\\n     -+ ${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} B\n     -+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A\n     -+EOF\n     -+\n      +test_expect_success 'test coloring with replace-objects' '\n      +\ttest_when_finished rm -rf .git/refs/replace* &&\n      +\ttest_commit C &&\n      +\ttest_commit D &&\n      +\n      +\tgit replace HEAD~1 HEAD~2 &&\n     -+\tgit log --first-parent --abbrev=10 --decorate --oneline --color=always HEAD |\n     -+\tsed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n     -+\ttest_decode_color >out &&\n     -+\ttest_cmp expected out &&\n     ++\n     ++\tcat >expect <<-EOF &&\n     ++\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \\\n     ++${c_reset}${c_branch}main${c_reset}${c_commit}, \\\n     ++${c_reset}${c_tag}tag: D${c_reset}${c_commit})${c_reset} D\n     ++\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: C${c_reset}${c_commit}, \\\n     ++${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} B\n     ++\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A\n     ++EOF\n     ++\n     ++\tgit log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual &&\n     ++\tcmp_filtered_decorations &&\n      +\tgit replace -d HEAD~1 &&\n      +\n      +\tGIT_REPLACE_REF_BASE=refs/replace2/ git replace HEAD~1 HEAD~2 &&\n     -+\tGIT_REPLACE_REF_BASE=refs/replace2/ git log --first-parent --abbrev=10 \\\n     -+\t\t--decorate --oneline --color=always HEAD |\n     -+\tsed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n     -+\ttest_decode_color >out &&\n     -+\ttest_cmp expected out\n     ++\tGIT_REPLACE_REF_BASE=refs/replace2/ git log --first-parent \\\n     ++\t\t--no-abbrev --decorate --oneline --color=always HEAD >actual &&\n     ++\tcmp_filtered_decorations\n      +'\n      +\n     -+cat >expected <<EOF\n     -+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD ->\\\n     -+ ${c_reset}${c_branch}main${c_reset}${c_commit},\\\n     -+ ${c_reset}${c_tag}tag: D${c_reset}${c_commit},\\\n     -+ ${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} D\n     -+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit},\\\n     -+ ${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B\n     -+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A\n     -+EOF\n     -+\n      +test_expect_success 'test coloring with grafted commit' '\n      +\ttest_when_finished rm -rf .git/refs/replace* &&\n      +\n      +\tgit replace --graft HEAD HEAD~2 &&\n     -+\tgit log --first-parent --abbrev=10 --decorate --oneline --color=always HEAD |\n     -+\tsed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n     -+\ttest_decode_color >out &&\n     -+\ttest_cmp expected out &&\n     ++\n     ++\tcat >expect <<-EOF &&\n     ++\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \\\n     ++${c_reset}${c_branch}main${c_reset}${c_commit}, \\\n     ++${c_reset}${c_tag}tag: D${c_reset}${c_commit}, \\\n     ++${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} D\n     ++\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit}, \\\n     ++${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B\n     ++\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A\n     ++\tEOF\n     ++\n     ++\tgit log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual &&\n     ++\tcmp_filtered_decorations &&\n      +\tgit replace -d HEAD &&\n      +\n      +\tGIT_REPLACE_REF_BASE=refs/replace2/ git replace --graft HEAD HEAD~2 &&\n     -+\tGIT_REPLACE_REF_BASE=refs/replace2/ git log --first-parent --abbrev=10 \\\n     -+\t\t--decorate --oneline --color=always HEAD |\n     -+\tsed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n     -+\ttest_decode_color >out &&\n     -+\ttest_cmp expected out\n     ++\tGIT_REPLACE_REF_BASE=refs/replace2/ git log --first-parent \\\n     ++\t\t--no-abbrev --decorate --oneline --color=always HEAD >actual &&\n     ++\tcmp_filtered_decorations\n      +'\n      +\n       test_done\n  3:  d7486390d57 !  4:  475ebca6310 refs: add array of ref namespaces\n     @@ refs.c: static unsigned char refname_disposition[256] = {\n       \t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4\n       };\n       \n     -+struct ref_namespace_info ref_namespaces[] = {\n     ++struct ref_namespace_info ref_namespace[] = {\n      +\t[NAMESPACE_HEAD] = {\n      +\t\t.ref = \"HEAD\",\n      +\t\t.decoration = DECORATION_REF_HEAD,\n     @@ refs.c: static unsigned char refname_disposition[256] = {\n      +\t\t/*\n      +\t\t * The refs/notes/commit ref points to the tip of a\n      +\t\t * parallel commit history that adds metadata to commits\n     -+\t\t * in the normal history. This branch can be overwritten\n     ++\t\t * in the normal history. This ref can be overwritten\n      +\t\t * by the core.notesRef config variable or the\n      +\t\t * GIT_NOTES_REFS environment variable.\n      +\t\t */\n     @@ refs.c: static unsigned char refname_disposition[256] = {\n      +\n      +void update_ref_namespace(enum ref_namespace namespace, char *ref)\n      +{\n     -+\tstruct ref_namespace_info *info = &ref_namespaces[namespace];\n     ++\tstruct ref_namespace_info *info = &ref_namespace[namespace];\n      +\tif (info->ref_updated)\n      +\t\tfree(info->ref);\n      +\tinfo->ref = ref;\n     @@ refs.h: struct ref_store *get_main_ref_store(struct repository *r);\n       \n      +/*\n      + * Some of the names specified by refs have special meaning to Git.\n     -+ * Organize these namespaces in a comon 'ref_namespaces' array for\n     ++ * Organize these namespaces in a comon 'ref_namespace' array for\n      + * reference from multiple places in the codebase.\n      + */\n      +\n     @@ refs.h: struct ref_store *get_main_ref_store(struct repository *r);\n      +\t * If 'exact' is true, then we must match the 'ref' exactly.\n      +\t * Otherwise, use a prefix match.\n      +\t *\n     -+\t * 'orig_ref' is for internal use. It represents whether the\n     ++\t * 'ref_updated' is for internal use. It represents whether the\n      +\t * 'ref' value was replaced from its original literal version.\n      +\t */\n      +\tunsigned exact:1,\n     @@ refs.h: struct ref_store *get_main_ref_store(struct repository *r);\n      +};\n      +\n      +/* See refs.c for the contents of this array. */\n     -+extern struct ref_namespace_info ref_namespaces[];\n     ++extern struct ref_namespace_info ref_namespace[NAMESPACE__COUNT];\n      +\n      +/*\n      + * Some ref namespaces can be modified by config values or environment\n  4:  8da0b0a3181 !  5:  45e3ce94d0d refs: use ref_namespaces for replace refs base\n     @@ builtin/replace.c: static int for_each_replace_name(const char **argv, each_repl\n       \tsize_t base_len;\n       \tint had_error = 0;\n       \tstruct object_id oid;\n     -+\tconst char *git_replace_ref_base = ref_namespaces[NAMESPACE_REPLACE].ref;\n     ++\tconst char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;\n       \n       \tstrbuf_addstr(&ref, git_replace_ref_base);\n       \tbase_len = ref.len;\n     @@ builtin/replace.c: static int check_ref_valid(struct object_id *object,\n       \t\t\t    struct strbuf *ref,\n       \t\t\t    int force)\n       {\n     -+\tconst char *git_replace_ref_base = ref_namespaces[NAMESPACE_REPLACE].ref;\n     ++\tconst char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;\n      +\n       \tstrbuf_reset(ref);\n       \tstrbuf_addf(ref, \"%s%s\", git_replace_ref_base, oid_to_hex(object));\n     @@ log-tree.c: static int add_ref_decoration(const char *refname, const struct obje\n       \tenum object_type objtype;\n       \tenum decoration_type deco_type = DECORATION_NONE;\n       \tstruct decoration_filter *filter = (struct decoration_filter *)cb_data;\n     -+\tconst char *git_replace_ref_base;\n     ++\tconst char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;\n       \n       \tif (filter && !ref_filter_match(refname, filter))\n       \t\treturn 0;\n     - \n     -+\tgit_replace_ref_base = ref_namespaces[NAMESPACE_REPLACE].ref;\n     - \tif (starts_with(refname, git_replace_ref_base)) {\n     - \t\tstruct object_id original_oid;\n     - \t\tif (!read_replace_refs)\n      \n       ## refs.c ##\n      @@ refs.c: int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,\n       \n       int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data)\n       {\n     -+\tconst char *git_replace_ref_base = ref_namespaces[NAMESPACE_REPLACE].ref;\n     ++\tconst char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;\n       \treturn do_for_each_repo_ref(r, git_replace_ref_base, fn,\n       \t\t\t\t    strlen(git_replace_ref_base),\n       \t\t\t\t    DO_FOR_EACH_INCLUDE_BROKEN, cb_data);\n  5:  53b15a0b793 !  6:  063e5bac2ce log-tree: use ref_namespaces instead of if/else-if\n     @@ log-tree.c: static int add_ref_decoration(const char *refname, const struct obje\n      -\t\tdeco_type = DECORATION_REF_STASH;\n      -\telse if (!strcmp(refname, \"HEAD\"))\n      -\t\tdeco_type = DECORATION_REF_HEAD;\n     -+\tfor (i = 0; i < NAMESPACE__COUNT; i++) {\n     -+\t\tstruct ref_namespace_info *info = &ref_namespaces[i];\n     ++\tfor (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {\n     ++\t\tstruct ref_namespace_info *info = &ref_namespace[i];\n      +\n      +\t\tif (!info->decoration)\n      +\t\t\tcontinue;\n  6:  bec532fb8c6 !  7:  c249bface2a log: add default decoration filter\n     @@ builtin/log.c: static void cmd_log_init_defaults(struct rev_info *rev)\n      +\t * No command-line or config options were given, so\n      +\t * populate with sensible defaults.\n      +\t */\n     -+\tfor (i = 0; i < NAMESPACE__COUNT; i++) {\n     -+\t\tif (!ref_namespaces[i].decoration)\n     ++\tfor (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {\n     ++\t\tif (!ref_namespace[i].decoration)\n      +\t\t\tcontinue;\n      +\n     -+\t\tstring_list_append(include, ref_namespaces[i].ref);\n     ++\t\tstring_list_append(include, ref_namespace[i].ref);\n      +\t}\n      +}\n      +\n     @@ t/t4202-log.sh: test_expect_success 'log --decorate includes all levels of tag a\n      +\n      +\tgit log --decorate=full --oneline >actual &&\n      +\n     -+\tfor ref in $reflist\n     -+\tdo\n     -+\t\t! grep $ref/fake actual || return 1\n     -+\tdone\n     ++\t# None of the refs are visible:\n     ++\t! grep /fake actual\n      +'\n      +\n       test_expect_success 'log --end-of-options' '\n  7:  64ee889369d !  8:  1b12374ff1b log: add --decorate-all option\n     @@ Metadata\n      Author: Derrick Stolee <derrickstolee@github.com>\n      \n       ## Commit message ##\n     -    log: add --decorate-all option\n     +    log: add --clear-decorations option\n     +\n     +    The previous changes introduced a new default ref filter for decorations\n     +    in the 'git log' command. This can be overridden using\n     +    --decorate-refs=HEAD and --decorate-refs=refs/, but that is cumbersome\n     +    for users.\n     +\n     +    Instead, add a --clear-decorations option that resets all previous\n     +    filters to a blank filter that accepts all refs.\n      \n          Signed-off-by: Derrick Stolee <derrickstolee@github.com>\n      \n     @@ Documentation/git-log.txt: If none of these options or config settings are given\n       used as decoration if they match `HEAD`, `refs/heads/`, `refs/remotes/`,\n       `refs/stash/`, or `refs/tags/`.\n       \n     -+--decorate-all::\n     ++--clear-decorations::\n      +\tWhen specified, this option clears all previous `--decorate-refs`\n      +\tor `--decorate-refs-exclude` options and relaxes the default\n     -+\tdecoration filter to include all possible decoration refs.\n     ++\tdecoration filter to include all references.\n      +\n       --source::\n       \tPrint out the ref name given on the command line by which each\n     @@ builtin/log.c: static int parse_decoration_style(const char *value)\n       \treturn -1;\n       }\n       \n     -+static int decorate_all;\n     ++static int use_default_decoration_filter = 1;\n      +static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n      +static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;\n      +static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n      +\n     -+static int decorate_all_callback(const struct option *opt,\n     -+\t\t\t\t const char *arg, int unset)\n     ++static int clear_decorations_callback(const struct option *opt,\n     ++\t\t\t\t\t    const char *arg, int unset)\n      +{\n     -+\tif (unset) {\n     -+\t\tdecorate_all = 0;\n     -+\t\treturn 0;\n     -+\t}\n     -+\n      +\tstring_list_clear(&decorate_refs_include, 0);\n      +\tstring_list_clear(&decorate_refs_exclude, 0);\n     -+\tdecorate_all = 1;\n     ++\tuse_default_decoration_filter = 0;\n      +\treturn 0;\n      +}\n      +\n     @@ builtin/log.c: static void set_default_decoration_filter(struct decoration_filte\n       \t}\n       \n      -\tif (decoration_filter->exclude_ref_pattern->nr ||\n     -+\tif (decorate_all ||\n     ++\tif (!use_default_decoration_filter ||\n      +\t    decoration_filter->exclude_ref_pattern->nr ||\n       \t    decoration_filter->include_ref_pattern->nr ||\n       \t    decoration_filter->exclude_ref_config_pattern->nr)\n     @@ builtin/log.c: static void cmd_log_init_finish(int argc, const char **argv, cons\n       \t\tOPT_BOOL(0, \"source\", &source, N_(\"show source\")),\n       \t\tOPT_BOOL(0, \"use-mailmap\", &mailmap, N_(\"use mail map file\")),\n       \t\tOPT_ALIAS(0, \"mailmap\", \"use-mailmap\"),\n     -+\t\tOPT_CALLBACK_F(0, \"decorate-all\", NULL, NULL, N_(\"how all ref decorations\"),\n     -+\t\t\t       PARSE_OPT_NOARG, decorate_all_callback),\n     ++\t\tOPT_CALLBACK_F(0, \"clear-decorations\", NULL, NULL,\n     ++\t\t\t       N_(\"clear all previously-defined decoration filters\"),\n     ++\t\t\t       PARSE_OPT_NOARG | PARSE_OPT_NONEG,\n     ++\t\t\t       clear_decorations_callback),\n       \t\tOPT_STRING_LIST(0, \"decorate-refs\", &decorate_refs_include,\n       \t\t\t\tN_(\"pattern\"), N_(\"only decorate refs that match <pattern>\")),\n       \t\tOPT_STRING_LIST(0, \"decorate-refs-exclude\", &decorate_refs_exclude,\n     @@ t/t4013-diff-various.sh: log -GF -p --pickaxe-all master\n       log -IA -IB -I1 -I2 -p master\n       log --decorate --all\n       log --decorate=full --all\n     -+log --decorate --decorate-all --all\n     -+log --decorate=full --decorate-all --all\n     ++log --decorate --clear-decorations --all\n     ++log --decorate=full --clear-decorations --all\n       \n       rev-list --parents HEAD\n       rev-list --children HEAD\n      \n     + ## t/t4013/diff.log_--decorate=full_--clear-decorations_--all (new) ##\n     +@@\n     ++$ git log --decorate=full --clear-decorations --all\n     ++commit b7e0bc69303b488b47deca799a7d723971dfa6cd (refs/heads/mode)\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:06:00 2006 +0000\n     ++\n     ++    update mode\n     ++\n     ++commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (refs/heads/note)\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:06:00 2006 +0000\n     ++\n     ++    update mode (file2)\n     ++\n     ++Notes:\n     ++    note\n     ++\n     ++commit cd4e72fd96faed3f0ba949dc42967430374e2290 (refs/heads/rearrange)\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:06:00 2006 +0000\n     ++\n     ++    Rearranged lines in dir/sub\n     ++\n     ++commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:06:00 2006 +0000\n     ++\n     ++    Notes added by 'git notes add'\n     ++\n     ++commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master)\n     ++Merge: 9a6d494 c7a2ab9\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:04:00 2006 +0000\n     ++\n     ++    Merge branch 'side'\n     ++\n     ++commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side)\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:03:00 2006 +0000\n     ++\n     ++    Side\n     ++\n     ++commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:02:00 2006 +0000\n     ++\n     ++    Third\n     ++\n     ++commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:01:00 2006 +0000\n     ++\n     ++    Second\n     ++    \n     ++    This is the second commit.\n     ++\n     ++commit 444ac553ac7612cc88969031b02b3767fb8a353a (refs/heads/initial)\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:00:00 2006 +0000\n     ++\n     ++    Initial\n     ++$\n     +\n       ## t/t4013/diff.log_--decorate=full_--decorate-all_--all (new) ##\n      @@\n      +$ git log --decorate=full --decorate-all --all\n     @@ t/t4013/diff.log_--decorate=full_--decorate-all_--all (new)\n      +Date:   Mon Jun 26 00:00:00 2006 +0000\n      +\n      +    Initial\n     ++$\n     +\n     + ## t/t4013/diff.log_--decorate_--clear-decorations_--all (new) ##\n     +@@\n     ++$ git log --decorate --clear-decorations --all\n     ++commit b7e0bc69303b488b47deca799a7d723971dfa6cd (mode)\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:06:00 2006 +0000\n     ++\n     ++    update mode\n     ++\n     ++commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (note)\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:06:00 2006 +0000\n     ++\n     ++    update mode (file2)\n     ++\n     ++Notes:\n     ++    note\n     ++\n     ++commit cd4e72fd96faed3f0ba949dc42967430374e2290 (rearrange)\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:06:00 2006 +0000\n     ++\n     ++    Rearranged lines in dir/sub\n     ++\n     ++commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:06:00 2006 +0000\n     ++\n     ++    Notes added by 'git notes add'\n     ++\n     ++commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master)\n     ++Merge: 9a6d494 c7a2ab9\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:04:00 2006 +0000\n     ++\n     ++    Merge branch 'side'\n     ++\n     ++commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side)\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:03:00 2006 +0000\n     ++\n     ++    Side\n     ++\n     ++commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:02:00 2006 +0000\n     ++\n     ++    Third\n     ++\n     ++commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:01:00 2006 +0000\n     ++\n     ++    Second\n     ++    \n     ++    This is the second commit.\n     ++\n     ++commit 444ac553ac7612cc88969031b02b3767fb8a353a (initial)\n     ++Author: A U Thor <author@example.com>\n     ++Date:   Mon Jun 26 00:00:00 2006 +0000\n     ++\n     ++    Initial\n      +$\n      \n       ## t/t4013/diff.log_--decorate_--decorate-all_--all (new) ##\n     @@ t/t4202-log.sh: test_expect_success 'decorate-refs focus from default' '\n       \t! grep HEAD actual\n       '\n       \n     -+test_expect_success '--decorate-all overrides defaults' '\n     ++test_expect_success '--clear-decorations overrides defaults' '\n      +\tcat >expect.default <<-\\EOF &&\n      +\tMerge-tag-reach (HEAD -> refs/heads/main)\n      +\tMerge-tags-octopus-a-and-octopus-b\n     @@ t/t4202-log.sh: test_expect_success 'decorate-refs focus from default' '\n      +\tinitial\n      +\tEOF\n      +\tgit log --decorate=full --pretty=\"tformat:%f%d\" \\\n     -+\t\t--decorate-all >actual &&\n     ++\t\t--clear-decorations >actual &&\n      +\ttest_cmp expect.all actual\n      +'\n      +\n     -+test_expect_success '--decorate-all clears previous exclusions' '\n     ++test_expect_success '--clear-decorations clears previous exclusions' '\n      +\tcat >expect.all <<-\\EOF &&\n      +\tMerge-tag-reach (HEAD -> refs/heads/main)\n      +\treach (tag: refs/tags/reach, refs/heads/reach)\n     @@ t/t4202-log.sh: test_expect_success 'decorate-refs focus from default' '\n      +\t\t--simplify-by-decoration \\\n      +\t\t--decorate-refs-exclude=\"heads/octopus*\" \\\n      +\t\t--decorate-refs=\"heads\" \\\n     -+\t\t--decorate-all >actual &&\n     ++\t\t--clear-decorations >actual &&\n      +\ttest_cmp expect.all actual &&\n      +\n      +\tcat >expect.filtered <<-\\EOF &&\n     @@ t/t4202-log.sh: test_expect_success 'decorate-refs focus from default' '\n      +\t\t--simplify-by-decoration \\\n      +\t\t--decorate-refs-exclude=\"heads/octopus\" \\\n      +\t\t--decorate-refs=\"heads\" \\\n     -+\t\t--decorate-all \\\n     ++\t\t--clear-decorations \\\n      +\t\t--decorate-refs-exclude=\"tags/\" \\\n      +\t\t--decorate-refs=\"heads/octopus*\" >actual &&\n      +\ttest_cmp expect.filtered actual\n  8:  8142b32f023 !  9:  7ec2578b90a log: create log.decorateFilter=all\n     @@ Metadata\n      Author: Derrick Stolee <derrickstolee@github.com>\n      \n       ## Commit message ##\n     -    log: create log.decorateFilter=all\n     +    log: create log.initialDecorationSet=all\n      \n     -    The previous change introduced the --decorate-all option for users who\n     -    do not want their decorations limited to a narrow set of ref namespaces.\n     +    The previous change introduced the --clear-decorations option for users\n     +    who do not want their decorations limited to a narrow set of ref\n     +    namespaces.\n      \n     -    Add a config option that is equivalent to specifying --decorate-all by\n     -    default.\n     +    Add a config option that is equivalent to specifying --clear-decorations\n     +    by default.\n      \n          Signed-off-by: Derrick Stolee <derrickstolee@github.com>\n      \n     @@ Documentation/config/log.txt: log.decorate::\n       \tnames are shown. This is the same as the `--decorate` option\n       \tof the `git log`.\n       \n     -+log.decorateFilter::\n     ++log.initialDecorationSet::\n      +\tBy default, `git log` only shows decorations for certain known ref\n     -+\tnamespaces. If 'all' is specified, then show all possible ref\n     -+\tdecorations. Default value is 'default'.\n     ++\tnamespaces. If 'all' is specified, then show all refs as\n     ++\tdecorations.\n      +\n       log.excludeDecoration::\n       \tExclude the specified patterns from the log decorations. This is\n     @@ Documentation/config/log.txt: log.decorate::\n      \n       ## Documentation/git-log.txt ##\n      @@ Documentation/git-log.txt: used as decoration if they match `HEAD`, `refs/heads/`, `refs/remotes/`,\n     - --decorate-all::\n     + --clear-decorations::\n       \tWhen specified, this option clears all previous `--decorate-refs`\n       \tor `--decorate-refs-exclude` options and relaxes the default\n     --\tdecoration filter to include all possible decoration refs.\n     -+\tdecoration filter to include all possible decoration refs. This\n     -+\toption is assumed if the config value `log.decorateFilter` is set\n     -+\tto `all`.\n     +-\tdecoration filter to include all references.\n     ++\tdecoration filter to include all references. This option is\n     ++\tassumed if the config value `log.initialDecorationSet` is set to\n     ++\t`all`.\n       \n       --source::\n       \tPrint out the ref name given on the command line by which each\n     @@ builtin/log.c: static void set_default_decoration_filter(struct decoration_filte\n       \n      +\t/*\n      +\t * By default, decorate_all is disabled. Enable it if\n     -+\t * log.decorateMode=all. Don't ever disable it by config, since\n     -+\t * the command-line takes precedent.\n     ++\t * log.initialDecorationSet=all. Don't ever disable it by config,\n     ++\t * since the command-line takes precedent.\n      +\t */\n     -+\tif (!decorate_all &&\n     -+\t    !git_config_get_string(\"log.decoratefilter\", &value) &&\n     ++\tif (use_default_decoration_filter &&\n     ++\t    !git_config_get_string(\"log.initialdecorationset\", &value) &&\n      +\t    !strcmp(\"all\", value))\n     -+\t\tdecorate_all = 1;\n     ++\t\tuse_default_decoration_filter = 0;\n      +\tfree(value);\n      +\n     - \tif (decorate_all ||\n     + \tif (!use_default_decoration_filter ||\n       \t    decoration_filter->exclude_ref_pattern->nr ||\n       \t    decoration_filter->include_ref_pattern->nr ||\n      \n       ## t/t4202-log.sh ##\n     -@@ t/t4202-log.sh: test_expect_success '--decorate-all overrides defaults' '\n     +@@ t/t4202-log.sh: test_expect_success '--clear-decorations overrides defaults' '\n       \tEOF\n       \tgit log --decorate=full --pretty=\"tformat:%f%d\" \\\n     - \t\t--decorate-all >actual &&\n     + \t\t--clear-decorations >actual &&\n      +\ttest_cmp expect.all actual &&\n     -+\tgit -c log.decorateFilter=all log \\\n     ++\tgit -c log.initialDecorationSet=all log \\\n      +\t\t--decorate=full --pretty=\"tformat:%f%d\" >actual &&\n       \ttest_cmp expect.all actual\n       '\n       \n     -\n     - ## t/t9902-completion.sh ##\n     -@@ t/t9902-completion.sh: test_expect_success 'git config - variable name' '\n     - \ttest_completion \"git config log.d\" <<-\\EOF\n     - \tlog.date Z\n     - \tlog.decorate Z\n     -+\tlog.decorateFilter Z\n     - \tlog.diffMerges Z\n     - \tEOF\n     - '\n     -@@ t/t9902-completion.sh: test_expect_success 'git -c - variable name' '\n     - \ttest_completion \"git -c log.d\" <<-\\EOF\n     - \tlog.date=Z\n     - \tlog.decorate=Z\n     -+\tlog.decorateFilter=Z\n     - \tlog.diffMerges=Z\n     - \tEOF\n     - '\n     -@@ t/t9902-completion.sh: test_expect_success 'git clone --config= - variable name' '\n     - \ttest_completion \"git clone --config=log.d\" <<-\\EOF\n     - \tlog.date=Z\n     - \tlog.decorate=Z\n     -+\tlog.decorateFilter=Z\n     - \tlog.diffMerges=Z\n     - \tEOF\n     - '\n  9:  318269dfe27 = 10:  1f4d9bc4b3f maintenance: stop writing log.excludeDecoration\n 10:  8599bb55045 ! 11:  bd2ffac88ac fetch: use ref_namespaces during prefetch\n     @@ builtin/fetch.c: static void filter_prefetch_refspec(struct refspec *rs)\n       \t\t    (rs->items[i].src &&\n      -\t\t     !strncmp(rs->items[i].src, \"refs/tags/\", 10))) {\n      +\t\t     !strncmp(rs->items[i].src,\n     -+\t\t\t      ref_namespaces[NAMESPACE_TAGS].ref,\n     -+\t\t\t      strlen(ref_namespaces[NAMESPACE_TAGS].ref)))) {\n     ++\t\t\t      ref_namespace[NAMESPACE_TAGS].ref,\n     ++\t\t\t      strlen(ref_namespace[NAMESPACE_TAGS].ref)))) {\n       \t\t\tint j;\n       \n       \t\t\tfree(rs->items[i].src);\n     @@ builtin/fetch.c: static void filter_prefetch_refspec(struct refspec *rs)\n       \n       \t\told_dst = rs->items[i].dst;\n      -\t\tstrbuf_addstr(&new_dst, \"refs/prefetch/\");\n     -+\t\tstrbuf_addstr(&new_dst, ref_namespaces[NAMESPACE_PREFETCH].ref);\n     ++\t\tstrbuf_addstr(&new_dst, ref_namespace[NAMESPACE_PREFETCH].ref);\n       \n       \t\t/*\n       \t\t * If old_dst starts with \"refs/\", then place\n\n-- \ngitgitgadget\n"},{"id":"460722","messageId":"1522889352ff5cb823132052d9ab62b5f2d7b8b0.1659722324.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v3.git.1659722323.gitgitgadget@gmail.com","subject":"[PATCH v3 01/11] refs: allow \"HEAD\" as decoration filter","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-08-05T17:58:33Z","receivedAt":"2022-08-05T17:59:02Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe normalize_glob_ref() method was introduced in 65516f586b693 (log:\nadd option to choose which refs to decorate, 2017-11-21) to help with\ndecoration filters such as --decorate-refs=<filter> and\n--decorate-refs-exclude=<filter>. The method has not been used anywhere\nelse.\n\nAt the moment, it is impossible to specify HEAD as a decoration filter\nsince normalize_glob_ref() prepends \"refs/\" to the filter if it isn't\nalready there.\n\nAllow adding HEAD as a decoration filter by allowing the exact string\n\"HEAD\" to not be prepended with \"refs/\". Add a test in t4202-log.sh that\nwould previously fail since the HEAD decoration would exist in the\noutput.\n\nIt is sufficient to only cover \"HEAD\" here and not include other special\nrefs like REBASE_HEAD. This is because HEAD is the only ref outside of\nrefs/* that is added to the list of decorations. However, we may want to\nspecial-case these other refs in normalize_glob_ref() in the future.\nLeave a NEEDSWORK comment for now.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n refs.c         | 11 ++++++++---\n t/t4202-log.sh |  6 ++++++\n 2 files changed, 14 insertions(+), 3 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 90bcb271687..3fdfa86a5b9 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -455,11 +455,16 @@ void normalize_glob_ref(struct string_list_item *item, const char *prefix,\n \tif (*pattern == '/')\n \t\tBUG(\"pattern must not start with '/'\");\n \n-\tif (prefix) {\n+\tif (prefix)\n \t\tstrbuf_addstr(&normalized_pattern, prefix);\n-\t}\n-\telse if (!starts_with(pattern, \"refs/\"))\n+\telse if (!starts_with(pattern, \"refs/\") &&\n+\t\t   strcmp(pattern, \"HEAD\"))\n \t\tstrbuf_addstr(&normalized_pattern, \"refs/\");\n+\t/*\n+\t * NEEDSWORK: Special case other symrefs such as REBASE_HEAD,\n+\t * MERGE_HEAD, etc.\n+\t */\n+\n \tstrbuf_addstr(&normalized_pattern, pattern);\n \tstrbuf_strip_suffix(&normalized_pattern, \"/\");\n \ndiff --git a/t/t4202-log.sh b/t/t4202-log.sh\nindex 6e663525582..6b7d8e269f7 100755\n--- a/t/t4202-log.sh\n+++ b/t/t4202-log.sh\n@@ -1025,6 +1025,12 @@ test_expect_success 'decorate-refs and simplify-by-decoration without output' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'decorate-refs-exclude HEAD' '\n+\tgit log --decorate=full --oneline \\\n+\t\t--decorate-refs-exclude=\"HEAD\" >actual &&\n+\t! grep HEAD actual\n+'\n+\n test_expect_success 'log.decorate config parsing' '\n \tgit log --oneline --decorate=full >expect.full &&\n \tgit log --oneline --decorate=short >expect.short &&\n-- \ngitgitgadget\n\n"},{"id":"460724","messageId":"0633f8403dbb425bd942458cf7ee5423c29a403f.1659722324.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v3.git.1659722323.gitgitgadget@gmail.com","subject":"[PATCH v3 02/11] t4207: modernize test","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-08-05T17:58:34Z","receivedAt":"2022-08-05T17:59:03Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nBefore adding new tests to t4207-log-decoration-colors.sh, update the\nexisting test to use modern test conventions. This includes:\n\n1. Use lowercase in test names.\n\n2. Keep all test setup inside the test_expect_success blocks. We need\n   to be careful about left whitespace in the broken lines of the input\n   file.\n\n3. Do not use 'git' commands on the left side of a pipe.\n\n4. Create a cmp_filtered_decorations helper to perform the 'log', 'sed',\n   and test_decode_color manipulations. Move the '--all' option to be an\n   argument so we can change that value in future tests.\n\n5. Modify the 'sed' command to use a simpler form that is more\n   portable.\n\nThe next change will introduce new tests usinge these new conventions.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n t/t4207-log-decoration-colors.sh | 37 +++++++++++++++++---------------\n 1 file changed, 20 insertions(+), 17 deletions(-)\n\ndiff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh\nindex 36ac6aff1e4..324412d0839 100755\n--- a/t/t4207-log-decoration-colors.sh\n+++ b/t/t4207-log-decoration-colors.sh\n@@ -3,7 +3,7 @@\n # Copyright (c) 2010 Nazri Ramliy\n #\n \n-test_description='Test for \"git log --decorate\" colors'\n+test_description='test \"git log --decorate\" colors'\n \n GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main\n export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME\n@@ -42,25 +42,28 @@ test_expect_success setup '\n \tgit stash save Changes to A.t\n '\n \n-cat >expected <<EOF\n-${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD ->\\\n- ${c_reset}${c_branch}main${c_reset}${c_commit},\\\n- ${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit},\\\n- ${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B\n-${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A1${c_reset}${c_commit},\\\n- ${c_reset}${c_remoteBranch}other/main${c_reset}${c_commit})${c_reset} A1\n-${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_stash}refs/stash${c_reset}${c_commit})${c_reset}\\\n- On main: Changes to A.t\n-${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A\n-EOF\n+cmp_filtered_decorations () {\n+\tsed \"s/$OID_REGEX/COMMIT_ID/\" actual | test_decode_color >filtered &&\n+\ttest_cmp expect filtered\n+}\n \n # We want log to show all, but the second parent to refs/stash is irrelevant\n # to this test since it does not contain any decoration, hence --first-parent\n-test_expect_success 'Commit Decorations Colored Correctly' '\n-\tgit log --first-parent --abbrev=10 --all --decorate --oneline --color=always |\n-\tsed \"s/[0-9a-f]\\{10,10\\}/COMMIT_ID/\" |\n-\ttest_decode_color >out &&\n-\ttest_cmp expected out\n+test_expect_success 'commit decorations colored correctly' '\n+\tcat >expect <<-EOF &&\n+\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \\\n+${c_reset}${c_branch}main${c_reset}${c_commit}, \\\n+${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit}, \\\n+${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B\n+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A1${c_reset}${c_commit}, \\\n+${c_reset}${c_remoteBranch}other/main${c_reset}${c_commit})${c_reset} A1\n+\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_stash}refs/stash${c_reset}${c_commit})${c_reset} \\\n+On main: Changes to A.t\n+\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A\n+\tEOF\n+\n+\tgit log --first-parent --no-abbrev --decorate --oneline --color=always --all >actual &&\n+\tcmp_filtered_decorations\n '\n \n test_done\n-- \ngitgitgadget\n\n"},{"id":"460725","messageId":"fafe20c1e82d604acf40d9a2152904a8cd902f15.1659722324.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v3.git.1659722323.gitgitgadget@gmail.com","subject":"[PATCH v3 03/11] t4207: test coloring of grafted decorations","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-08-05T17:58:35Z","receivedAt":"2022-08-05T17:59:07Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe color.decorate.<slot> config option added the 'grafted' slot in\n09c4ba410b0f (log-tree: allow to customize 'grafted' color, 2018-05-26)\nbut included no tests for this behavior. When modifying some logic\naround decorations, this ref namespace was ignored and could have been\nlost as a default namespace for 'git log' decorations by default.\n\nAdd two tests to t4207 that check that the replaced objects are\ncorrectly decorated. Use \"black\" as the color since it is distinct from\nthe other colors already in the test. The first test uses regular\nreplace-objects while the second creates a commit graft.\n\nBe sure to test both modes with GIT_REPLACE_REF_BASE unset and set to an\nalternative base.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n t/t4207-log-decoration-colors.sh | 53 ++++++++++++++++++++++++++++++++\n 1 file changed, 53 insertions(+)\n\ndiff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh\nindex 324412d0839..ded33a82e2c 100755\n--- a/t/t4207-log-decoration-colors.sh\n+++ b/t/t4207-log-decoration-colors.sh\n@@ -17,6 +17,7 @@ test_expect_success setup '\n \tgit config color.decorate.remoteBranch red &&\n \tgit config color.decorate.tag \"reverse bold yellow\" &&\n \tgit config color.decorate.stash magenta &&\n+\tgit config color.decorate.grafted black &&\n \tgit config color.decorate.HEAD cyan &&\n \n \tc_reset=\"<RESET>\" &&\n@@ -27,6 +28,7 @@ test_expect_success setup '\n \tc_tag=\"<BOLD;REVERSE;YELLOW>\" &&\n \tc_stash=\"<MAGENTA>\" &&\n \tc_HEAD=\"<CYAN>\" &&\n+\tc_grafted=\"<BLACK>\" &&\n \n \ttest_commit A &&\n \tgit clone . other &&\n@@ -66,4 +68,55 @@ On main: Changes to A.t\n \tcmp_filtered_decorations\n '\n \n+test_expect_success 'test coloring with replace-objects' '\n+\ttest_when_finished rm -rf .git/refs/replace* &&\n+\ttest_commit C &&\n+\ttest_commit D &&\n+\n+\tgit replace HEAD~1 HEAD~2 &&\n+\n+\tcat >expect <<-EOF &&\n+\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \\\n+${c_reset}${c_branch}main${c_reset}${c_commit}, \\\n+${c_reset}${c_tag}tag: D${c_reset}${c_commit})${c_reset} D\n+\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: C${c_reset}${c_commit}, \\\n+${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} B\n+\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A\n+EOF\n+\n+\tgit log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual &&\n+\tcmp_filtered_decorations &&\n+\tgit replace -d HEAD~1 &&\n+\n+\tGIT_REPLACE_REF_BASE=refs/replace2/ git replace HEAD~1 HEAD~2 &&\n+\tGIT_REPLACE_REF_BASE=refs/replace2/ git log --first-parent \\\n+\t\t--no-abbrev --decorate --oneline --color=always HEAD >actual &&\n+\tcmp_filtered_decorations\n+'\n+\n+test_expect_success 'test coloring with grafted commit' '\n+\ttest_when_finished rm -rf .git/refs/replace* &&\n+\n+\tgit replace --graft HEAD HEAD~2 &&\n+\n+\tcat >expect <<-EOF &&\n+\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \\\n+${c_reset}${c_branch}main${c_reset}${c_commit}, \\\n+${c_reset}${c_tag}tag: D${c_reset}${c_commit}, \\\n+${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} D\n+\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit}, \\\n+${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B\n+\t${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A\n+\tEOF\n+\n+\tgit log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual &&\n+\tcmp_filtered_decorations &&\n+\tgit replace -d HEAD &&\n+\n+\tGIT_REPLACE_REF_BASE=refs/replace2/ git replace --graft HEAD HEAD~2 &&\n+\tGIT_REPLACE_REF_BASE=refs/replace2/ git log --first-parent \\\n+\t\t--no-abbrev --decorate --oneline --color=always HEAD >actual &&\n+\tcmp_filtered_decorations\n+'\n+\n test_done\n-- \ngitgitgadget\n\n"},{"id":"460726","messageId":"475ebca6310768adb11fc5b64fb5499f20b3cd5f.1659722324.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v3.git.1659722323.gitgitgadget@gmail.com","subject":"[PATCH v3 04/11] refs: add array of ref namespaces","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-08-05T17:58:36Z","receivedAt":"2022-08-05T17:59:08Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nGit interprets different meanings to different refs based on their\nnames. Some meanings are cosmetic, like how refs in  'refs/remotes/*'\nare colored differently from refs in 'refs/heads/*'. Others are more\ncritical, such as how replace refs are interpreted.\n\nBefore making behavior changes based on ref namespaces, collect all\nknown ref namespaces into a array of ref_namespace_info structs. This\narray is indexed by the new ref_namespace enum for quick access.\n\nAs of this change, this array is purely documentation. Future changes\nwill add dependencies on this array.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n environment.c |  2 ++\n notes.c       |  1 +\n refs.c        | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++\n refs.h        | 46 ++++++++++++++++++++++++++++\n 4 files changed, 132 insertions(+)\n\ndiff --git a/environment.c b/environment.c\nindex b3296ce7d15..9eb22f975c7 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -185,6 +185,8 @@ void setup_git_env(const char *git_dir)\n \tfree(git_replace_ref_base);\n \tgit_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base\n \t\t\t\t\t\t\t  : \"refs/replace/\");\n+\tupdate_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);\n+\n \tfree(git_namespace);\n \tgit_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));\n \tshallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);\ndiff --git a/notes.c b/notes.c\nindex 7452e71cc8d..7bade6d8f69 100644\n--- a/notes.c\n+++ b/notes.c\n@@ -1005,6 +1005,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,\n \n \tif (!notes_ref)\n \t\tnotes_ref = default_notes_ref();\n+\tupdate_ref_namespace(NAMESPACE_NOTES, xstrdup(notes_ref));\n \n \tif (!combine_notes)\n \t\tcombine_notes = combine_notes_concatenate;\ndiff --git a/refs.c b/refs.c\nindex 3fdfa86a5b9..65decf25d09 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -20,6 +20,7 @@\n #include \"repository.h\"\n #include \"sigchain.h\"\n #include \"date.h\"\n+#include \"commit.h\"\n \n /*\n  * List of all available backends\n@@ -56,6 +57,88 @@ static unsigned char refname_disposition[256] = {\n \t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4\n };\n \n+struct ref_namespace_info ref_namespace[] = {\n+\t[NAMESPACE_HEAD] = {\n+\t\t.ref = \"HEAD\",\n+\t\t.decoration = DECORATION_REF_HEAD,\n+\t\t.exact = 1,\n+\t},\n+\t[NAMESPACE_BRANCHES] = {\n+\t\t.ref = \"refs/heads/\",\n+\t\t.decoration = DECORATION_REF_LOCAL,\n+\t},\n+\t[NAMESPACE_TAGS] = {\n+\t\t.ref = \"refs/tags/\",\n+\t\t.decoration = DECORATION_REF_TAG,\n+\t},\n+\t[NAMESPACE_REMOTE_REFS] = {\n+\t\t/*\n+\t\t * The default refspec for new remotes copies refs from\n+\t\t * refs/heads/ on the remote into refs/remotes/<remote>/.\n+\t\t * As such, \"refs/remotes/\" has special handling.\n+\t\t */\n+\t\t.ref = \"refs/remotes/\",\n+\t\t.decoration = DECORATION_REF_REMOTE,\n+\t},\n+\t[NAMESPACE_STASH] = {\n+\t\t/*\n+\t\t * The single ref \"refs/stash\" stores the latest stash.\n+\t\t * Older stashes can be found in the reflog.\n+\t\t */\n+\t\t.ref = \"refs/stash\",\n+\t\t.exact = 1,\n+\t\t.decoration = DECORATION_REF_STASH,\n+\t},\n+\t[NAMESPACE_REPLACE] = {\n+\t\t/*\n+\t\t * This namespace allows Git to act as if one object ID\n+\t\t * points to the content of another. Unlike the other\n+\t\t * ref namespaces, this one can be changed by the\n+\t\t * GIT_REPLACE_REF_BASE environment variable. This\n+\t\t * .namespace value will be overwritten in setup_git_env().\n+\t\t */\n+\t\t.ref = \"refs/replace/\",\n+\t\t.decoration = DECORATION_GRAFTED,\n+\t},\n+\t[NAMESPACE_NOTES] = {\n+\t\t/*\n+\t\t * The refs/notes/commit ref points to the tip of a\n+\t\t * parallel commit history that adds metadata to commits\n+\t\t * in the normal history. This ref can be overwritten\n+\t\t * by the core.notesRef config variable or the\n+\t\t * GIT_NOTES_REFS environment variable.\n+\t\t */\n+\t\t.ref = \"refs/notes/commit\",\n+\t\t.exact = 1,\n+\t},\n+\t[NAMESPACE_PREFETCH] = {\n+\t\t/*\n+\t\t * Prefetch refs are written by the background 'fetch'\n+\t\t * maintenance task. It allows faster foreground fetches\n+\t\t * by advertising these previously-downloaded tips without\n+\t\t * updating refs/remotes/ without user intervention.\n+\t\t */\n+\t\t.ref = \"refs/prefetch/\",\n+\t},\n+\t[NAMESPACE_REWRITTEN] = {\n+\t\t/*\n+\t\t * Rewritten refs are used by the 'label' command in the\n+\t\t * sequencer. These are particularly useful during an\n+\t\t * interactive rebase that uses the 'merge' command.\n+\t\t */\n+\t\t.ref = \"refs/rewritten/\",\n+\t},\n+};\n+\n+void update_ref_namespace(enum ref_namespace namespace, char *ref)\n+{\n+\tstruct ref_namespace_info *info = &ref_namespace[namespace];\n+\tif (info->ref_updated)\n+\t\tfree(info->ref);\n+\tinfo->ref = ref;\n+\tinfo->ref_updated = 1;\n+}\n+\n /*\n  * Try to read one refname component from the front of refname.\n  * Return the length of the component found, or -1 if the component is\ndiff --git a/refs.h b/refs.h\nindex 47cb9edbaa8..d6575b8c2bd 100644\n--- a/refs.h\n+++ b/refs.h\n@@ -2,6 +2,7 @@\n #define REFS_H\n \n #include \"cache.h\"\n+#include \"commit.h\"\n \n struct object_id;\n struct ref_store;\n@@ -930,4 +931,49 @@ struct ref_store *get_main_ref_store(struct repository *r);\n struct ref_store *get_submodule_ref_store(const char *submodule);\n struct ref_store *get_worktree_ref_store(const struct worktree *wt);\n \n+/*\n+ * Some of the names specified by refs have special meaning to Git.\n+ * Organize these namespaces in a comon 'ref_namespace' array for\n+ * reference from multiple places in the codebase.\n+ */\n+\n+struct ref_namespace_info {\n+\tchar *ref;\n+\tenum decoration_type decoration;\n+\n+\t/*\n+\t * If 'exact' is true, then we must match the 'ref' exactly.\n+\t * Otherwise, use a prefix match.\n+\t *\n+\t * 'ref_updated' is for internal use. It represents whether the\n+\t * 'ref' value was replaced from its original literal version.\n+\t */\n+\tunsigned exact:1,\n+\t\t ref_updated:1;\n+};\n+\n+enum ref_namespace {\n+\tNAMESPACE_HEAD,\n+\tNAMESPACE_BRANCHES,\n+\tNAMESPACE_TAGS,\n+\tNAMESPACE_REMOTE_REFS,\n+\tNAMESPACE_STASH,\n+\tNAMESPACE_REPLACE,\n+\tNAMESPACE_NOTES,\n+\tNAMESPACE_PREFETCH,\n+\tNAMESPACE_REWRITTEN,\n+\n+\t/* Must be last */\n+\tNAMESPACE__COUNT\n+};\n+\n+/* See refs.c for the contents of this array. */\n+extern struct ref_namespace_info ref_namespace[NAMESPACE__COUNT];\n+\n+/*\n+ * Some ref namespaces can be modified by config values or environment\n+ * variables. Modify a namespace as specified by its ref_namespace key.\n+ */\n+void update_ref_namespace(enum ref_namespace namespace, char *ref);\n+\n #endif /* REFS_H */\n-- \ngitgitgadget\n\n"},{"id":"460727","messageId":"45e3ce94d0dac9ff935a01d936c2c9638fe9d364.1659722324.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v3.git.1659722323.gitgitgadget@gmail.com","subject":"[PATCH v3 05/11] refs: use ref_namespaces for replace refs base","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-08-05T17:58:37Z","receivedAt":"2022-08-05T17:59:22Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe git_replace_ref_base global is used to store the value of the\nGIT_REPLACE_REF_BASE environment variable or the default of\n\"refs/replace/\". This is initialized within setup_git_env().\n\nThe ref_namespaces array is a new centralized location for information\nsuch as the ref namespace used for replace refs. Instead of having this\nnamespace stored in two places, use the ref_namespaces array instead.\n\nFor simplicity, create a local git_replace_ref_base variable wherever\nthe global was previously used.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n builtin/replace.c | 3 +++\n cache.h           | 1 -\n environment.c     | 3 +--\n log-tree.c        | 1 +\n refs.c            | 1 +\n 5 files changed, 6 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/replace.c b/builtin/replace.c\nindex 583702a0980..a29e911d309 100644\n--- a/builtin/replace.c\n+++ b/builtin/replace.c\n@@ -106,6 +106,7 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn)\n \tsize_t base_len;\n \tint had_error = 0;\n \tstruct object_id oid;\n+\tconst char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;\n \n \tstrbuf_addstr(&ref, git_replace_ref_base);\n \tbase_len = ref.len;\n@@ -147,6 +148,8 @@ static int check_ref_valid(struct object_id *object,\n \t\t\t    struct strbuf *ref,\n \t\t\t    int force)\n {\n+\tconst char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;\n+\n \tstrbuf_reset(ref);\n \tstrbuf_addf(ref, \"%s%s\", git_replace_ref_base, oid_to_hex(object));\n \tif (check_refname_format(ref->buf, 0))\ndiff --git a/cache.h b/cache.h\nindex ac5ab4ef9d3..631a4f388d6 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1008,7 +1008,6 @@ void reset_shared_repository(void);\n  * commands that do not want replace references to be active.\n  */\n extern int read_replace_refs;\n-extern char *git_replace_ref_base;\n \n /*\n  * These values are used to help identify parts of a repository to fsync.\ndiff --git a/environment.c b/environment.c\nindex 9eb22f975c7..b2004437dce 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -56,7 +56,6 @@ const char *askpass_program;\n const char *excludes_file;\n enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;\n int read_replace_refs = 1;\n-char *git_replace_ref_base;\n enum eol core_eol = EOL_UNSET;\n int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;\n char *check_roundtrip_encoding = \"SHIFT-JIS\";\n@@ -162,6 +161,7 @@ const char *getenv_safe(struct strvec *argv, const char *name)\n \n void setup_git_env(const char *git_dir)\n {\n+\tchar *git_replace_ref_base;\n \tconst char *shallow_file;\n \tconst char *replace_ref_base;\n \tstruct set_gitdir_args args = { NULL };\n@@ -182,7 +182,6 @@ void setup_git_env(const char *git_dir)\n \tif (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))\n \t\tread_replace_refs = 0;\n \treplace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);\n-\tfree(git_replace_ref_base);\n \tgit_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base\n \t\t\t\t\t\t\t  : \"refs/replace/\");\n \tupdate_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);\ndiff --git a/log-tree.c b/log-tree.c\nindex d0ac0a6327a..1b2c76c5bb9 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -141,6 +141,7 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,\n \tenum object_type objtype;\n \tenum decoration_type deco_type = DECORATION_NONE;\n \tstruct decoration_filter *filter = (struct decoration_filter *)cb_data;\n+\tconst char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;\n \n \tif (filter && !ref_filter_match(refname, filter))\n \t\treturn 0;\ndiff --git a/refs.c b/refs.c\nindex 65decf25d09..92819732ab7 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1612,6 +1612,7 @@ int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,\n \n int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data)\n {\n+\tconst char *git_replace_ref_base = ref_namespace[NAMESPACE_REPLACE].ref;\n \treturn do_for_each_repo_ref(r, git_replace_ref_base, fn,\n \t\t\t\t    strlen(git_replace_ref_base),\n \t\t\t\t    DO_FOR_EACH_INCLUDE_BROKEN, cb_data);\n-- \ngitgitgadget\n\n"},{"id":"460728","messageId":"063e5bac2ce0bbe08ce71ba5012c4f7c447e0d4e.1659722324.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v3.git.1659722323.gitgitgadget@gmail.com","subject":"[PATCH v3 06/11] log-tree: use ref_namespaces instead of if/else-if","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-08-05T17:58:38Z","receivedAt":"2022-08-05T17:59:27Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe add_ref_decoration() method uses an if/else-if chain to determine if\na ref matches a known ref namespace that has a special decoration\ncategory. That decoration type is later used to assign a color when\nwriting to stdout.\n\nThe newly-added ref_namespaces array contains all namespaces, along\nwith information about their decoration type. Check this array instead\nof this if/else-if chain. This reduces our dependency on string literals\nbeing embedded in the decoration logic.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n log-tree.c | 26 ++++++++++++++++----------\n 1 file changed, 16 insertions(+), 10 deletions(-)\n\ndiff --git a/log-tree.c b/log-tree.c\nindex 1b2c76c5bb9..bb6cbceee63 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -137,6 +137,7 @@ static int ref_filter_match(const char *refname,\n static int add_ref_decoration(const char *refname, const struct object_id *oid,\n \t\t\t      int flags, void *cb_data)\n {\n+\tint i;\n \tstruct object *obj;\n \tenum object_type objtype;\n \tenum decoration_type deco_type = DECORATION_NONE;\n@@ -166,16 +167,21 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,\n \t\treturn 0;\n \tobj = lookup_object_by_type(the_repository, oid, objtype);\n \n-\tif (starts_with(refname, \"refs/heads/\"))\n-\t\tdeco_type = DECORATION_REF_LOCAL;\n-\telse if (starts_with(refname, \"refs/remotes/\"))\n-\t\tdeco_type = DECORATION_REF_REMOTE;\n-\telse if (starts_with(refname, \"refs/tags/\"))\n-\t\tdeco_type = DECORATION_REF_TAG;\n-\telse if (!strcmp(refname, \"refs/stash\"))\n-\t\tdeco_type = DECORATION_REF_STASH;\n-\telse if (!strcmp(refname, \"HEAD\"))\n-\t\tdeco_type = DECORATION_REF_HEAD;\n+\tfor (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {\n+\t\tstruct ref_namespace_info *info = &ref_namespace[i];\n+\n+\t\tif (!info->decoration)\n+\t\t\tcontinue;\n+\t\tif (info->exact) {\n+\t\t\tif (!strcmp(refname, info->ref)) {\n+\t\t\t\tdeco_type = info->decoration;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t} else if (starts_with(refname, info->ref)) {\n+\t\t\tdeco_type = info->decoration;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n \n \tadd_name_decoration(deco_type, refname, obj);\n \twhile (obj->type == OBJ_TAG) {\n-- \ngitgitgadget\n\n"},{"id":"460729","messageId":"c249bface2a6dcd0355620f92579b42a6fa4ea58.1659722324.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v3.git.1659722323.gitgitgadget@gmail.com","subject":"[PATCH v3 07/11] log: add default decoration filter","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-08-05T17:58:39Z","receivedAt":"2022-08-05T17:59:29Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nWhen a user runs 'git log', they expect a certain set of helpful\ndecorations. This includes:\n\n* The HEAD ref\n* Branches (refs/heads/)\n* Stashes (refs/stash)\n* Tags (refs/tags/)\n* Remote branches (refs/remotes/)\n* Replace refs (refs/replace/ or $GIT_REPLACE_REF_BASE)\n\nEach of these namespaces was selected due to existing test cases that\nverify these namespaces appear in the decorations. In particular,\nstashes and replace refs can have custom colors from the\ncolor.decorate.<slot> config option.\n\nWhile one test checks for a decoration from notes, it only applies to\nthe tip of refs/notes/commit (or its configured ref name). Notes form\ntheir own kind of decoration instead. Modify the expected output for the\ntests in t4013 that expect this note decoration.  There are several\ntests throughout the codebase that verify that --decorate-refs,\n--decorate-refs-exclude, and log.excludeDecoration work as designed and\nthe tests continue to pass without intervention.\n\nHowever, there are other refs that are less helpful to show as\ndecoration:\n\n* Prefetch refs (refs/prefetch/)\n* Rebase refs (refs/rebase-merge/ and refs/rebase-apply/)\n* Bundle refs (refs/bundle/) [!]\n\n[!] The bundle refs are part of a parallel series that bootstraps a repo\n    from a bundle file, storing the bundle's refs into the repo's\n    refs/bundle/ namespace.\n\nIn the case of prefetch refs, 96eaffebbf3d0 (maintenance: set\nlog.excludeDecoration durin prefetch, 2021-01-19) added logic to add\nrefs/prefetch/ to the log.excludeDecoration config option. Additional\nfeedback pointed out that having such a side-effect can be confusing and\nperhaps not helpful to users. Instead, we should hide these ref\nnamespaces that are being used by Git for internal reasons but are not\nhelpful for the users to see.\n\nThe way to provide a seamless user experience without setting the config\nis to modify the default decoration filters to match our expectation of\nwhat refs the user actually wants to see.\n\nIn builtin/log.c, after parsing the --decorate-refs and\n--decorate-refs-exclude options from the command-line, call\nset_default_decoration_filter(). This method populates the exclusions\nfrom log.excludeDecoration, then checks if the list of pattern\nmodifications are empty. If none are specified, then the default set is\nrestricted to the set of inclusions mentioned earlier (HEAD, branches,\netc.).  A previous change introduced the ref_namespaces array, which\nincludes all of these currently-used namespaces. The 'decoration' value\nis non-zero when that namespace is associated with a special coloring\nand fits into the list of \"expected\" decorations as described above,\nwhich makes the implementation of this filter very simple.\n\nNote that the logic in ref_filter_match() in log-tree.c follows this\nmatching pattern:\n\n 1. If there are exclusion patterns and the ref matches one, then ignore\n    the decoration.\n\n 2. If there are inclusion patterns and the ref matches one, then\n    definitely include the decoration.\n\n 3. If there are config-based exclusions from log.excludeDecoration and\n    the ref matches one, then ignore the decoration.\n\nWith this logic in mind, we need to ensure that we do not populate our\nnew defaults if any of these filters are manually set. Specifically, if\na user runs\n\n\tgit -c log.excludeDecoration=HEAD log\n\nthen we expect the HEAD decoration to not appear. If we left the default\ninclusions in the set, then HEAD would match that inclusion before\nreaching the config-based exclusions.\n\nA potential alternative would be to check the list of default inclusions\nat the end, after the config-based exclusions. This would still create a\nbehavior change for some uses of --decorate-refs-exclude=<X>, and could\nbe overwritten somewhat with --decorate-refs=refs/ and\n--decorate-refs=HEAD. However, it no longer becomes possible to include\nrefs outside of the defaults while also excluding some using\nlog.excludeDecoration.\n\nAnother alternative would be to exclude the known namespaces that are\nnot intended to be shown. This would reduce the visible effect of the\nchange for expert users who use their own custom ref namespaces. The\nimplementation change would be very simple to swap due to our use of\nref_namespaces:\n\n\tint i;\n\tstruct string_list *exclude = decoration_filter->exclude_ref_pattern;\n\n\t/*\n\t * No command-line or config options were given, so\n\t * populate with sensible defaults.\n\t */\n\tfor (i = 0; i < NAMESPACE__COUNT; i++) {\n\t\tif (ref_namespaces[i].decoration)\n\t\t\tcontinue;\n\n\t\tstring_list_append(exclude, ref_namespaces[i].ref);\n\t}\n\nThe main downside of this approach is that we expect to add new hidden\nnamespaces in the future, and that means that Git versions will be less\nstable in how they behave as those namespaces are added.\n\nIt is critical that we provide ways for expert users to disable this\nbehavior change via command-line options and config keys. These changes\nwill be implemented in a future change.\n\nAdd a test that checks that the defaults are not added when\n--decorate-refs is specified. We verify this by showing that HEAD is not\nincluded as it normally would.  Also add a test that shows that the\ndefault filter avoids the unwanted decorations from refs/prefetch,\nrefs/rebase-merge,\nand refs/bundle.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n Documentation/git-log.txt              |  7 ++--\n builtin/log.c                          | 50 +++++++++++++++++++-------\n t/t4013/diff.log_--decorate=full_--all |  2 +-\n t/t4013/diff.log_--decorate_--all      |  2 +-\n t/t4202-log.sh                         | 20 +++++++++++\n 5 files changed, 64 insertions(+), 17 deletions(-)\n\ndiff --git a/Documentation/git-log.txt b/Documentation/git-log.txt\nindex 20e87cecf49..b2ac89dfafc 100644\n--- a/Documentation/git-log.txt\n+++ b/Documentation/git-log.txt\n@@ -45,13 +45,16 @@ OPTIONS\n \n --decorate-refs=<pattern>::\n --decorate-refs-exclude=<pattern>::\n-\tIf no `--decorate-refs` is given, pretend as if all refs were\n-\tincluded.  For each candidate, do not use it for decoration if it\n+\tFor each candidate reference, do not use it for decoration if it\n \tmatches any patterns given to `--decorate-refs-exclude` or if it\n \tdoesn't match any of the patterns given to `--decorate-refs`. The\n \t`log.excludeDecoration` config option allows excluding refs from\n \tthe decorations, but an explicit `--decorate-refs` pattern will\n \toverride a match in `log.excludeDecoration`.\n++\n+If none of these options or config settings are given, then references are\n+used as decoration if they match `HEAD`, `refs/heads/`, `refs/remotes/`,\n+`refs/stash/`, or `refs/tags/`.\n \n --source::\n \tPrint out the ref name given on the command line by which each\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 88a5e98875a..6683e5ff134 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -162,6 +162,37 @@ static void cmd_log_init_defaults(struct rev_info *rev)\n \t\tparse_date_format(default_date_mode, &rev->date_mode);\n }\n \n+static void set_default_decoration_filter(struct decoration_filter *decoration_filter)\n+{\n+\tint i;\n+\tstruct string_list *include = decoration_filter->include_ref_pattern;\n+\tconst struct string_list *config_exclude =\n+\t\t\tgit_config_get_value_multi(\"log.excludeDecoration\");\n+\n+\tif (config_exclude) {\n+\t\tstruct string_list_item *item;\n+\t\tfor_each_string_list_item(item, config_exclude)\n+\t\t\tstring_list_append(decoration_filter->exclude_ref_config_pattern,\n+\t\t\t\t\t   item->string);\n+\t}\n+\n+\tif (decoration_filter->exclude_ref_pattern->nr ||\n+\t    decoration_filter->include_ref_pattern->nr ||\n+\t    decoration_filter->exclude_ref_config_pattern->nr)\n+\t\treturn;\n+\n+\t/*\n+\t * No command-line or config options were given, so\n+\t * populate with sensible defaults.\n+\t */\n+\tfor (i = 0; i < ARRAY_SIZE(ref_namespace); i++) {\n+\t\tif (!ref_namespace[i].decoration)\n+\t\t\tcontinue;\n+\n+\t\tstring_list_append(include, ref_namespace[i].ref);\n+\t}\n+}\n+\n static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\t\t struct rev_info *rev, struct setup_revision_opt *opt)\n {\n@@ -171,9 +202,11 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \tstatic struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n \tstatic struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;\n \tstatic struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n-\tstruct decoration_filter decoration_filter = {&decorate_refs_include,\n-\t\t\t\t\t\t      &decorate_refs_exclude,\n-\t\t\t\t\t\t      &decorate_refs_exclude_config};\n+\tstruct decoration_filter decoration_filter = {\n+\t\t.exclude_ref_pattern = &decorate_refs_exclude,\n+\t\t.include_ref_pattern = &decorate_refs_include,\n+\t\t.exclude_ref_config_pattern = &decorate_refs_exclude_config,\n+\t};\n \tstatic struct revision_sources revision_sources;\n \n \tconst struct option builtin_log_options[] = {\n@@ -265,16 +298,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t}\n \n \tif (decoration_style || rev->simplify_by_decoration) {\n-\t\tconst struct string_list *config_exclude =\n-\t\t\trepo_config_get_value_multi(the_repository,\n-\t\t\t\t\t\t    \"log.excludeDecoration\");\n-\n-\t\tif (config_exclude) {\n-\t\t\tstruct string_list_item *item;\n-\t\t\tfor_each_string_list_item(item, config_exclude)\n-\t\t\t\tstring_list_append(&decorate_refs_exclude_config,\n-\t\t\t\t\t\t   item->string);\n-\t\t}\n+\t\tset_default_decoration_filter(&decoration_filter);\n \n \t\tif (decoration_style)\n \t\t\trev->show_decorations = 1;\ndiff --git a/t/t4013/diff.log_--decorate=full_--all b/t/t4013/diff.log_--decorate=full_--all\nindex 3f9b872eceb..6b0b334a5d6 100644\n--- a/t/t4013/diff.log_--decorate=full_--all\n+++ b/t/t4013/diff.log_--decorate=full_--all\n@@ -20,7 +20,7 @@ Date:   Mon Jun 26 00:06:00 2006 +0000\n \n     Rearranged lines in dir/sub\n \n-commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n+commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0\n Author: A U Thor <author@example.com>\n Date:   Mon Jun 26 00:06:00 2006 +0000\n \ndiff --git a/t/t4013/diff.log_--decorate_--all b/t/t4013/diff.log_--decorate_--all\nindex f5e20e1e14a..c7df1f58141 100644\n--- a/t/t4013/diff.log_--decorate_--all\n+++ b/t/t4013/diff.log_--decorate_--all\n@@ -20,7 +20,7 @@ Date:   Mon Jun 26 00:06:00 2006 +0000\n \n     Rearranged lines in dir/sub\n \n-commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n+commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0\n Author: A U Thor <author@example.com>\n Date:   Mon Jun 26 00:06:00 2006 +0000\n \ndiff --git a/t/t4202-log.sh b/t/t4202-log.sh\nindex 6b7d8e269f7..4c3ce863074 100755\n--- a/t/t4202-log.sh\n+++ b/t/t4202-log.sh\n@@ -1031,6 +1031,12 @@ test_expect_success 'decorate-refs-exclude HEAD' '\n \t! grep HEAD actual\n '\n \n+test_expect_success 'decorate-refs focus from default' '\n+\tgit log --decorate=full --oneline \\\n+\t\t--decorate-refs=\"refs/heads\" >actual &&\n+\t! grep HEAD actual\n+'\n+\n test_expect_success 'log.decorate config parsing' '\n \tgit log --oneline --decorate=full >expect.full &&\n \tgit log --oneline --decorate=short >expect.short &&\n@@ -2198,6 +2204,20 @@ test_expect_success 'log --decorate includes all levels of tag annotated tags' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'log --decorate does not include things outside filter' '\n+\treflist=\"refs/prefetch refs/rebase-merge refs/bundle\" &&\n+\n+\tfor ref in $reflist\n+\tdo\n+\t\tgit update-ref $ref/fake HEAD || return 1\n+\tdone &&\n+\n+\tgit log --decorate=full --oneline >actual &&\n+\n+\t# None of the refs are visible:\n+\t! grep /fake actual\n+'\n+\n test_expect_success 'log --end-of-options' '\n        git update-ref refs/heads/--source HEAD &&\n        git log --end-of-options --source >actual &&\n-- \ngitgitgadget\n\n"},{"id":"460731","messageId":"1b12374ff1b1836522c6af2ea70cbd3f96cc75e3.1659722324.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v3.git.1659722323.gitgitgadget@gmail.com","subject":"[PATCH v3 08/11] log: add --clear-decorations option","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-08-05T17:58:40Z","receivedAt":"2022-08-05T17:59:36Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe previous changes introduced a new default ref filter for decorations\nin the 'git log' command. This can be overridden using\n--decorate-refs=HEAD and --decorate-refs=refs/, but that is cumbersome\nfor users.\n\nInstead, add a --clear-decorations option that resets all previous\nfilters to a blank filter that accepts all refs.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n Documentation/git-log.txt                     |   5 +\n builtin/log.c                                 |  24 +++-\n t/t4013-diff-various.sh                       |   2 +\n ..._--decorate=full_--clear-decorations_--all |  61 +++++++++++\n ...f.log_--decorate=full_--decorate-all_--all |  61 +++++++++++\n ...f.log_--decorate_--clear-decorations_--all |  61 +++++++++++\n .../diff.log_--decorate_--decorate-all_--all  |  61 +++++++++++\n t/t4202-log.sh                                | 103 +++++++++++++++++-\n 8 files changed, 371 insertions(+), 7 deletions(-)\n create mode 100644 t/t4013/diff.log_--decorate=full_--clear-decorations_--all\n create mode 100644 t/t4013/diff.log_--decorate=full_--decorate-all_--all\n create mode 100644 t/t4013/diff.log_--decorate_--clear-decorations_--all\n create mode 100644 t/t4013/diff.log_--decorate_--decorate-all_--all\n\ndiff --git a/Documentation/git-log.txt b/Documentation/git-log.txt\nindex b2ac89dfafc..f2ce16fba71 100644\n--- a/Documentation/git-log.txt\n+++ b/Documentation/git-log.txt\n@@ -56,6 +56,11 @@ If none of these options or config settings are given, then references are\n used as decoration if they match `HEAD`, `refs/heads/`, `refs/remotes/`,\n `refs/stash/`, or `refs/tags/`.\n \n+--clear-decorations::\n+\tWhen specified, this option clears all previous `--decorate-refs`\n+\tor `--decorate-refs-exclude` options and relaxes the default\n+\tdecoration filter to include all references.\n+\n --source::\n \tPrint out the ref name given on the command line by which each\n \tcommit was reached.\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 6683e5ff134..7d35d1ecab1 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -101,6 +101,20 @@ static int parse_decoration_style(const char *value)\n \treturn -1;\n }\n \n+static int use_default_decoration_filter = 1;\n+static struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n+static struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;\n+static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n+\n+static int clear_decorations_callback(const struct option *opt,\n+\t\t\t\t\t    const char *arg, int unset)\n+{\n+\tstring_list_clear(&decorate_refs_include, 0);\n+\tstring_list_clear(&decorate_refs_exclude, 0);\n+\tuse_default_decoration_filter = 0;\n+\treturn 0;\n+}\n+\n static int decorate_callback(const struct option *opt, const char *arg, int unset)\n {\n \tif (unset)\n@@ -176,7 +190,8 @@ static void set_default_decoration_filter(struct decoration_filter *decoration_f\n \t\t\t\t\t   item->string);\n \t}\n \n-\tif (decoration_filter->exclude_ref_pattern->nr ||\n+\tif (!use_default_decoration_filter ||\n+\t    decoration_filter->exclude_ref_pattern->nr ||\n \t    decoration_filter->include_ref_pattern->nr ||\n \t    decoration_filter->exclude_ref_config_pattern->nr)\n \t\treturn;\n@@ -199,9 +214,6 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \tstruct userformat_want w;\n \tint quiet = 0, source = 0, mailmap;\n \tstatic struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};\n-\tstatic struct string_list decorate_refs_exclude = STRING_LIST_INIT_NODUP;\n-\tstatic struct string_list decorate_refs_exclude_config = STRING_LIST_INIT_NODUP;\n-\tstatic struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;\n \tstruct decoration_filter decoration_filter = {\n \t\t.exclude_ref_pattern = &decorate_refs_exclude,\n \t\t.include_ref_pattern = &decorate_refs_include,\n@@ -214,6 +226,10 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,\n \t\tOPT_BOOL(0, \"source\", &source, N_(\"show source\")),\n \t\tOPT_BOOL(0, \"use-mailmap\", &mailmap, N_(\"use mail map file\")),\n \t\tOPT_ALIAS(0, \"mailmap\", \"use-mailmap\"),\n+\t\tOPT_CALLBACK_F(0, \"clear-decorations\", NULL, NULL,\n+\t\t\t       N_(\"clear all previously-defined decoration filters\"),\n+\t\t\t       PARSE_OPT_NOARG | PARSE_OPT_NONEG,\n+\t\t\t       clear_decorations_callback),\n \t\tOPT_STRING_LIST(0, \"decorate-refs\", &decorate_refs_include,\n \t\t\t\tN_(\"pattern\"), N_(\"only decorate refs that match <pattern>\")),\n \t\tOPT_STRING_LIST(0, \"decorate-refs-exclude\", &decorate_refs_exclude,\ndiff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh\nindex 056e922164d..dfcf3a0aaae 100755\n--- a/t/t4013-diff-various.sh\n+++ b/t/t4013-diff-various.sh\n@@ -352,6 +352,8 @@ log -GF -p --pickaxe-all master\n log -IA -IB -I1 -I2 -p master\n log --decorate --all\n log --decorate=full --all\n+log --decorate --clear-decorations --all\n+log --decorate=full --clear-decorations --all\n \n rev-list --parents HEAD\n rev-list --children HEAD\ndiff --git a/t/t4013/diff.log_--decorate=full_--clear-decorations_--all b/t/t4013/diff.log_--decorate=full_--clear-decorations_--all\nnew file mode 100644\nindex 00000000000..1c030a6554e\n--- /dev/null\n+++ b/t/t4013/diff.log_--decorate=full_--clear-decorations_--all\n@@ -0,0 +1,61 @@\n+$ git log --decorate=full --clear-decorations --all\n+commit b7e0bc69303b488b47deca799a7d723971dfa6cd (refs/heads/mode)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    update mode\n+\n+commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (refs/heads/note)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    update mode (file2)\n+\n+Notes:\n+    note\n+\n+commit cd4e72fd96faed3f0ba949dc42967430374e2290 (refs/heads/rearrange)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    Rearranged lines in dir/sub\n+\n+commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    Notes added by 'git notes add'\n+\n+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master)\n+Merge: 9a6d494 c7a2ab9\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:04:00 2006 +0000\n+\n+    Merge branch 'side'\n+\n+commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:03:00 2006 +0000\n+\n+    Side\n+\n+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:02:00 2006 +0000\n+\n+    Third\n+\n+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:01:00 2006 +0000\n+\n+    Second\n+    \n+    This is the second commit.\n+\n+commit 444ac553ac7612cc88969031b02b3767fb8a353a (refs/heads/initial)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:00:00 2006 +0000\n+\n+    Initial\n+$\ndiff --git a/t/t4013/diff.log_--decorate=full_--decorate-all_--all b/t/t4013/diff.log_--decorate=full_--decorate-all_--all\nnew file mode 100644\nindex 00000000000..d6e79287846\n--- /dev/null\n+++ b/t/t4013/diff.log_--decorate=full_--decorate-all_--all\n@@ -0,0 +1,61 @@\n+$ git log --decorate=full --decorate-all --all\n+commit b7e0bc69303b488b47deca799a7d723971dfa6cd (refs/heads/mode)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    update mode\n+\n+commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (refs/heads/note)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    update mode (file2)\n+\n+Notes:\n+    note\n+\n+commit cd4e72fd96faed3f0ba949dc42967430374e2290 (refs/heads/rearrange)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    Rearranged lines in dir/sub\n+\n+commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    Notes added by 'git notes add'\n+\n+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master)\n+Merge: 9a6d494 c7a2ab9\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:04:00 2006 +0000\n+\n+    Merge branch 'side'\n+\n+commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (refs/heads/side)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:03:00 2006 +0000\n+\n+    Side\n+\n+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:02:00 2006 +0000\n+\n+    Third\n+\n+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:01:00 2006 +0000\n+\n+    Second\n+    \n+    This is the second commit.\n+\n+commit 444ac553ac7612cc88969031b02b3767fb8a353a (refs/heads/initial)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:00:00 2006 +0000\n+\n+    Initial\n+$\ndiff --git a/t/t4013/diff.log_--decorate_--clear-decorations_--all b/t/t4013/diff.log_--decorate_--clear-decorations_--all\nnew file mode 100644\nindex 00000000000..88be82cce31\n--- /dev/null\n+++ b/t/t4013/diff.log_--decorate_--clear-decorations_--all\n@@ -0,0 +1,61 @@\n+$ git log --decorate --clear-decorations --all\n+commit b7e0bc69303b488b47deca799a7d723971dfa6cd (mode)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    update mode\n+\n+commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (note)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    update mode (file2)\n+\n+Notes:\n+    note\n+\n+commit cd4e72fd96faed3f0ba949dc42967430374e2290 (rearrange)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    Rearranged lines in dir/sub\n+\n+commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    Notes added by 'git notes add'\n+\n+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master)\n+Merge: 9a6d494 c7a2ab9\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:04:00 2006 +0000\n+\n+    Merge branch 'side'\n+\n+commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:03:00 2006 +0000\n+\n+    Side\n+\n+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:02:00 2006 +0000\n+\n+    Third\n+\n+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:01:00 2006 +0000\n+\n+    Second\n+    \n+    This is the second commit.\n+\n+commit 444ac553ac7612cc88969031b02b3767fb8a353a (initial)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:00:00 2006 +0000\n+\n+    Initial\n+$\ndiff --git a/t/t4013/diff.log_--decorate_--decorate-all_--all b/t/t4013/diff.log_--decorate_--decorate-all_--all\nnew file mode 100644\nindex 00000000000..5d22618bb60\n--- /dev/null\n+++ b/t/t4013/diff.log_--decorate_--decorate-all_--all\n@@ -0,0 +1,61 @@\n+$ git log --decorate --decorate-all --all\n+commit b7e0bc69303b488b47deca799a7d723971dfa6cd (mode)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    update mode\n+\n+commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (note)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    update mode (file2)\n+\n+Notes:\n+    note\n+\n+commit cd4e72fd96faed3f0ba949dc42967430374e2290 (rearrange)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    Rearranged lines in dir/sub\n+\n+commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:06:00 2006 +0000\n+\n+    Notes added by 'git notes add'\n+\n+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master)\n+Merge: 9a6d494 c7a2ab9\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:04:00 2006 +0000\n+\n+    Merge branch 'side'\n+\n+commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a (side)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:03:00 2006 +0000\n+\n+    Side\n+\n+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:02:00 2006 +0000\n+\n+    Third\n+\n+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:01:00 2006 +0000\n+\n+    Second\n+    \n+    This is the second commit.\n+\n+commit 444ac553ac7612cc88969031b02b3767fb8a353a (initial)\n+Author: A U Thor <author@example.com>\n+Date:   Mon Jun 26 00:00:00 2006 +0000\n+\n+    Initial\n+$\ndiff --git a/t/t4202-log.sh b/t/t4202-log.sh\nindex 4c3ce863074..90800feb0f1 100755\n--- a/t/t4202-log.sh\n+++ b/t/t4202-log.sh\n@@ -704,9 +704,12 @@ test_expect_success 'set up more tangled history' '\n \tgit checkout -b tangle HEAD~6 &&\n \ttest_commit tangle-a tangle-a a &&\n \tgit merge main~3 &&\n+\tgit update-ref refs/prefetch/merge HEAD &&\n \tgit merge side~1 &&\n+\tgit update-ref refs/rewritten/merge HEAD &&\n \tgit checkout main &&\n \tgit merge tangle &&\n+\tgit update-ref refs/hidden/tangle HEAD &&\n \tgit checkout -b reach &&\n \ttest_commit reach &&\n \tgit checkout main &&\n@@ -974,9 +977,9 @@ test_expect_success 'decorate-refs-exclude and simplify-by-decoration' '\n \tMerge-tag-reach (HEAD -> main)\n \treach (tag: reach, reach)\n \tseventh (tag: seventh)\n-\tMerge-branch-tangle\n-\tMerge-branch-side-early-part-into-tangle (tangle)\n-\ttangle-a (tag: tangle-a)\n+\tMerge-branch-tangle (refs/hidden/tangle)\n+\tMerge-branch-side-early-part-into-tangle (refs/rewritten/merge, tangle)\n+\tMerge-branch-main-early-part-into-tangle (refs/prefetch/merge)\n \tEOF\n \tgit log -n6 --decorate=short --pretty=\"tformat:%f%d\" \\\n \t\t--decorate-refs-exclude=\"*octopus*\" \\\n@@ -1037,6 +1040,100 @@ test_expect_success 'decorate-refs focus from default' '\n \t! grep HEAD actual\n '\n \n+test_expect_success '--clear-decorations overrides defaults' '\n+\tcat >expect.default <<-\\EOF &&\n+\tMerge-tag-reach (HEAD -> refs/heads/main)\n+\tMerge-tags-octopus-a-and-octopus-b\n+\tseventh (tag: refs/tags/seventh)\n+\toctopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)\n+\toctopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)\n+\treach (tag: refs/tags/reach, refs/heads/reach)\n+\tMerge-branch-tangle\n+\tMerge-branch-side-early-part-into-tangle (refs/heads/tangle)\n+\tMerge-branch-main-early-part-into-tangle\n+\ttangle-a (tag: refs/tags/tangle-a)\n+\tMerge-branch-side\n+\tside-2 (tag: refs/tags/side-2, refs/heads/side)\n+\tside-1 (tag: refs/tags/side-1)\n+\tSecond\n+\tsixth\n+\tfifth\n+\tfourth\n+\tthird\n+\tsecond\n+\tinitial\n+\tEOF\n+\tgit log --decorate=full --pretty=\"tformat:%f%d\" >actual &&\n+\ttest_cmp expect.default actual &&\n+\n+\tcat >expect.all <<-\\EOF &&\n+\tMerge-tag-reach (HEAD -> refs/heads/main)\n+\tMerge-tags-octopus-a-and-octopus-b\n+\tseventh (tag: refs/tags/seventh)\n+\toctopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)\n+\toctopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)\n+\treach (tag: refs/tags/reach, refs/heads/reach)\n+\tMerge-branch-tangle (refs/hidden/tangle)\n+\tMerge-branch-side-early-part-into-tangle (refs/rewritten/merge, refs/heads/tangle)\n+\tMerge-branch-main-early-part-into-tangle (refs/prefetch/merge)\n+\ttangle-a (tag: refs/tags/tangle-a)\n+\tMerge-branch-side\n+\tside-2 (tag: refs/tags/side-2, refs/heads/side)\n+\tside-1 (tag: refs/tags/side-1)\n+\tSecond\n+\tsixth\n+\tfifth\n+\tfourth\n+\tthird\n+\tsecond\n+\tinitial\n+\tEOF\n+\tgit log --decorate=full --pretty=\"tformat:%f%d\" \\\n+\t\t--clear-decorations >actual &&\n+\ttest_cmp expect.all actual\n+'\n+\n+test_expect_success '--clear-decorations clears previous exclusions' '\n+\tcat >expect.all <<-\\EOF &&\n+\tMerge-tag-reach (HEAD -> refs/heads/main)\n+\treach (tag: refs/tags/reach, refs/heads/reach)\n+\tMerge-tags-octopus-a-and-octopus-b\n+\toctopus-b (tag: refs/tags/octopus-b, refs/heads/octopus-b)\n+\toctopus-a (tag: refs/tags/octopus-a, refs/heads/octopus-a)\n+\tseventh (tag: refs/tags/seventh)\n+\tMerge-branch-tangle (refs/hidden/tangle)\n+\tMerge-branch-side-early-part-into-tangle (refs/rewritten/merge, refs/heads/tangle)\n+\tMerge-branch-main-early-part-into-tangle (refs/prefetch/merge)\n+\ttangle-a (tag: refs/tags/tangle-a)\n+\tside-2 (tag: refs/tags/side-2, refs/heads/side)\n+\tside-1 (tag: refs/tags/side-1)\n+\tinitial\n+\tEOF\n+\n+\tgit log --decorate=full --pretty=\"tformat:%f%d\" \\\n+\t\t--simplify-by-decoration \\\n+\t\t--decorate-refs-exclude=\"heads/octopus*\" \\\n+\t\t--decorate-refs=\"heads\" \\\n+\t\t--clear-decorations >actual &&\n+\ttest_cmp expect.all actual &&\n+\n+\tcat >expect.filtered <<-\\EOF &&\n+\tMerge-tags-octopus-a-and-octopus-b\n+\toctopus-b (refs/heads/octopus-b)\n+\toctopus-a (refs/heads/octopus-a)\n+\tinitial\n+\tEOF\n+\n+\tgit log --decorate=full --pretty=\"tformat:%f%d\" \\\n+\t\t--simplify-by-decoration \\\n+\t\t--decorate-refs-exclude=\"heads/octopus\" \\\n+\t\t--decorate-refs=\"heads\" \\\n+\t\t--clear-decorations \\\n+\t\t--decorate-refs-exclude=\"tags/\" \\\n+\t\t--decorate-refs=\"heads/octopus*\" >actual &&\n+\ttest_cmp expect.filtered actual\n+'\n+\n test_expect_success 'log.decorate config parsing' '\n \tgit log --oneline --decorate=full >expect.full &&\n \tgit log --oneline --decorate=short >expect.short &&\n-- \ngitgitgadget\n\n"},{"id":"460732","messageId":"1f4d9bc4b3feb0d95a24c4ffb900070f7c9c7e1b.1659722324.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v3.git.1659722323.gitgitgadget@gmail.com","subject":"[PATCH v3 10/11] maintenance: stop writing log.excludeDecoration","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-08-05T17:58:42Z","receivedAt":"2022-08-05T17:59:40Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThis reverts commit 96eaffebbf3d0 (maintenance: set\nlog.excludeDecoration durin prefetch, 2021-01-19).\n\nThe previous change created a default decoration filter that does not\ninclude refs/prefetch/, so this modification of the config is no longer\nneeded.\n\nOne issue that can happen from this point on is that users who ran the\nprefetch task on previous versions of Git will still have a\nlog.excludeDecoration value and that will prevent the new default\ndecoration filter from being active. Thus, when we add the refs/bundle/\nnamespace as part of the bundle URI feature, those users will see\nrefs/bundle/ decorations.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n builtin/gc.c           |  6 ------\n t/t7900-maintenance.sh | 21 ---------------------\n 2 files changed, 27 deletions(-)\n\ndiff --git a/builtin/gc.c b/builtin/gc.c\nindex eeff2b760e0..6c222052177 100644\n--- a/builtin/gc.c\n+++ b/builtin/gc.c\n@@ -910,12 +910,6 @@ static int fetch_remote(struct remote *remote, void *cbdata)\n \n static int maintenance_task_prefetch(struct maintenance_run_opts *opts)\n {\n-\tgit_config_set_multivar_gently(\"log.excludedecoration\",\n-\t\t\t\t\t\"refs/prefetch/\",\n-\t\t\t\t\t\"refs/prefetch/\",\n-\t\t\t\t\tCONFIG_FLAGS_FIXED_VALUE |\n-\t\t\t\t\tCONFIG_FLAGS_MULTI_REPLACE);\n-\n \tif (for_each_remote(fetch_remote, opts)) {\n \t\terror(_(\"failed to prefetch remotes\"));\n \t\treturn 1;\ndiff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh\nindex 74aa6384755..62ed694a404 100755\n--- a/t/t7900-maintenance.sh\n+++ b/t/t7900-maintenance.sh\n@@ -162,7 +162,6 @@ test_expect_success 'prefetch multiple remotes' '\n \ttest_cmp_rev refs/remotes/remote1/one refs/prefetch/remotes/remote1/one &&\n \ttest_cmp_rev refs/remotes/remote2/two refs/prefetch/remotes/remote2/two &&\n \n-\ttest_cmp_config refs/prefetch/ log.excludedecoration &&\n \tgit log --oneline --decorate --all >log &&\n \t! grep \"prefetch\" log &&\n \n@@ -173,26 +172,6 @@ test_expect_success 'prefetch multiple remotes' '\n \ttest_subcommand git fetch remote2 $fetchargs <skip-remote1.txt\n '\n \n-test_expect_success 'prefetch and existing log.excludeDecoration values' '\n-\tgit config --unset-all log.excludeDecoration &&\n-\tgit config log.excludeDecoration refs/remotes/remote1/ &&\n-\tgit maintenance run --task=prefetch &&\n-\n-\tgit config --get-all log.excludeDecoration >out &&\n-\tgrep refs/remotes/remote1/ out &&\n-\tgrep refs/prefetch/ out &&\n-\n-\tgit log --oneline --decorate --all >log &&\n-\t! grep \"prefetch\" log &&\n-\t! grep \"remote1\" log &&\n-\tgrep \"remote2\" log &&\n-\n-\t# a second run does not change the config\n-\tgit maintenance run --task=prefetch &&\n-\tgit log --oneline --decorate --all >log2 &&\n-\ttest_cmp log log2\n-'\n-\n test_expect_success 'loose-objects task' '\n \t# Repack everything so we know the state of the object dir\n \tgit repack -adk &&\n-- \ngitgitgadget\n\n"},{"id":"460733","messageId":"7ec2578b90a4e9f0e698bd29d7413e11df819253.1659722324.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v3.git.1659722323.gitgitgadget@gmail.com","subject":"[PATCH v3 09/11] log: create log.initialDecorationSet=all","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-08-05T17:58:41Z","receivedAt":"2022-08-05T17:59:42Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe previous change introduced the --clear-decorations option for users\nwho do not want their decorations limited to a narrow set of ref\nnamespaces.\n\nAdd a config option that is equivalent to specifying --clear-decorations\nby default.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n Documentation/config/log.txt |  5 +++++\n Documentation/git-log.txt    |  4 +++-\n builtin/log.c                | 12 ++++++++++++\n t/t4202-log.sh               |  3 +++\n 4 files changed, 23 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/config/log.txt b/Documentation/config/log.txt\nindex 456eb07800c..5250ba45fb4 100644\n--- a/Documentation/config/log.txt\n+++ b/Documentation/config/log.txt\n@@ -18,6 +18,11 @@ log.decorate::\n \tnames are shown. This is the same as the `--decorate` option\n \tof the `git log`.\n \n+log.initialDecorationSet::\n+\tBy default, `git log` only shows decorations for certain known ref\n+\tnamespaces. If 'all' is specified, then show all refs as\n+\tdecorations.\n+\n log.excludeDecoration::\n \tExclude the specified patterns from the log decorations. This is\n \tsimilar to the `--decorate-refs-exclude` command-line option, but\ndiff --git a/Documentation/git-log.txt b/Documentation/git-log.txt\nindex f2ce16fba71..b1285aee3c2 100644\n--- a/Documentation/git-log.txt\n+++ b/Documentation/git-log.txt\n@@ -59,7 +59,9 @@ used as decoration if they match `HEAD`, `refs/heads/`, `refs/remotes/`,\n --clear-decorations::\n \tWhen specified, this option clears all previous `--decorate-refs`\n \tor `--decorate-refs-exclude` options and relaxes the default\n-\tdecoration filter to include all references.\n+\tdecoration filter to include all references. This option is\n+\tassumed if the config value `log.initialDecorationSet` is set to\n+\t`all`.\n \n --source::\n \tPrint out the ref name given on the command line by which each\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 7d35d1ecab1..2e2136020e5 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -179,6 +179,7 @@ static void cmd_log_init_defaults(struct rev_info *rev)\n static void set_default_decoration_filter(struct decoration_filter *decoration_filter)\n {\n \tint i;\n+\tchar *value = NULL;\n \tstruct string_list *include = decoration_filter->include_ref_pattern;\n \tconst struct string_list *config_exclude =\n \t\t\tgit_config_get_value_multi(\"log.excludeDecoration\");\n@@ -190,6 +191,17 @@ static void set_default_decoration_filter(struct decoration_filter *decoration_f\n \t\t\t\t\t   item->string);\n \t}\n \n+\t/*\n+\t * By default, decorate_all is disabled. Enable it if\n+\t * log.initialDecorationSet=all. Don't ever disable it by config,\n+\t * since the command-line takes precedent.\n+\t */\n+\tif (use_default_decoration_filter &&\n+\t    !git_config_get_string(\"log.initialdecorationset\", &value) &&\n+\t    !strcmp(\"all\", value))\n+\t\tuse_default_decoration_filter = 0;\n+\tfree(value);\n+\n \tif (!use_default_decoration_filter ||\n \t    decoration_filter->exclude_ref_pattern->nr ||\n \t    decoration_filter->include_ref_pattern->nr ||\ndiff --git a/t/t4202-log.sh b/t/t4202-log.sh\nindex 90800feb0f1..4b2d642d34c 100755\n--- a/t/t4202-log.sh\n+++ b/t/t4202-log.sh\n@@ -1090,6 +1090,9 @@ test_expect_success '--clear-decorations overrides defaults' '\n \tEOF\n \tgit log --decorate=full --pretty=\"tformat:%f%d\" \\\n \t\t--clear-decorations >actual &&\n+\ttest_cmp expect.all actual &&\n+\tgit -c log.initialDecorationSet=all log \\\n+\t\t--decorate=full --pretty=\"tformat:%f%d\" >actual &&\n \ttest_cmp expect.all actual\n '\n \n-- \ngitgitgadget\n\n"},{"id":"460734","messageId":"bd2ffac88acd4ac4c408e362b86dada330656cc4.1659722324.git.gitgitgadget@gmail.com","threadId":"58226","inReplyTo":"pull.1301.v3.git.1659722323.gitgitgadget@gmail.com","subject":"[PATCH v3 11/11] fetch: use ref_namespaces during prefetch","fromName":"Derrick Stolee via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2022-08-05T17:58:43Z","receivedAt":"2022-08-05T18:00:05Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"From: Derrick Stolee <derrickstolee@github.com>\n\nThe \"refs/prefetch/\" namespace is used by 'git fetch --prefetch' as a\nreplacement of the destination of the refpsec for a remote. Git also\nremoves refspecs that include tags.\n\nInstead of using string literals for the 'refs/tags/ and\n'refs/prefetch/' namespaces, use the entries in the ref_namespaces\narray.\n\nThis kind of change could be done in many places around the codebase,\nbut we are isolating only to this change because of the way the\nrefs/prefetch/ namespace somewhat motivated the creation of the\nref_namespaces array.\n\nSigned-off-by: Derrick Stolee <derrickstolee@github.com>\n---\n builtin/fetch.c | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/fetch.c b/builtin/fetch.c\nindex fc5cecb4835..368a0f5329c 100644\n--- a/builtin/fetch.c\n+++ b/builtin/fetch.c\n@@ -490,7 +490,9 @@ static void filter_prefetch_refspec(struct refspec *rs)\n \t\t\tcontinue;\n \t\tif (!rs->items[i].dst ||\n \t\t    (rs->items[i].src &&\n-\t\t     !strncmp(rs->items[i].src, \"refs/tags/\", 10))) {\n+\t\t     !strncmp(rs->items[i].src,\n+\t\t\t      ref_namespace[NAMESPACE_TAGS].ref,\n+\t\t\t      strlen(ref_namespace[NAMESPACE_TAGS].ref)))) {\n \t\t\tint j;\n \n \t\t\tfree(rs->items[i].src);\n@@ -506,7 +508,7 @@ static void filter_prefetch_refspec(struct refspec *rs)\n \t\t}\n \n \t\told_dst = rs->items[i].dst;\n-\t\tstrbuf_addstr(&new_dst, \"refs/prefetch/\");\n+\t\tstrbuf_addstr(&new_dst, ref_namespace[NAMESPACE_PREFETCH].ref);\n \n \t\t/*\n \t\t * If old_dst starts with \"refs/\", then place\n-- \ngitgitgadget\n"},{"id":"461098","messageId":"220811.86k07eplty.gmgdl@evledraar.gmail.com","threadId":"58226","inReplyTo":"2184ffe4-4fde-878f-052f-e7dcdebe8161@github.com","subject":"Re: [PATCH v2 06/10] log: add default decoration filter","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-08-11T19:30:43Z","receivedAt":"2022-08-11T20:27:45Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Aug 05 2022, Derrick Stolee wrote:\n\n> On 8/5/2022 10:50 AM, Ævar Arnfjörð Bjarmason wrote:\n>> \n>> On Fri, Aug 05 2022, Derrick Stolee wrote:\n>\n>>> Now that this version removed the notes ref from the\n>>> decoration, the stance for inclusion is simple:\n>>>\n>>>   If Git offers to color the namespace with color.decoration.<slot>,\n>>>   then Git decorates with that namespace by default.\n>> \n>> I'm a bit confused, sorry.\n>> \n>> So aside from \"notes\", if we have a color.decoration.<slot> applying to\n>> a ref now, it's a bug in your series if it's not showing up anymore?\n>\n> The possible slots are:\n>\n>  * branch (refs/heads/)\n>  * remoteBranch (refs/remotes/)\n>  * tag (refs/tags/)\n>  * stash (refs/stash)\n>  * HEAD (HEAD)\n>  * grafted (refs/replace/ or GIT_REPLACE_REF_BASE)\n>\n> These are exactly the namespaces that are now shown by default in\n> this series.\n\nNo, e.g. \"tag\" doesn't mean \"refs/tags/*\", it means *a tag object*. Try\nthis on master:\n\n\tgit update-ref refs/archived-tags/v2.36.0 refs/tags/v2.36.0\n\nThen on master:\n\n\t./git -P -c color.decorate.tag=\"bold blue\" log --oneline -1 v2.36.0\n\t6cd33dceed6 (tag: v2.36.0, gitster/yw/cmake-use-pcre2, gitgitgadget/yw/cmake-use-pcre2, tag: refs/archived-tags/v2.36.0) Git 2.36\n\nBut on \"seen\" currently:\n\n\t$ ./git -P -c color.decorate.tag=\"bold blue\" log --oneline -1 v2.36.0\n\t6cd33dceed6 (tag: v2.36.0, gitster/yw/cmake-use-pcre2, gitgitgadget/yw/cmake-use-pcre2) Git 2.36\n\nBefore that \"bold blue\" applied to *tag objects*, but your series has\nmade it apply to the refs/tags/* namespace.\n\nI noted this (indirectly) before in\nhttps://lore.kernel.org/git/220726.86tu73ncf8.gmgdl@evledraar.gmail.com/;\nI.e. that I have a \"refs/built-tags/\" namespace.\n\nSo that specifically seems like a regression by the criteria you've\nestablished for inclusion. I.e. we have objects that are impacted by\nexisting coloring config now that your series is hiding, seemingly\nbecause you've conflated \"tag object\" with \"a name in in refs/tags/\".\n\nI *also* think it's overzelous to hide *uknown* things by default\nbecause we think we might add more *known* internal things in the\nfuture, but that's a distinct topic from this more narrow case, which\nseems to be a clear regression by criteria you're establishing &\nadvocating for.\n\n> If someone adds a new color slot, then that would need to be\n> justified with a reason why that slot is important. We've already\n> had discussions as to why showing a decoration for notes is not\n> valuable to an end user. The stability of this config option (the\n> last addition of 'grafted' was in 2011) is good evidence that this\n> core set of namespaces is all users will need.\n>\n> By contrast, the use of \"hidden\" namespaces is relatively new and\n> is expected to increase in the near future.\n\nI really don't see how you're making the leap that because nobody's\nbothered to customize the coloring for things in custom namespaces that\nit's OK to hide them entirely.\n\nI just leave everything at the default color settings, aside from (after\nchecking my ~/.gitconfig) one bit of diff coloring default that I found\nannoying.\n"},{"id":"461135","messageId":"d4b78b33-5b27-b536-1534-6a5201d392f0@github.com","threadId":"58226","inReplyTo":"220811.86k07eplty.gmgdl@evledraar.gmail.com","subject":"Re: [PATCH v2 06/10] log: add default decoration filter","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-08-12T19:37:23Z","receivedAt":"2022-08-12T19:37:31Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 8/11/2022 3:30 PM, Ævar Arnfjörð Bjarmason wrote:\n> \n> On Fri, Aug 05 2022, Derrick Stolee wrote:\n> \n>> On 8/5/2022 10:50 AM, Ævar Arnfjörð Bjarmason wrote:\n>>>\n>>> On Fri, Aug 05 2022, Derrick Stolee wrote:\n>>\n>>>> Now that this version removed the notes ref from the\n>>>> decoration, the stance for inclusion is simple:\n>>>>\n>>>>   If Git offers to color the namespace with color.decoration.<slot>,\n>>>>   then Git decorates with that namespace by default.\n>>>\n>>> I'm a bit confused, sorry.\n>>>\n>>> So aside from \"notes\", if we have a color.decoration.<slot> applying to\n>>> a ref now, it's a bug in your series if it's not showing up anymore?\n>>\n>> The possible slots are:\n>>\n>>  * branch (refs/heads/)\n>>  * remoteBranch (refs/remotes/)\n>>  * tag (refs/tags/)\n>>  * stash (refs/stash)\n>>  * HEAD (HEAD)\n>>  * grafted (refs/replace/ or GIT_REPLACE_REF_BASE)\n>>\n>> These are exactly the namespaces that are now shown by default in\n>> this series.\n> \n> No, e.g. \"tag\" doesn't mean \"refs/tags/*\", it means *a tag object*.\n\nYou are half right. It means \"refs/tags/*\" _or_ \"a tag object\". A\nlightweight tag is still counted based only on its ref namespace.\n\n> Try\n> this on master:\n> \n> \tgit update-ref refs/archived-tags/v2.36.0 refs/tags/v2.36.0\n> \n> Then on master:\n> \n> \t./git -P -c color.decorate.tag=\"bold blue\" log --oneline -1 v2.36.0\n> \t6cd33dceed6 (tag: v2.36.0, gitster/yw/cmake-use-pcre2, gitgitgadget/yw/cmake-use-pcre2, tag: refs/archived-tags/v2.36.0) Git 2.36\n> \n> But on \"seen\" currently:\n> \n> \t$ ./git -P -c color.decorate.tag=\"bold blue\" log --oneline -1 v2.36.0\n> \t6cd33dceed6 (tag: v2.36.0, gitster/yw/cmake-use-pcre2, gitgitgadget/yw/cmake-use-pcre2) Git 2.36\n\nYou initially made me think there was a bug that was not covered\nby our existing test infrastructure. We may still be missing a\ntest about this \"annotated tag outside of refs/tags/*\" behavior,\nbut it is not broken with this series.\n\nThe change of behavior here is that refs/archived-tags is excluded\nfrom the list of decorations. If you applied --clear-decorations to\nyour log command, then it would appear. It would also receive the\nbold blue coloring (and the \"tag:\" prefix) since it points to an\nannotated tag object.\n\nI also tested non-annotated tags in the refs/tags/* space and the\ncoloring continues to work correctly before and after this change.\n\nThanks,\n-Stolee\n"},{"id":"462836","messageId":"kl6lr10l8t7y.fsf@chooglen-macbookpro.roam.corp.google.com","threadId":"58226","inReplyTo":"c249bface2a6dcd0355620f92579b42a6fa4ea58.1659722324.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 07/11] log: add default decoration filter","fromName":"Glen Choo","fromEmail":"chooglen@google.com","sentAt":"2022-09-08T21:13:53Z","receivedAt":"2022-09-08T21:14:04Z","isPatch":true,"sender":{"key":"glencbz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58092771?v=4"},"body":"\"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> From: Derrick Stolee <derrickstolee@github.com>\n>\n> When a user runs 'git log', they expect a certain set of helpful\n> decorations. This includes:\n>\n> * The HEAD ref\n> * Branches (refs/heads/)\n> * Stashes (refs/stash)\n> * Tags (refs/tags/)\n> * Remote branches (refs/remotes/)\n> * Replace refs (refs/replace/ or $GIT_REPLACE_REF_BASE)\n>\n> Each of these namespaces was selected due to existing test cases that\n> verify these namespaces appear in the decorations. In particular,\n> stashes and replace refs can have custom colors from the\n> color.decorate.<slot> config option.\n\nI _just_ noticed that refs/bisect/* isn't part of this list, but I'd\npresume that users want to see those decorations (or I do, at least).\nWas that an intentional omission?\n"},{"id":"462848","messageId":"42db9da3-3f69-1bf0-6d88-692e18eb74c1@github.com","threadId":"58226","inReplyTo":"kl6lr10l8t7y.fsf@chooglen-macbookpro.roam.corp.google.com","subject":"Re: [PATCH v3 07/11] log: add default decoration filter","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-09-09T12:23:28Z","receivedAt":"2022-09-09T12:24:34Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 9/8/2022 5:13 PM, Glen Choo wrote:\n> \"Derrick Stolee via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n> \n>> From: Derrick Stolee <derrickstolee@github.com>\n>>\n>> When a user runs 'git log', they expect a certain set of helpful\n>> decorations. This includes:\n>>\n>> * The HEAD ref\n>> * Branches (refs/heads/)\n>> * Stashes (refs/stash)\n>> * Tags (refs/tags/)\n>> * Remote branches (refs/remotes/)\n>> * Replace refs (refs/replace/ or $GIT_REPLACE_REF_BASE)\n>>\n>> Each of these namespaces was selected due to existing test cases that\n>> verify these namespaces appear in the decorations. In particular,\n>> stashes and replace refs can have custom colors from the\n>> color.decorate.<slot> config option.\n> \n> I _just_ noticed that refs/bisect/* isn't part of this list, but I'd\n> presume that users want to see those decorations (or I do, at least).\n> Was that an intentional omission?\n\nIt was an intentional omission because the refs/bisect/* references\nare not part of the color.decorate.<slot> category.\n\nLooking into it further, the bisect refs look pretty ugly (especially\nthe ones like \"refs/bisect/good-<hash>\").\n\nIf you would like to include these in the default filter, then I\nwould recommend also adding a color.decorate.<slot> category for them\nand possibly replace the \"refs/bisect\" with just \"bisect\". Alternatively,\nyou could take a hint from replace objects and just use an indicator\nlike \"bisect good\" or \"bisect bad\" instead of listing the full ref name.\n\nThanks,\n-Stolee\n"},{"id":"462868","messageId":"xmqqbkromsfx.fsf@gitster.g","threadId":"58226","inReplyTo":"42db9da3-3f69-1bf0-6d88-692e18eb74c1@github.com","subject":"Re: [PATCH v3 07/11] log: add default decoration filter","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-09-09T16:19:14Z","receivedAt":"2022-09-09T16:19:19Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Derrick Stolee <derrickstolee@github.com> writes:\n\n> It was an intentional omission because the refs/bisect/* references\n> are not part of the color.decorate.<slot> category.\n>\n> Looking into it further, the bisect refs look pretty ugly (especially\n> the ones like \"refs/bisect/good-<hash>\").\n>\n> If you would like to include these in the default filter, then I\n> would recommend also adding a color.decorate.<slot> category for them\n> and possibly replace the \"refs/bisect\" with just \"bisect\". Alternatively,\n> you could take a hint from replace objects and just use an indicator\n> like \"bisect good\" or \"bisect bad\" instead of listing the full ref name.\n\nI personally do not think bisect/bad and bisect/good-* need to be\npart of the default set of refs to use for decoration.\n\nI suspect that the suggestion to use them for decoration is based on\nthe gut feeling: \"People during their bisect session would want to\nknow which points they already examined and what their states are.\"\n\nBut during bisection, there is a specific command to give them\nexactly that information: \"bisect visualize\".  It is roughly\nequilvalent to:\n\n    git log refs/bisect/bad \\\n\t$(git for-each-ref --format='^%(refname)' refs/bisect/good-\\*\n\ni.e. show the history surrounded by all the known-to-be-good commits\nand the known-to-be-bad commit we currently are chasing.  Bad and good\ncommits are at the boundary you can tell them without decoration.\n\nBut if we still want to see bisect/bad and bisect/good-* in a larger\ngraph (i.e. showing descendants of bad and ancestors of good), then\nI do not think good-<object name> being a long label is something we\nshould special case and shorten.  Especially because the user is not\nusing \"bisect visualize\", which is readable without decoration, they\nmay be seeking more information in the names, perhaps cutting and\npasting the object names to feed \"git show\" running on a separate\nterminal, or something.\n"},{"id":"462870","messageId":"d0d0836c-9d2f-53fe-dda1-a8c61e3acd9f@github.com","threadId":"58226","inReplyTo":"xmqqbkromsfx.fsf@gitster.g","subject":"Re: [PATCH v3 07/11] log: add default decoration filter","fromName":"Derrick Stolee","fromEmail":"derrickstolee@github.com","sentAt":"2022-09-09T16:40:37Z","receivedAt":"2022-09-09T16:41:04Z","isPatch":true,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 9/9/2022 12:19 PM, Junio C Hamano wrote:\n\n> But during bisection, there is a specific command to give them\n> exactly that information: \"bisect visualize\".  It is roughly\n> equilvalent to:\n> \n>     git log refs/bisect/bad \\\n> \t$(git for-each-ref --format='^%(refname)' refs/bisect/good-\\*\n> \n> i.e. show the history surrounded by all the known-to-be-good commits\n> and the known-to-be-bad commit we currently are chasing.  Bad and good\n> commits are at the boundary you can tell them without decoration.\n\nThank you for recommending this as the expected behavior.\n \n> But if we still want to see bisect/bad and bisect/good-* in a larger\n> graph (i.e. showing descendants of bad and ancestors of good), then\n> I do not think good-<object name> being a long label is something we\n> should special case and shorten.  Especially because the user is not\n> using \"bisect visualize\", which is readable without decoration, they\n> may be seeking more information in the names, perhaps cutting and\n> pasting the object names to feed \"git show\" running on a separate\n> terminal, or something.\n\nThe object names should be visible as part of the \"git log\" output\n(perhaps abbreviated) and that provides a way to get that information\nwithout needing an unabbreviated hash showing up in a decoration slot.\n\nThanks,\n-Stolee\n"},{"id":"462874","messageId":"kl6lk06c8oad.fsf@chooglen-macbookpro.roam.corp.google.com","threadId":"58226","inReplyTo":"xmqqbkromsfx.fsf@gitster.g","subject":"Re: [PATCH v3 07/11] log: add default decoration filter","fromName":"Glen Choo","fromEmail":"chooglen@google.com","sentAt":"2022-09-09T17:12:42Z","receivedAt":"2022-09-09T17:12:49Z","isPatch":true,"sender":{"key":"glencbz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58092771?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Derrick Stolee <derrickstolee@github.com> writes:\n>\n>> It was an intentional omission because the refs/bisect/* references\n>> are not part of the color.decorate.<slot> category.\n>>\n>> Looking into it further, the bisect refs look pretty ugly (especially\n>> the ones like \"refs/bisect/good-<hash>\").\n>>\n>> If you would like to include these in the default filter, then I\n>> would recommend also adding a color.decorate.<slot> category for them\n>> and possibly replace the \"refs/bisect\" with just \"bisect\". Alternatively,\n>> you could take a hint from replace objects and just use an indicator\n>> like \"bisect good\" or \"bisect bad\" instead of listing the full ref name.\n>\n> I suspect that the suggestion to use them for decoration is based on\n> the gut feeling: \"People during their bisect session would want to\n> know which points they already examined and what their states are.\"\n>\n> But during bisection, there is a specific command to give them\n> exactly that information: \"bisect visualize\".  It is roughly\n> equilvalent to:\n>\n>     git log refs/bisect/bad \\\n> \t$(git for-each-ref --format='^%(refname)' refs/bisect/good-\\*\n>\n> i.e. show the history surrounded by all the known-to-be-good commits\n> and the known-to-be-bad commit we currently are chasing.  Bad and good\n> commits are at the boundary you can tell them without decoration.\n\nThanks, both. I think \"bisect visualize\" covers the use case I was\nthinking of (seeing the bisect result in the commit history), so\nomitting refs/bisect/* sounds fine. And if users are unhappy about the\nchange, it seems simple enough to add it to the list.\n"},{"id":"462877","messageId":"xmqqh71gla27.fsf@gitster.g","threadId":"58226","inReplyTo":"d0d0836c-9d2f-53fe-dda1-a8c61e3acd9f@github.com","subject":"Re: [PATCH v3 07/11] log: add default decoration filter","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-09-09T17:41:36Z","receivedAt":"2022-09-09T17:41:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Derrick Stolee <derrickstolee@github.com> writes:\n\n> The object names should be visible as part of the \"git log\" output\n> (perhaps abbreviated) and that provides a way to get that information\n> without needing an unabbreviated hash showing up in a decoration slot.\n\nOK.\n"}]}