{"thread":{"id":"65377","subject":"[PATCH v1 1/1] cat-file: add use-mailmap/no-use-mailmap to --batch-command","startedAt":"2026-03-28T20:36:22Z","lastAt":"2026-05-20T03:26:50Z","messageCount":28,"participants":["Siddharth Asthana","Junio C Hamano","Karthik Nayak","Patrick Steinhardt","Jean-Noël AVILA","Jean-Noël Avila"],"isPatch":true,"patchVersion":1,"patchTotal":1},"messages":[{"id":"540301","messageId":"20260328203615.60402-1-siddharthasthana31@gmail.com","threadId":"65377","inReplyTo":null,"subject":"[PATCH v1 1/1] cat-file: add use-mailmap/no-use-mailmap to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-03-28T20:36:15Z","receivedAt":"2026-03-28T20:36:22Z","isPatch":true,"body":"git-cat-file(1)'s --batch-command works with the --use-mailmap option,\nbut this option needs to be set when the process is created. This means\nwe cannot change this option mid-operation.\n\nAt GitLab, Gitaly caches git-cat-file processes and it would be useful\nif --batch-command supported toggling mailmap dynamically with existing\nprocesses.\n\nAdd `use-mailmap` and `no-use-mailmap` as new subcommands to\n--batch-command. `use-mailmap` enables the mailmap mechanism for\nsubsequent `contents` and `info` commands, lazily loading the mailmap\ndata from disk on first invocation. `no-use-mailmap` disables it but\nkeeps the data in memory so re-enabling doesn't require reloading.\n\nThe subcommand names mirror the existing --use-mailmap/--no-use-mailmap\nCLI options to keep the interface consistent.\n\nSigned-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n---\nCI: https://gitlab.com/gitlab-org/git/-/pipelines/2415084557\n\n Documentation/git-cat-file.adoc |  9 +++++++\n builtin/cat-file.c              | 33 ++++++++++++++++++++---\n t/t4203-mailmap.sh              | 48 +++++++++++++++++++++++++++++++++\n 3 files changed, 86 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc\nindex c139f55a16..03aadbbe89 100644\n--- a/Documentation/git-cat-file.adoc\n+++ b/Documentation/git-cat-file.adoc\n@@ -174,6 +174,15 @@ flush::\n \tsince the beginning or since the last flush was issued. When `--buffer`\n \tis used, no output will come until a `flush` is issued. When `--buffer`\n \tis not used, commands are flushed each time without issuing `flush`.\n+\n+use-mailmap::\n+\tEnable mailmap for subsequent `contents` and `info` commands. If the\n+\tmailmap has not been loaded yet, it is read from disk at this point.\n+\n+no-use-mailmap::\n+\tDisable mailmap for subsequent `contents` and `info` commands. The\n+\tmailmap data is kept in memory so that a later `use-mailmap` command\n+\tdoes not need to reload it from disk.\n --\n +\n \ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex b6f12f41d6..7772d4d41b 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -54,6 +54,7 @@ static const char *force_path;\n \n static struct string_list mailmap = STRING_LIST_INIT_NODUP;\n static int use_mailmap;\n+static int mailmap_loaded;\n \n static char *replace_idents_using_mailmap(char *, size_t *);\n \n@@ -692,6 +693,26 @@ static void parse_cmd_info(struct batch_options *opt,\n \tbatch_one_object(line, output, opt, data);\n }\n \n+static void parse_cmd_use_mailmap(struct batch_options *opt UNUSED,\n+\t\t\t\t  const char *line UNUSED,\n+\t\t\t\t  struct strbuf *output UNUSED,\n+\t\t\t\t  struct expand_data *data UNUSED)\n+{\n+\tif (!mailmap_loaded) {\n+\t\tread_mailmap(the_repository, &mailmap);\n+\t\tmailmap_loaded = 1;\n+\t}\n+\tuse_mailmap = 1;\n+}\n+\n+static void parse_cmd_disable_mailmap(struct batch_options *opt UNUSED,\n+\t\t\t\t      const char *line UNUSED,\n+\t\t\t\t      struct strbuf *output UNUSED,\n+\t\t\t\t      struct expand_data *data UNUSED)\n+{\n+\tuse_mailmap = 0;\n+}\n+\n static void dispatch_calls(struct batch_options *opt,\n \t\tstruct strbuf *output,\n \t\tstruct expand_data *data,\n@@ -725,9 +746,11 @@ static const struct parse_cmd {\n \tparse_cmd_fn_t fn;\n \tunsigned takes_args;\n } commands[] = {\n-\t{ \"contents\", parse_cmd_contents, 1},\n-\t{ \"info\", parse_cmd_info, 1},\n-\t{ \"flush\", NULL, 0},\n+\t{ \"contents\", parse_cmd_contents, 1 },\n+\t{ \"info\", parse_cmd_info, 1 },\n+\t{ \"flush\", NULL, 0 },\n+\t{ \"use-mailmap\", parse_cmd_use_mailmap, 0 },\n+\t{ \"no-use-mailmap\", parse_cmd_disable_mailmap, 0 },\n };\n \n static void batch_objects_command(struct batch_options *opt,\n@@ -1127,8 +1150,10 @@ int cmd_cat_file(int argc,\n \topt_cw = (opt == 'c' || opt == 'w');\n \topt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');\n \n-\tif (use_mailmap)\n+\tif (use_mailmap) {\n \t\tread_mailmap(the_repository, &mailmap);\n+\t\tmailmap_loaded = 1;\n+\t}\n \n \tswitch (batch.objects_filter.choice) {\n \tcase LOFC_DISABLED:\ndiff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh\nindex 74b7ddccb2..2ae063e5c3 100755\n--- a/t/t4203-mailmap.sh\n+++ b/t/t4203-mailmap.sh\n@@ -1133,6 +1133,54 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'git cat-file --batch-command use-mailmap enables mailmap mid-stream' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"info HEAD\\nuse-mailmap\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n+\techo $commit_sha commit $size_no_mailmap >expect &&\n+\techo $commit_sha commit $size_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command no-use-mailmap disables mailmap mid-stream' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"use-mailmap\\ninfo HEAD\\nno-use-mailmap\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command use-mailmap works in --buffer mode' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"use-mailmap\\ninfo HEAD\\nno-use-mailmap\\ninfo HEAD\\nflush\\n\" | git cat-file --batch-command --buffer >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'git cat-file --mailmap works with different author and committer' '\n \ttest_when_finished \"rm .mailmap\" &&\n \tcat >.mailmap <<-\\EOF &&\n-- \n2.51.0\n\n"},{"id":"540308","messageId":"xmqqldfbh32d.fsf@gitster.g","threadId":"65377","inReplyTo":"20260328203615.60402-1-siddharthasthana31@gmail.com","subject":"Re: [PATCH v1 1/1] cat-file: add use-mailmap/no-use-mailmap to --batch-command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-29T00:50:02Z","receivedAt":"2026-03-29T00:50:06Z","isPatch":true,"body":"Siddharth Asthana <siddharthasthana31@gmail.com> writes:\n\n> git-cat-file(1)'s --batch-command works with the --use-mailmap option,\n> but this option needs to be set when the process is created. This means\n> we cannot change this option mid-operation.\n>\n> At GitLab, Gitaly caches git-cat-file processes and it would be useful\n> if --batch-command supported toggling mailmap dynamically with existing\n> processes.\n>\n> Add `use-mailmap` and `no-use-mailmap` as new subcommands to\n> --batch-command. `use-mailmap` enables the mailmap mechanism for\n> subsequent `contents` and `info` commands, lazily loading the mailmap\n> data from disk on first invocation. `no-use-mailmap` disables it but\n> keeps the data in memory so re-enabling doesn't require reloading.\n\nAnd the cached information in process, if any, would be flushed?\n\nBecause in your design, these command words are parsed separately\nfrom and have nothing in common with the command line options, I\nwonder if it is easier to understand if you added just a single\ncommand, \"mailmap\", that takes a single parameter \"yes\" or \"no\"?\nThen this hunk would ...\n\n> +\t{ \"contents\", parse_cmd_contents, 1 },\n> +\t{ \"info\", parse_cmd_info, 1 },\n> +\t{ \"flush\", NULL, 0 },\n> +\t{ \"use-mailmap\", parse_cmd_use_mailmap, 0 },\n> +\t{ \"no-use-mailmap\", parse_cmd_disable_mailmap, 0 },\n\n... need only one addition instead of two entries and you do not\nhave to write boilerplate-rich helper functions twice.\n"},{"id":"540313","messageId":"a4ec7bfa-f16b-4505-9b37-d3dd137e93cb@gmail.com","threadId":"65377","inReplyTo":"xmqqldfbh32d.fsf@gitster.g","subject":"Re: [PATCH v1 1/1] cat-file: add use-mailmap/no-use-mailmap to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-03-29T07:25:24Z","receivedAt":"2026-03-29T07:25:29Z","isPatch":true,"body":"\n\nOn 29/03/26 06:20, Junio C Hamano wrote:\n> Siddharth Asthana <siddharthasthana31@gmail.com> writes:\n> \n>> git-cat-file(1)'s --batch-command works with the --use-mailmap option,\n>> but this option needs to be set when the process is created. This means\n>> we cannot change this option mid-operation.\n>>\n>> At GitLab, Gitaly caches git-cat-file processes and it would be useful\n>> if --batch-command supported toggling mailmap dynamically with existing\n>> processes.\n>>\n>> Add `use-mailmap` and `no-use-mailmap` as new subcommands to\n>> --batch-command. `use-mailmap` enables the mailmap mechanism for\n>> subsequent `contents` and `info` commands, lazily loading the mailmap\n>> data from disk on first invocation. `no-use-mailmap` disables it but\n>> keeps the data in memory so re-enabling doesn't require reloading.\n> \n> And the cached information in process, if any, would be flushed?\n\n\nNo. The mailmap data is kept in memory. Turning it off only disables \napplication of mailmap; turning it back on reuses already loaded data.\n\n> \n> Because in your design, these command words are parsed separately\n> from and have nothing in common with the command line options, I\n> wonder if it is easier to understand if you added just a single\n> command, \"mailmap\", that takes a single parameter \"yes\" or \"no\"?\n\n\nAgreed, this is cleaner.\n\nI will rerolled this as a single `mailmap` subcommand with `yes|no`, so \nthe dispatch table has one entry and the handling is in one function\n\nI'll send v2 with this update.\n\n\nThanks,\nSiddharth\n\n\n> Then this hunk would ...\n> \n>> +\t{ \"contents\", parse_cmd_contents, 1 },\n>> +\t{ \"info\", parse_cmd_info, 1 },\n>> +\t{ \"flush\", NULL, 0 },\n>> +\t{ \"use-mailmap\", parse_cmd_use_mailmap, 0 },\n>> +\t{ \"no-use-mailmap\", parse_cmd_disable_mailmap, 0 },\n> \n> ... need only one addition instead of two entries and you do not\n> have to write boilerplate-rich helper functions twice.\n\n"},{"id":"540314","messageId":"20260329082808.12609-1-siddharthasthana31@gmail.com","threadId":"65377","inReplyTo":"20260328203615.60402-1-siddharthasthana31@gmail.com","subject":"[PATCH v2 0/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-03-29T08:28:07Z","receivedAt":"2026-03-29T08:28:13Z","isPatch":true,"body":"git-cat-file(1)'s --batch-command works with the --use-mailmap option,\nbut this option needs to be set when the process is created. This means\nwe cannot change this option mid-operation.\n\nAt GitLab, Gitaly caches git-cat-file processes and it would be useful\nif --batch-command supported toggling mailmap dynamically with existing\nprocesses.\n\nThis patch adds a `mailmap` subcommand to --batch-command that takes\n`yes` or `no` as its argument. When enabled, mailmap data is loaded from\ndisk on first use and kept in memory so that toggling back on does not\nrequire reloading.\n\nThe series is based on top of 5361983c07 (The 22nd batch, 2026-03-21).\n\nCI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861\n\nChanges in v2:\n- Replace two separate `use-mailmap` / `no-use-mailmap` zero-argument\n  subcommands with a single `mailmap` subcommand that takes `yes` or\n  `no` as its argument. This reduces the dispatch\n  table to one entry and the implementation to one function.\n- Link to v1: https://public-inbox.org/git/a4ec7bfa-f16b-4505-9b37-d3dd137e93cb@gmail.com/T/#m5c62fb6ad0fbcc99a706dba4c78b66359c247acd\n\nThanks,\nSiddharth\n\n---\nSiddharth Asthana (1):\n  cat-file: add mailmap subcommand to --batch-command\n\n Documentation/git-cat-file.adoc |  7 +++++\n builtin/cat-file.c              | 30 ++++++++++++++++++---\n t/t4203-mailmap.sh              | 48 +++++++++++++++++++++++++++++++++\n 3 files changed, 81 insertions(+), 4 deletions(-)\n\nRange-diff versus v1:\n\n1:  39f40e9cb7 ! 1:  936ca27419 cat-file: add use-mailmap/no-use-mailmap to --batch-command\n    @@ Metadata\n      Author: Siddharth Asthana <siddharthasthana31@gmail.com>\n\n       ## Commit message ##\n    -    cat-file: add use-mailmap/no-use-mailmap to --batch-command\n    +    cat-file: add mailmap subcommand to --batch-command\n\n         git-cat-file(1)'s --batch-command works with the --use-mailmap option,\n         but this option needs to be set when the process is created. This means\n    @@ Commit message\n         if --batch-command supported toggling mailmap dynamically with existing\n         processes.\n\n    -    Add `use-mailmap` and `no-use-mailmap` as new subcommands to\n    -    --batch-command. `use-mailmap` enables the mailmap mechanism for\n    -    subsequent `contents` and `info` commands, lazily loading the mailmap\n    -    data from disk on first invocation. `no-use-mailmap` disables it but\n    -    keeps the data in memory so re-enabling doesn't require reloading.\n    -\n    -    The subcommand names mirror the existing --use-mailmap/--no-use-mailmap\n    -    CLI options to keep the interface consistent.\n    +    Add a `mailmap` subcommand to --batch-command that takes a single\n    +    argument: `yes` to enable mailmap and `no` to disable it. When enabled,\n    +    mailmap data is loaded from disk on first use and kept in memory so that\n    +    toggling back on does not require reloading.\n\n    +    Suggested-by: Junio C Hamano <gitster@pobox.com>\n         Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n\n    @@ Documentation/git-cat-file.adoc: flush::\n      \tis used, no output will come until a `flush` is issued. When `--buffer`\n      \tis not used, commands are flushed each time without issuing `flush`.\n     +\n    -+use-mailmap::\n    -+\tEnable mailmap for subsequent `contents` and `info` commands. If the\n    -+\tmailmap has not been loaded yet, it is read from disk at this point.\n    -+\n    -+no-use-mailmap::\n    -+\tDisable mailmap for subsequent `contents` and `info` commands. The\n    -+\tmailmap data is kept in memory so that a later `use-mailmap` command\n    -+\tdoes not need to reload it from disk.\n    ++mailmap <yes|no>::\n    ++\tEnable or disable mailmap for subsequent `contents` and `info`\n    ++\tcommands. When `yes` is given, mailmap data is loaded from disk on\n    ++\tfirst use and kept in memory; passing `yes` again does not reload it.\n    ++\tWhen `no` is given, mailmap is disabled but the data stays in memory\n    ++\tso that a later `mailmap yes` does not need to reload it from disk.\n      --\n\n    @@ builtin/cat-file.c: static void parse_cmd_info(struct batch_options *opt,\n      \tbatch_one_object(line, output, opt, data);\n      }\n\n    -+static void parse_cmd_use_mailmap(struct batch_options *opt UNUSED,\n    -+\t\t\t\t  const char *line UNUSED,\n    -+\t\t\t\t  struct strbuf *output UNUSED,\n    -+\t\t\t\t  struct expand_data *data UNUSED)\n    ++static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n    ++\t\t\t      const char *line,\n    ++\t\t\t      struct strbuf *output UNUSED,\n    ++\t\t\t      struct expand_data *data UNUSED)\n     +{\n    -+\tif (!mailmap_loaded) {\n    -+\t\tread_mailmap(the_repository, &mailmap);\n    -+\t\tmailmap_loaded = 1;\n    ++\tif (!strcmp(line, \"yes\")) {\n    ++\t\tif (!mailmap_loaded) {\n    ++\t\t\tread_mailmap(the_repository, &mailmap);\n    ++\t\t\tmailmap_loaded = 1;\n    ++\t\t}\n    ++\t\tuse_mailmap = 1;\n    ++\t} else if (!strcmp(line, \"no\")) {\n    ++\t\tuse_mailmap = 0;\n    ++\t} else {\n    ++\t\tdie(_(\"mailmap: unknown argument '%s', expected 'yes' or 'no'\"), line);\n     +\t}\n    -+\tuse_mailmap = 1;\n    -+}\n    -+\n    -+static void parse_cmd_disable_mailmap(struct batch_options *opt UNUSED,\n    -+\t\t\t\t      const char *line UNUSED,\n    -+\t\t\t\t      struct strbuf *output UNUSED,\n    -+\t\t\t\t      struct expand_data *data UNUSED)\n    -+{\n    -+\tuse_mailmap = 0;\n     +}\n\n    @@ builtin/cat-file.c: static const struct parse_cmd {\n     +\t{ \"contents\", parse_cmd_contents, 1 },\n     +\t{ \"info\", parse_cmd_info, 1 },\n     +\t{ \"flush\", NULL, 0 },\n    -+\t{ \"use-mailmap\", parse_cmd_use_mailmap, 0 },\n    -+\t{ \"no-use-mailmap\", parse_cmd_disable_mailmap, 0 },\n    ++\t{ \"mailmap\", parse_cmd_mailmap, 1 },\n      };\n\n    @@ t/t4203-mailmap.sh: test_expect_success 'git cat-file --batch-command returns co\n     -+test_expect_success 'git cat-file --batch-command use-mailmap enables mailmap mid-stream' '\n     ++test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' '\n     +\t...\n     -+\tprintf \"info HEAD\\nuse-mailmap\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n     ++\tprintf \"info HEAD\\nmailmap yes\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n\n     -+test_expect_success 'git cat-file --batch-command no-use-mailmap disables mailmap mid-stream' '\n     ++test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' '\n     +\t...\n     -+\tprintf \"use-mailmap\\ninfo HEAD\\nno-use-mailmap\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n     ++\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n\n     -+test_expect_success 'git cat-file --batch-command use-mailmap works in --buffer mode' '\n     ++test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' '\n     +\t...\n     -+\tprintf \"use-mailmap\\ninfo HEAD\\nno-use-mailmap\\ninfo HEAD\\nflush\\n\" | git cat-file --batch-command --buffer >actual &&\n     ++\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\nflush\\n\" | git cat-file --batch-command --buffer >actual &&\n\nbase-commit: 5361983c075154725be47b65cca9a2421789e410\n-- \n2.51.0\n\n"},{"id":"540315","messageId":"20260329082808.12609-2-siddharthasthana31@gmail.com","threadId":"65377","inReplyTo":"20260329082808.12609-1-siddharthasthana31@gmail.com","subject":"[PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-03-29T08:28:08Z","receivedAt":"2026-03-29T08:28:18Z","isPatch":true,"body":"git-cat-file(1)'s --batch-command works with the --use-mailmap option,\nbut this option needs to be set when the process is created. This means\nwe cannot change this option mid-operation.\n\nAt GitLab, Gitaly caches git-cat-file processes and it would be useful\nif --batch-command supported toggling mailmap dynamically with existing\nprocesses.\n\nAdd a `mailmap` subcommand to --batch-command that takes a single\nargument: `yes` to enable mailmap and `no` to disable it. When enabled,\nmailmap data is loaded from disk on first use and kept in memory so that\ntoggling back on does not require reloading.\n\nSuggested-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n---\nCI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861\n\n Documentation/git-cat-file.adoc |  7 +++++\n builtin/cat-file.c              | 30 ++++++++++++++++++---\n t/t4203-mailmap.sh              | 48 +++++++++++++++++++++++++++++++++\n 3 files changed, 81 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc\nindex c139f55a16..af32e929a8 100644\n--- a/Documentation/git-cat-file.adoc\n+++ b/Documentation/git-cat-file.adoc\n@@ -174,6 +174,13 @@ flush::\n \tsince the beginning or since the last flush was issued. When `--buffer`\n \tis used, no output will come until a `flush` is issued. When `--buffer`\n \tis not used, commands are flushed each time without issuing `flush`.\n+\n+mailmap <yes|no>::\n+\tEnable or disable mailmap for subsequent `contents` and `info`\n+\tcommands. When `yes` is given, mailmap data is loaded from disk on\n+\tfirst use and kept in memory; passing `yes` again does not reload it.\n+\tWhen `no` is given, mailmap is disabled but the data stays in memory\n+\tso that a later `mailmap yes` does not need to reload it from disk.\n --\n +\n \ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex b6f12f41d6..a53926d2bb 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -54,6 +54,7 @@ static const char *force_path;\n \n static struct string_list mailmap = STRING_LIST_INIT_NODUP;\n static int use_mailmap;\n+static int mailmap_loaded;\n \n static char *replace_idents_using_mailmap(char *, size_t *);\n \n@@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt,\n \tbatch_one_object(line, output, opt, data);\n }\n \n+static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n+\t\t\t      const char *line,\n+\t\t\t      struct strbuf *output UNUSED,\n+\t\t\t      struct expand_data *data UNUSED)\n+{\n+\tif (!strcmp(line, \"yes\")) {\n+\t\tif (!mailmap_loaded) {\n+\t\t\tread_mailmap(the_repository, &mailmap);\n+\t\t\tmailmap_loaded = 1;\n+\t\t}\n+\t\tuse_mailmap = 1;\n+\t} else if (!strcmp(line, \"no\")) {\n+\t\tuse_mailmap = 0;\n+\t} else {\n+\t\tdie(_(\"mailmap: unknown argument '%s', expected 'yes' or 'no'\"), line);\n+\t}\n+}\n+\n static void dispatch_calls(struct batch_options *opt,\n \t\tstruct strbuf *output,\n \t\tstruct expand_data *data,\n@@ -725,9 +744,10 @@ static const struct parse_cmd {\n \tparse_cmd_fn_t fn;\n \tunsigned takes_args;\n } commands[] = {\n-\t{ \"contents\", parse_cmd_contents, 1},\n-\t{ \"info\", parse_cmd_info, 1},\n-\t{ \"flush\", NULL, 0},\n+\t{ \"contents\", parse_cmd_contents, 1 },\n+\t{ \"info\", parse_cmd_info, 1 },\n+\t{ \"flush\", NULL, 0 },\n+\t{ \"mailmap\", parse_cmd_mailmap, 1 },\n };\n \n static void batch_objects_command(struct batch_options *opt,\n@@ -1127,8 +1147,10 @@ int cmd_cat_file(int argc,\n \topt_cw = (opt == 'c' || opt == 'w');\n \topt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');\n \n-\tif (use_mailmap)\n+\tif (use_mailmap) {\n \t\tread_mailmap(the_repository, &mailmap);\n+\t\tmailmap_loaded = 1;\n+\t}\n \n \tswitch (batch.objects_filter.choice) {\n \tcase LOFC_DISABLED:\ndiff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh\nindex 74b7ddccb2..f66637cd86 100755\n--- a/t/t4203-mailmap.sh\n+++ b/t/t4203-mailmap.sh\n@@ -1133,6 +1133,54 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"info HEAD\\nmailmap yes\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n+\techo $commit_sha commit $size_no_mailmap >expect &&\n+\techo $commit_sha commit $size_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\nflush\\n\" | git cat-file --batch-command --buffer >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'git cat-file --mailmap works with different author and committer' '\n \ttest_when_finished \"rm .mailmap\" &&\n \tcat >.mailmap <<-\\EOF &&\n-- \n2.51.0\n\n"},{"id":"540335","messageId":"xmqqh5pygxu4.fsf@gitster.g","threadId":"65377","inReplyTo":"a4ec7bfa-f16b-4505-9b37-d3dd137e93cb@gmail.com","subject":"Re: [PATCH v1 1/1] cat-file: add use-mailmap/no-use-mailmap to --batch-command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-29T20:55:15Z","receivedAt":"2026-03-29T20:55:18Z","isPatch":true,"body":"Siddharth Asthana <siddharthasthana31@gmail.com> writes:\n\n>> And the cached information in process, if any, would be flushed?\n>\n> No. The mailmap data is kept in memory. Turning it off only disables \n> application of mailmap; turning it back on reuses already loaded data.\n\nI was asking if the rewritten commmit objects were kept around in\nmemory and how long; after you show an object once with mapped\nauthor data, toggled the mailmap use, and then try to show the same\nobject again, you would want to avoid reusing the mapped result\nagain.\n\nBut it turns out that the command, with or without your patch, reads\nthe object data and maps the author/commit in it every time an\nobject is requested.  In fact, in a bad case, I think it calls\nreplace_idents_using_mailmap() twice, once in batch_object_write()\nonly to grab the size of the munged object, then again in\nprint_object_or_die() for both contents and the size.\n\nSo there is no \"tainted data retained across the mode switch\"\nproblem.\n"},{"id":"540353","messageId":"xmqqtstyf4lj.fsf@gitster.g","threadId":"65377","inReplyTo":"20260329082808.12609-2-siddharthasthana31@gmail.com","subject":"Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-30T02:12:08Z","receivedAt":"2026-03-30T02:12:13Z","isPatch":true,"body":"Siddharth Asthana <siddharthasthana31@gmail.com> writes:\n\n> git-cat-file(1)'s --batch-command works with the --use-mailmap option,\n> but this option needs to be set when the process is created. This means\n> we cannot change this option mid-operation.\n>\n> At GitLab, Gitaly caches git-cat-file processes and it would be useful\n\nWould \"keeps interacting with a single 'cat-file' process\" be more\naccurate than \"caches\"?  The latter gives, at least to me,\nconnotations that may not be necessarily true, like (1) there is a\npool of cat-file processes waiting for Gitaly to connect and serve,\n(2) a running Gitaly may decide to disconnect from cat-file from\ntime to time, and then reconnect to one of them when it becomes\nnecessary again, etc.\n\n> if --batch-command supported toggling mailmap dynamically with existing\n> processes.\n>\n> Add a `mailmap` subcommand to --batch-command that takes a single\n> argument: `yes` to enable mailmap and `no` to disable it. When enabled,\n> mailmap data is loaded from disk on first use and kept in memory so that\n> toggling back on does not require reloading.\n>\n> Suggested-by: Junio C Hamano <gitster@pobox.com>\n\nThis is over-crediting me.  The idea to unify the two commands into\none may have come from me, but that is at most helped-by but it is\nperfectly fine without any credit.\n\n> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n> ---\n\n> diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n> index b6f12f41d6..a53926d2bb 100644\n> --- a/builtin/cat-file.c\n> +++ b/builtin/cat-file.c\n> @@ -54,6 +54,7 @@ static const char *force_path;\n>  \n>  static struct string_list mailmap = STRING_LIST_INIT_NODUP;\n>  static int use_mailmap;\n> +static int mailmap_loaded;\n\nNot part of this topic, but in case less experienced developers who\nare watching from the sidelines wonder if we want to add this\nfile-scope global variable, this is perfectly fine.  Anything under\nbuiltin/foo.c are meant to serve a single command \"git foo\" and does\nnot benefit from \"let's sift globals into classes that belong to\ndifferent concepts in the system; most of which will be per\nrepository, so make them some part of the repository object\"\nmovement as much as more library-ish parts of the system.\n\nUntil a specific command starts working on multiple repositories at\none time, that is.\n\n\n> @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt,\n>  \tbatch_one_object(line, output, opt, data);\n>  }\n>  \n> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n> +\t\t\t      const char *line,\n> +\t\t\t      struct strbuf *output UNUSED,\n> +\t\t\t      struct expand_data *data UNUSED)\n> +{\n> +\tif (!strcmp(line, \"yes\")) {\n> +\t\tif (!mailmap_loaded) {\n> +\t\t\tread_mailmap(the_repository, &mailmap);\n> +\t\t\tmailmap_loaded = 1;\n> +\t\t}\n> +\t\tuse_mailmap = 1;\n> +\t} else if (!strcmp(line, \"no\")) {\n> +\t\tuse_mailmap = 0;\n> +\t} else {\n> +\t\tdie(_(\"mailmap: unknown argument '%s', expected 'yes' or 'no'\"), line);\n> +\t}\n> +}\n\nOK.\n\n> @@ -725,9 +744,10 @@ static const struct parse_cmd {\n>  \tparse_cmd_fn_t fn;\n>  \tunsigned takes_args;\n>  } commands[] = {\n> -\t{ \"contents\", parse_cmd_contents, 1},\n> -\t{ \"info\", parse_cmd_info, 1},\n> -\t{ \"flush\", NULL, 0},\n> +\t{ \"contents\", parse_cmd_contents, 1 },\n> +\t{ \"info\", parse_cmd_info, 1 },\n> +\t{ \"flush\", NULL, 0 },\n> +\t{ \"mailmap\", parse_cmd_mailmap, 1 },\n>  };\n\nMixing style fixes to existing entries in the same patch that adds a\nnew feature by adding a new entry to the table is annoying than\nhaving a preliminary clean-up patch that only fixes style and then\nthe main patch that adds the feature.\n\n>  static void batch_objects_command(struct batch_options *opt,\n> @@ -1127,8 +1147,10 @@ int cmd_cat_file(int argc,\n>  \topt_cw = (opt == 'c' || opt == 'w');\n>  \topt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');\n>  \n> -\tif (use_mailmap)\n> +\tif (use_mailmap) {\n>  \t\tread_mailmap(the_repository, &mailmap);\n> +\t\tmailmap_loaded = 1;\n> +\t}\n\nHmph, interesting.  Two points.\n\n * It would make it easier to follow if these two lines are made\n   into a small helper function to be called from here and from the\n   \"parse_cmd_mailmap()\"?\n\n * Can we somehow make mailmap object itself slightly smarter so\n   that it knows if it has already been asked to read the data from\n   its sources?  It is a pretty dumb string_list, but from a cursory\n   read of the code flow, it seems that mailmap.strdup_strings is\n   initialized to be false in builtin/cat-file.c and then one of the\n   first things done in mailmap.c::read_mailmap() is to flip that\n   bit on, so the \"yes\" part of the parse_cmd_mailmap() might become\n\n\tif (yes)\n\t\tload_mailmap();\n\n   with the helper load_mailmap() that may look like:\n\n\tstatic void load_mailmap(void)\n\t{\n\t\tif (mailmap.strdup_strings)\n\t\t\treturn; /* we know read_mailmap() flips it on */\n\t\tread_mailmap(the_repository, &mailmap);\n\t}\n\n   The first bullet point to introduce a small common helper will\n   help hiding such an ugly implementation detail there.\n"},{"id":"540357","messageId":"CAOLa=ZTqk3rG21e5H5HLDCw6MWK2ndgi=4pC0ZUWn98z39SSEQ@mail.gmail.com","threadId":"65377","inReplyTo":"20260329082808.12609-2-siddharthasthana31@gmail.com","subject":"Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Karthik Nayak","fromEmail":"karthik.188@gmail.com","sentAt":"2026-03-30T09:44:01Z","receivedAt":"2026-03-30T09:44:03Z","isPatch":true,"body":"Siddharth Asthana <siddharthasthana31@gmail.com> writes:\n\n> git-cat-file(1)'s --batch-command works with the --use-mailmap option,\n> but this option needs to be set when the process is created. This means\n> we cannot change this option mid-operation.\n>\n> At GitLab, Gitaly caches git-cat-file processes and it would be useful\n> if --batch-command supported toggling mailmap dynamically with existing\n> processes.\n>\n> Add a `mailmap` subcommand to --batch-command that takes a single\n> argument: `yes` to enable mailmap and `no` to disable it. When enabled,\n> mailmap data is loaded from disk on first use and kept in memory so that\n> toggling back on does not require reloading.\n>\n> Suggested-by: Junio C Hamano <gitster@pobox.com>\n> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n> ---\n> CI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861\n>\n>  Documentation/git-cat-file.adoc |  7 +++++\n>  builtin/cat-file.c              | 30 ++++++++++++++++++---\n>  t/t4203-mailmap.sh              | 48 +++++++++++++++++++++++++++++++++\n>  3 files changed, 81 insertions(+), 4 deletions(-)\n>\n> diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc\n> index c139f55a16..af32e929a8 100644\n> --- a/Documentation/git-cat-file.adoc\n> +++ b/Documentation/git-cat-file.adoc\n> @@ -174,6 +174,13 @@ flush::\n>  \tsince the beginning or since the last flush was issued. When `--buffer`\n>  \tis used, no output will come until a `flush` is issued. When `--buffer`\n>  \tis not used, commands are flushed each time without issuing `flush`.\n> +\n> +mailmap <yes|no>::\n> +\tEnable or disable mailmap for subsequent `contents` and `info`\n> +\tcommands. When `yes` is given, mailmap data is loaded from disk on\n\nAre there any commands that the mailmap wouldn't apply to? Would it make\nsense to simply say\n\n      Enable or disable mailmap for subsequent commands.\n\nalso we can s/is given//.\n\n> +\tfirst use and kept in memory; passing `yes` again does not reload it.\n> +\tWhen `no` is given, mailmap is disabled but the data stays in memory\n> +\tso that a later `mailmap yes` does not need to reload it from disk.\n\nI think the first sentense here jumps directly into the the caching\nmechanism on using `yes`. It's more important for users to know what\n`yes` implies. So perhaps:\n\n    When `yes` mailmap data is used and disabled on `no`. The first\n    `yes` caches the mailmap data until the command exits.\n\n>  --\n>  +\n>\n> diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n> index b6f12f41d6..a53926d2bb 100644\n> --- a/builtin/cat-file.c\n> +++ b/builtin/cat-file.c\n> @@ -54,6 +54,7 @@ static const char *force_path;\n>\n>  static struct string_list mailmap = STRING_LIST_INIT_NODUP;\n>  static int use_mailmap;\n> +static int mailmap_loaded;\n>\n\nNit: should we use a 'bool' here?\n\nSo we use a variable and not simple rely on checking `mailmap.nr`\nbecause it is possible that we do load the mailmap but there are no\nentries. I assume we could rely on `maimap.cmp` being non-NULL, but\nthat's getting into implementation details.\n\n>  static char *replace_idents_using_mailmap(char *, size_t *);\n>\n> @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt,\n>  \tbatch_one_object(line, output, opt, data);\n>  }\n>\n> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n> +\t\t\t      const char *line,\n> +\t\t\t      struct strbuf *output UNUSED,\n> +\t\t\t      struct expand_data *data UNUSED)\n> +{\n> +\tif (!strcmp(line, \"yes\")) {\n> +\t\tif (!mailmap_loaded) {\n> +\t\t\tread_mailmap(the_repository, &mailmap);\n> +\t\t\tmailmap_loaded = 1;\n> +\t\t}\n> +\t\tuse_mailmap = 1;\n> +\t} else if (!strcmp(line, \"no\")) {\n> +\t\tuse_mailmap = 0;\n> +\t} else {\n> +\t\tdie(_(\"mailmap: unknown argument '%s', expected 'yes' or 'no'\"), line);\n> +\t}\n> +}\n> +\n>  static void dispatch_calls(struct batch_options *opt,\n>  \t\tstruct strbuf *output,\n>  \t\tstruct expand_data *data,\n> @@ -725,9 +744,10 @@ static const struct parse_cmd {\n>  \tparse_cmd_fn_t fn;\n>  \tunsigned takes_args;\n>  } commands[] = {\n> -\t{ \"contents\", parse_cmd_contents, 1},\n> -\t{ \"info\", parse_cmd_info, 1},\n> -\t{ \"flush\", NULL, 0},\n> +\t{ \"contents\", parse_cmd_contents, 1 },\n> +\t{ \"info\", parse_cmd_info, 1 },\n> +\t{ \"flush\", NULL, 0 },\n> +\t{ \"mailmap\", parse_cmd_mailmap, 1 },\n>  };\n>\n>  static void batch_objects_command(struct batch_options *opt,\n> @@ -1127,8 +1147,10 @@ int cmd_cat_file(int argc,\n>  \topt_cw = (opt == 'c' || opt == 'w');\n>  \topt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');\n>\n> -\tif (use_mailmap)\n> +\tif (use_mailmap) {\n>  \t\tread_mailmap(the_repository, &mailmap);\n> +\t\tmailmap_loaded = 1;\n> +\t}\n>\n\nThe rest of the code looks good.\n\n>  \tswitch (batch.objects_filter.choice) {\n>  \tcase LOFC_DISABLED:\n> diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh\n> index 74b7ddccb2..f66637cd86 100755\n> --- a/t/t4203-mailmap.sh\n> +++ b/t/t4203-mailmap.sh\n> @@ -1133,6 +1133,54 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us\n>  \ttest_cmp expect actual\n>  '\n>\n> +test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' '\n> +\ttest_when_finished \"rm .mailmap\" &&\n> +\tcat >.mailmap <<-\\EOF &&\n> +\tC O Mitter <committer@example.com> Orig <orig@example.com>\n> +\tEOF\n> +\tcommit_sha=$(git rev-parse HEAD) &&\n> +\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n> +\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n> +\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n> +\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n> +\tprintf \"info HEAD\\nmailmap yes\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n> +\techo $commit_sha commit $size_no_mailmap >expect &&\n> +\techo $commit_sha commit $size_mailmap >>expect &&\n> +\ttest_cmp expect actual\n> +'\n> +\n> +test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' '\n> +\ttest_when_finished \"rm .mailmap\" &&\n> +\tcat >.mailmap <<-\\EOF &&\n> +\tC O Mitter <committer@example.com> Orig <orig@example.com>\n> +\tEOF\n> +\tcommit_sha=$(git rev-parse HEAD) &&\n> +\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n> +\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n> +\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n> +\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n> +\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n> +\techo $commit_sha commit $size_mailmap >expect &&\n> +\techo $commit_sha commit $size_no_mailmap >>expect &&\n> +\ttest_cmp expect actual\n> +'\n> +\n> +test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' '\n> +\ttest_when_finished \"rm .mailmap\" &&\n> +\tcat >.mailmap <<-\\EOF &&\n> +\tC O Mitter <committer@example.com> Orig <orig@example.com>\n> +\tEOF\n> +\tcommit_sha=$(git rev-parse HEAD) &&\n> +\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n> +\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n> +\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n> +\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n> +\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\nflush\\n\" | git cat-file --batch-command --buffer >actual &&\n> +\techo $commit_sha commit $size_mailmap >expect &&\n> +\techo $commit_sha commit $size_no_mailmap >>expect &&\n> +\ttest_cmp expect actual\n> +'\n\nShouldn't we also add tests for how this interacts with '--mailmap' and\n'--no-mailmap'?\n\n>  test_expect_success 'git cat-file --mailmap works with different author and committer' '\n>  \ttest_when_finished \"rm .mailmap\" &&\n>  \tcat >.mailmap <<-\\EOF &&\n> --\n> 2.51.0\n"},{"id":"540361","messageId":"acpSgZ8RgBIE-h1Q@pks.im","threadId":"65377","inReplyTo":"20260329082808.12609-2-siddharthasthana31@gmail.com","subject":"Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-03-30T10:37:53Z","receivedAt":"2026-03-30T10:38:01Z","isPatch":true,"body":"On Sun, Mar 29, 2026 at 01:58:08PM +0530, Siddharth Asthana wrote:\n> diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n> index b6f12f41d6..a53926d2bb 100644\n> --- a/builtin/cat-file.c\n> +++ b/builtin/cat-file.c\n> @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt,\n>  \tbatch_one_object(line, output, opt, data);\n>  }\n>  \n> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n> +\t\t\t      const char *line,\n> +\t\t\t      struct strbuf *output UNUSED,\n> +\t\t\t      struct expand_data *data UNUSED)\n> +{\n> +\tif (!strcmp(line, \"yes\")) {\n> +\t\tif (!mailmap_loaded) {\n> +\t\t\tread_mailmap(the_repository, &mailmap);\n> +\t\t\tmailmap_loaded = 1;\n> +\t\t}\n> +\t\tuse_mailmap = 1;\n> +\t} else if (!strcmp(line, \"no\")) {\n> +\t\tuse_mailmap = 0;\n> +\t} else {\n> +\t\tdie(_(\"mailmap: unknown argument '%s', expected 'yes' or 'no'\"), line);\n> +\t}\n> +}\n\nNot commenting on the overall chanegchange, but I guess we should use\n`git_parse_maybe_bool()` here?\n\nPatrick\n"},{"id":"540389","messageId":"xmqqpl4lfjw8.fsf@gitster.g","threadId":"65377","inReplyTo":"acpSgZ8RgBIE-h1Q@pks.im","subject":"Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-30T14:53:59Z","receivedAt":"2026-03-30T14:54:02Z","isPatch":true,"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> On Sun, Mar 29, 2026 at 01:58:08PM +0530, Siddharth Asthana wrote:\n>> diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n>> index b6f12f41d6..a53926d2bb 100644\n>> --- a/builtin/cat-file.c\n>> +++ b/builtin/cat-file.c\n>> @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt,\n>>  \tbatch_one_object(line, output, opt, data);\n>>  }\n>>  \n>> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n>> +\t\t\t      const char *line,\n>> +\t\t\t      struct strbuf *output UNUSED,\n>> +\t\t\t      struct expand_data *data UNUSED)\n>> +{\n>> +\tif (!strcmp(line, \"yes\")) {\n>> +\t\tif (!mailmap_loaded) {\n>> +\t\t\tread_mailmap(the_repository, &mailmap);\n>> +\t\t\tmailmap_loaded = 1;\n>> +\t\t}\n>> +\t\tuse_mailmap = 1;\n>> +\t} else if (!strcmp(line, \"no\")) {\n>> +\t\tuse_mailmap = 0;\n>> +\t} else {\n>> +\t\tdie(_(\"mailmap: unknown argument '%s', expected 'yes' or 'no'\"), line);\n>> +\t}\n>> +}\n>\n> Not commenting on the overall chanegchange, but I guess we should use\n> `git_parse_maybe_bool()` here?\n\nThe saame thought occureed to me.  Also I agree with Karthik that we\nshould not say \"applies only to this and that commands\".\n\nThanks, all.\n"},{"id":"540450","messageId":"72543649-7994-4220-86fb-e3c84faf0b6a@gmail.com","threadId":"65377","inReplyTo":"xmqqtstyf4lj.fsf@gitster.g","subject":"Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-03-31T01:40:35Z","receivedAt":"2026-03-31T01:40:40Z","isPatch":true,"body":"\n\nOn 30/03/26 07:42, Junio C Hamano wrote:\n> Siddharth Asthana <siddharthasthana31@gmail.com> writes:\n> \n>> git-cat-file(1)'s --batch-command works with the --use-mailmap option,\n>> but this option needs to be set when the process is created. This means\n>> we cannot change this option mid-operation.\n>>\n>> At GitLab, Gitaly caches git-cat-file processes and it would be useful\n> \n> Would \"keeps interacting with a single 'cat-file' process\" be more\n> accurate than \"caches\"?  The latter gives, at least to me,\n\n\nThanks Junio\n\nMake sense, I will update that wording in v3!\n\n\n> connotations that may not be necessarily true, like (1) there is a\n> pool of cat-file processes waiting for Gitaly to connect and serve,\n> (2) a running Gitaly may decide to disconnect from cat-file from\n> time to time, and then reconnect to one of them when it becomes\n> necessary again, etc.\n> \n>> if --batch-command supported toggling mailmap dynamically with existing\n>> processes.\n>>\n>> Add a `mailmap` subcommand to --batch-command that takes a single\n>> argument: `yes` to enable mailmap and `no` to disable it. When enabled,\n>> mailmap data is loaded from disk on first use and kept in memory so that\n>> toggling back on does not require reloading.\n>>\n>> Suggested-by: Junio C Hamano <gitster@pobox.com>\n> \n> This is over-crediting me.  The idea to unify the two commands into\n> one may have come from me, but that is at most helped-by but it is\n> perfectly fine without any credit.\n\n\nGot it, thanks for pointing that out.\n\n\n> \n>> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n>> ---\n> \n>> diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n>> index b6f12f41d6..a53926d2bb 100644\n>> --- a/builtin/cat-file.c\n>> +++ b/builtin/cat-file.c\n>> @@ -54,6 +54,7 @@ static const char *force_path;\n>>   \n>>   static struct string_list mailmap = STRING_LIST_INIT_NODUP;\n>>   static int use_mailmap;\n>> +static int mailmap_loaded;\n> \n> Not part of this topic, but in case less experienced developers who\n> are watching from the sidelines wonder if we want to add this\n> file-scope global variable, this is perfectly fine.  Anything under\n> builtin/foo.c are meant to serve a single command \"git foo\" and does\n> not benefit from \"let's sift globals into classes that belong to\n> different concepts in the system; most of which will be per\n> repository, so make them some part of the repository object\"\n> movement as much as more library-ish parts of the system.\n> \n> Until a specific command starts working on multiple repositories at\n> one time, that is.\n> \n> \n>> @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt,\n>>   \tbatch_one_object(line, output, opt, data);\n>>   }\n>>   \n>> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n>> +\t\t\t      const char *line,\n>> +\t\t\t      struct strbuf *output UNUSED,\n>> +\t\t\t      struct expand_data *data UNUSED)\n>> +{\n>> +\tif (!strcmp(line, \"yes\")) {\n>> +\t\tif (!mailmap_loaded) {\n>> +\t\t\tread_mailmap(the_repository, &mailmap);\n>> +\t\t\tmailmap_loaded = 1;\n>> +\t\t}\n>> +\t\tuse_mailmap = 1;\n>> +\t} else if (!strcmp(line, \"no\")) {\n>> +\t\tuse_mailmap = 0;\n>> +\t} else {\n>> +\t\tdie(_(\"mailmap: unknown argument '%s', expected 'yes' or 'no'\"), line);\n>> +\t}\n>> +}\n> \n> OK.\n> \n>> @@ -725,9 +744,10 @@ static const struct parse_cmd {\n>>   \tparse_cmd_fn_t fn;\n>>   \tunsigned takes_args;\n>>   } commands[] = {\n>> -\t{ \"contents\", parse_cmd_contents, 1},\n>> -\t{ \"info\", parse_cmd_info, 1},\n>> -\t{ \"flush\", NULL, 0},\n>> +\t{ \"contents\", parse_cmd_contents, 1 },\n>> +\t{ \"info\", parse_cmd_info, 1 },\n>> +\t{ \"flush\", NULL, 0 },\n>> +\t{ \"mailmap\", parse_cmd_mailmap, 1 },\n>>   };\n> \n> Mixing style fixes to existing entries in the same patch that adds a\n> new feature by adding a new entry to the table is annoying than\n> having a preliminary clean-up patch that only fixes style and then\n> the main patch that adds the feature.\n\n\nAgreed. I will avoid mixing style-only cleanup with the feature change \nin v3.\n\n\n> \n>>   static void batch_objects_command(struct batch_options *opt,\n>> @@ -1127,8 +1147,10 @@ int cmd_cat_file(int argc,\n>>   \topt_cw = (opt == 'c' || opt == 'w');\n>>   \topt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');\n>>   \n>> -\tif (use_mailmap)\n>> +\tif (use_mailmap) {\n>>   \t\tread_mailmap(the_repository, &mailmap);\n>> +\t\tmailmap_loaded = 1;\n>> +\t}\n> \n> Hmph, interesting.  Two points.\n> \n>   * It would make it easier to follow if these two lines are made\n>     into a small helper function to be called from here and from the\n>     \"parse_cmd_mailmap()\"?\n> \n>   * Can we somehow make mailmap object itself slightly smarter so\n>     that it knows if it has already been asked to read the data from\n>     its sources?  It is a pretty dumb string_list, but from a cursory\n>     read of the code flow, it seems that mailmap.strdup_strings is\n>     initialized to be false in builtin/cat-file.c and then one of the\n>     first things done in mailmap.c::read_mailmap() is to flip that\n>     bit on, so the \"yes\" part of the parse_cmd_mailmap() might become\n> \n> \tif (yes)\n> \t\tload_mailmap();\n> \n>     with the helper load_mailmap() that may look like:\n> \n> \tstatic void load_mailmap(void)\n> \t{\n> \t\tif (mailmap.strdup_strings)\n> \t\t\treturn; /* we know read_mailmap() flips it on */\n> \t\tread_mailmap(the_repository, &mailmap);\n> \t}\n> \n>     The first bullet point to introduce a small common helper will\n>     help hiding such an ugly implementation detail there.\n\n\nThanks, this is helpful.\n\nI will introduce a small helper and call it from both places so the flow \nis easier to follow. I will also avoid publicating the load check in \neach callsite\n"},{"id":"540451","messageId":"49662ba7-3685-4745-8f23-7a9ba44c7966@gmail.com","threadId":"65377","inReplyTo":"CAOLa=ZTqk3rG21e5H5HLDCw6MWK2ndgi=4pC0ZUWn98z39SSEQ@mail.gmail.com","subject":"Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-03-31T01:42:36Z","receivedAt":"2026-03-31T01:42:41Z","isPatch":true,"body":"\n\nOn 30/03/26 15:14, Karthik Nayak wrote:\n> Siddharth Asthana <siddharthasthana31@gmail.com> writes:\n> \n>> git-cat-file(1)'s --batch-command works with the --use-mailmap option,\n>> but this option needs to be set when the process is created. This means\n>> we cannot change this option mid-operation.\n>>\n>> At GitLab, Gitaly caches git-cat-file processes and it would be useful\n>> if --batch-command supported toggling mailmap dynamically with existing\n>> processes.\n>>\n>> Add a `mailmap` subcommand to --batch-command that takes a single\n>> argument: `yes` to enable mailmap and `no` to disable it. When enabled,\n>> mailmap data is loaded from disk on first use and kept in memory so that\n>> toggling back on does not require reloading.\n>>\n>> Suggested-by: Junio C Hamano <gitster@pobox.com>\n>> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n>> ---\n>> CI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861\n>>\n>>   Documentation/git-cat-file.adoc |  7 +++++\n>>   builtin/cat-file.c              | 30 ++++++++++++++++++---\n>>   t/t4203-mailmap.sh              | 48 +++++++++++++++++++++++++++++++++\n>>   3 files changed, 81 insertions(+), 4 deletions(-)\n>>\n>> diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc\n>> index c139f55a16..af32e929a8 100644\n>> --- a/Documentation/git-cat-file.adoc\n>> +++ b/Documentation/git-cat-file.adoc\n>> @@ -174,6 +174,13 @@ flush::\n>>   \tsince the beginning or since the last flush was issued. When `--buffer`\n>>   \tis used, no output will come until a `flush` is issued. When `--buffer`\n>>   \tis not used, commands are flushed each time without issuing `flush`.\n>> +\n>> +mailmap <yes|no>::\n>> +\tEnable or disable mailmap for subsequent `contents` and `info`\n>> +\tcommands. When `yes` is given, mailmap data is loaded from disk on\n> \n> Are there any commands that the mailmap wouldn't apply to? Would it make\n> sense to simply say\n> \n>        Enable or disable mailmap for subsequent commands.\n\n\nGood point, agreed. I will simplify the wording in v3 and avoid listing \nspecific commands there.\n\n\n> \n> also we can s/is given//.\n> \n>> +\tfirst use and kept in memory; passing `yes` again does not reload it.\n>> +\tWhen `no` is given, mailmap is disabled but the data stays in memory\n>> +\tso that a later `mailmap yes` does not need to reload it from disk.\n> \n> I think the first sentense here jumps directly into the the caching\n> mechanism on using `yes`. It's more important for users to know what\n> `yes` implies. So perhaps:\n> \n>      When `yes` mailmap data is used and disabled on `no`. The first\n>      `yes` caches the mailmap data until the command exits.\n> \n>>   --\n>>   +\n>>\n>> diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n>> index b6f12f41d6..a53926d2bb 100644\n>> --- a/builtin/cat-file.c\n>> +++ b/builtin/cat-file.c\n>> @@ -54,6 +54,7 @@ static const char *force_path;\n>>\n>>   static struct string_list mailmap = STRING_LIST_INIT_NODUP;\n>>   static int use_mailmap;\n>> +static int mailmap_loaded;\n>>\n> \n> Nit: should we use a 'bool' here?\n\n\nYes, makes sense. I will switch that to bool in v3.\n\n> \n> So we use a variable and not simple rely on checking `mailmap.nr`\n> because it is possible that we do load the mailmap but there are no\n> entries. I assume we could rely on `maimap.cmp` being non-NULL, but\n> that's getting into implementation details.\n> \n>>   static char *replace_idents_using_mailmap(char *, size_t *);\n>>\n>> @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt,\n>>   \tbatch_one_object(line, output, opt, data);\n>>   }\n>>\n>> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n>> +\t\t\t      const char *line,\n>> +\t\t\t      struct strbuf *output UNUSED,\n>> +\t\t\t      struct expand_data *data UNUSED)\n>> +{\n>> +\tif (!strcmp(line, \"yes\")) {\n>> +\t\tif (!mailmap_loaded) {\n>> +\t\t\tread_mailmap(the_repository, &mailmap);\n>> +\t\t\tmailmap_loaded = 1;\n>> +\t\t}\n>> +\t\tuse_mailmap = 1;\n>> +\t} else if (!strcmp(line, \"no\")) {\n>> +\t\tuse_mailmap = 0;\n>> +\t} else {\n>> +\t\tdie(_(\"mailmap: unknown argument '%s', expected 'yes' or 'no'\"), line);\n>> +\t}\n>> +}\n>> +\n>>   static void dispatch_calls(struct batch_options *opt,\n>>   \t\tstruct strbuf *output,\n>>   \t\tstruct expand_data *data,\n>> @@ -725,9 +744,10 @@ static const struct parse_cmd {\n>>   \tparse_cmd_fn_t fn;\n>>   \tunsigned takes_args;\n>>   } commands[] = {\n>> -\t{ \"contents\", parse_cmd_contents, 1},\n>> -\t{ \"info\", parse_cmd_info, 1},\n>> -\t{ \"flush\", NULL, 0},\n>> +\t{ \"contents\", parse_cmd_contents, 1 },\n>> +\t{ \"info\", parse_cmd_info, 1 },\n>> +\t{ \"flush\", NULL, 0 },\n>> +\t{ \"mailmap\", parse_cmd_mailmap, 1 },\n>>   };\n>>\n>>   static void batch_objects_command(struct batch_options *opt,\n>> @@ -1127,8 +1147,10 @@ int cmd_cat_file(int argc,\n>>   \topt_cw = (opt == 'c' || opt == 'w');\n>>   \topt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');\n>>\n>> -\tif (use_mailmap)\n>> +\tif (use_mailmap) {\n>>   \t\tread_mailmap(the_repository, &mailmap);\n>> +\t\tmailmap_loaded = 1;\n>> +\t}\n>>\n> \n> The rest of the code looks good.\n> \n>>   \tswitch (batch.objects_filter.choice) {\n>>   \tcase LOFC_DISABLED:\n>> diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh\n>> index 74b7ddccb2..f66637cd86 100755\n>> --- a/t/t4203-mailmap.sh\n>> +++ b/t/t4203-mailmap.sh\n>> @@ -1133,6 +1133,54 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us\n>>   \ttest_cmp expect actual\n>>   '\n>>\n>> +test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' '\n>> +\ttest_when_finished \"rm .mailmap\" &&\n>> +\tcat >.mailmap <<-\\EOF &&\n>> +\tC O Mitter <committer@example.com> Orig <orig@example.com>\n>> +\tEOF\n>> +\tcommit_sha=$(git rev-parse HEAD) &&\n>> +\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n>> +\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n>> +\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n>> +\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n>> +\tprintf \"info HEAD\\nmailmap yes\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n>> +\techo $commit_sha commit $size_no_mailmap >expect &&\n>> +\techo $commit_sha commit $size_mailmap >>expect &&\n>> +\ttest_cmp expect actual\n>> +'\n>> +\n>> +test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' '\n>> +\ttest_when_finished \"rm .mailmap\" &&\n>> +\tcat >.mailmap <<-\\EOF &&\n>> +\tC O Mitter <committer@example.com> Orig <orig@example.com>\n>> +\tEOF\n>> +\tcommit_sha=$(git rev-parse HEAD) &&\n>> +\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n>> +\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n>> +\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n>> +\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n>> +\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n>> +\techo $commit_sha commit $size_mailmap >expect &&\n>> +\techo $commit_sha commit $size_no_mailmap >>expect &&\n>> +\ttest_cmp expect actual\n>> +'\n>> +\n>> +test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' '\n>> +\ttest_when_finished \"rm .mailmap\" &&\n>> +\tcat >.mailmap <<-\\EOF &&\n>> +\tC O Mitter <committer@example.com> Orig <orig@example.com>\n>> +\tEOF\n>> +\tcommit_sha=$(git rev-parse HEAD) &&\n>> +\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n>> +\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n>> +\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n>> +\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n>> +\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\nflush\\n\" | git cat-file --batch-command --buffer >actual &&\n>> +\techo $commit_sha commit $size_mailmap >expect &&\n>> +\techo $commit_sha commit $size_no_mailmap >>expect &&\n>> +\ttest_cmp expect actual\n>> +'\n> \n> Shouldn't we also add tests for how this interacts with '--mailmap' and\n> '--no-mailmap'?\n\n\nAgreed, that coverage is missing. I will add tests for startup option + \nruntime toggle interaction in v3.\n\n\n> \n>>   test_expect_success 'git cat-file --mailmap works with different author and committer' '\n>>   \ttest_when_finished \"rm .mailmap\" &&\n>>   \tcat >.mailmap <<-\\EOF &&\n>> --\n>> 2.51.0\n\n"},{"id":"540452","messageId":"81fc274c-a1ff-44d6-bd55-afc2308b6d9a@gmail.com","threadId":"65377","inReplyTo":"acpSgZ8RgBIE-h1Q@pks.im","subject":"Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-03-31T01:43:05Z","receivedAt":"2026-03-31T01:43:09Z","isPatch":true,"body":"\n\nOn 30/03/26 16:07, Patrick Steinhardt wrote:\n> On Sun, Mar 29, 2026 at 01:58:08PM +0530, Siddharth Asthana wrote:\n>> diff --git a/builtin/cat-file.c b/builtin/cat-file.c\n>> index b6f12f41d6..a53926d2bb 100644\n>> --- a/builtin/cat-file.c\n>> +++ b/builtin/cat-file.c\n>> @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt,\n>>   \tbatch_one_object(line, output, opt, data);\n>>   }\n>>   \n>> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n>> +\t\t\t      const char *line,\n>> +\t\t\t      struct strbuf *output UNUSED,\n>> +\t\t\t      struct expand_data *data UNUSED)\n>> +{\n>> +\tif (!strcmp(line, \"yes\")) {\n>> +\t\tif (!mailmap_loaded) {\n>> +\t\t\tread_mailmap(the_repository, &mailmap);\n>> +\t\t\tmailmap_loaded = 1;\n>> +\t\t}\n>> +\t\tuse_mailmap = 1;\n>> +\t} else if (!strcmp(line, \"no\")) {\n>> +\t\tuse_mailmap = 0;\n>> +\t} else {\n>> +\t\tdie(_(\"mailmap: unknown argument '%s', expected 'yes' or 'no'\"), line);\n>> +\t}\n>> +}\n> \n> Not commenting on the overall chanegchange, but I guess we should use\n> `git_parse_maybe_bool()` here?\n\nYep, agreed. I will switch to git_parse_maybe_bool() in v3.\n\n> \n> Patrick\n\n"},{"id":"540462","messageId":"xmqqbjg44qe9.fsf@gitster.g","threadId":"65377","inReplyTo":"72543649-7994-4220-86fb-e3c84faf0b6a@gmail.com","subject":"Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-31T03:41:18Z","receivedAt":"2026-03-31T03:41:21Z","isPatch":true,"body":"Siddharth Asthana <siddharthasthana31@gmail.com> writes:\n\n>>   * Can we somehow make mailmap object itself slightly smarter so\n>>     that it knows if it has already been asked to read the data from\n>>     its sources?  It is a pretty dumb string_list, but from a cursory\n>>     read of the code flow, it seems that mailmap.strdup_strings is\n>>     initialized to be false in builtin/cat-file.c and then one of the\n>>     first things done in mailmap.c::read_mailmap() is to flip that\n>>     bit on, so the \"yes\" part of the parse_cmd_mailmap() might become\n>> \n>> \tif (yes)\n>> \t\tload_mailmap();\n>> \n>>     with the helper load_mailmap() that may look like:\n\nThis part was a bit misstated.  What I meant was more like\n\n\tif (!strcmp(...yes))\n\t\tuse_mailmap = 1;\n\telse if (!strcmp(...no))\n\t\tuse_mailmap = 0;\n\telse\n\t\tdie(_(\"misconfigured\"));\n\n\tif (use_mailmap)\n\t\tload_mailmap();\n\n\n\n"},{"id":"540512","messageId":"20260331121111.9614-1-siddharthasthana31@gmail.com","threadId":"65377","inReplyTo":"20260329082808.12609-1-siddharthasthana31@gmail.com","subject":"[PATCH v3 0/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-03-31T12:11:10Z","receivedAt":"2026-03-31T12:11:18Z","isPatch":true,"body":"git-cat-file(1)'s --batch-command works with the --use-mailmap option,\nbut this option needs to be set when the process is created. This means\nwe cannot change this option mid-operation.\n\nAt GitLab, Gitaly keeps interacting with a long-lived git-cat-file\nprocess and it would be useful if --batch-command supported toggling\nmailmap dynamically on an existing process.\n\nThis patch adds a `mailmap` subcommand to --batch-command that accepts\na boolean argument and toggles mailmap dynamically for subsequent\ncommands.\n\nThe series is based on top of 5361983c07 (The 22nd batch, 2026-03-21).\n\nCI: https://gitlab.com/gitlab-org/git/-/pipelines/2419600519\n\nChanges in v3:\n- Use \"keeps interacting with a long-lived git-cat-file process\" wording\n  in the commit message and cover letter.\n- Drop the `Suggested-by` trailer.\n- Avoid style-only churn in the `commands[]` table by keeping existing\n  initializer style and only adding the new command entry.\n- Introduce a `load_mailmap()` helper used by both startup and\n  `parse_cmd_mailmap()`.\n- Parse `mailmap <bool>` using `git_parse_maybe_bool()` instead of\n  handling only `yes`/`no`.\n- Update docs to describe `mailmap <bool>` and reference Git's boolean\n  syntax from `git-config(1)`.\n- Add tests for startup option interaction (`--mailmap`/`--no-mailmap`),\n  accepted boolean values (`true`/`false`), and invalid boolean input.\n- Link to v2: https://public-inbox.org/git/20260329082804.53400-1-siddharthasthana31@gmail.com/\n- Link to v1: https://public-inbox.org/git/a4ec7bfa-f16b-4505-9b37-d3dd137e93cb@gmail.com/T/#m5c62fb6ad0fbcc99a706dba4c78b66359c247acd\n\nThanks,\nSiddharth\n\n---\nSiddharth Asthana (1):\n  cat-file: add mailmap subcommand to --batch-command\n\n Documentation/git-cat-file.adoc |   7 +++\n builtin/cat-file.c              |  32 ++++++++++--\n t/t4203-mailmap.sh              | 105 ++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 140 insertions(+), 4 deletions(-)\n\nRange-diff versus v2:\n\n1:  936ca27419 ! 1:  df446d7ca3 cat-file: add mailmap subcommand to --batch-command\n    @@ Commit message\n         but this option needs to be set when the process is created. This means\n         we cannot change this option mid-operation.\n     \n    -    At GitLab, Gitaly caches git-cat-file processes and it would be useful\n    -    if --batch-command supported toggling mailmap dynamically with existing\n    -    processes.\n    +    At GitLab, Gitaly keeps interacting with a long-lived git-cat-file\n    +    process and it would be useful if --batch-command supported toggling\n    +    mailmap dynamically on an existing process.\n     \n    -    Add a `mailmap` subcommand to --batch-command that takes a single\n    -    argument: `yes` to enable mailmap and `no` to disable it. When enabled,\n    -    mailmap data is loaded from disk on first use and kept in memory so that\n    -    toggling back on does not require reloading.\n    +    Add a `mailmap` subcommand to --batch-command that takes a boolean\n    +    argument. The command now uses `git_parse_maybe_bool()` and supports all\n    +    standard Git boolean values. Mailmap data is loaded lazily and kept in\n    +    memory, while a helper centralizes the one-time load path used both at\n    +    startup and from the batch-command handler.\n    +\n    +    Extend tests to cover runtime toggling, startup option interactions\n    +    (`--mailmap`/`--no-mailmap`), accepted boolean forms, and invalid values.\n     \n    -    Suggested-by: Junio C Hamano <gitster@pobox.com>\n         Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n     \n      ## Documentation/git-cat-file.adoc ##\n    @@ Documentation/git-cat-file.adoc: flush::\n      \tis used, no output will come until a `flush` is issued. When `--buffer`\n      \tis not used, commands are flushed each time without issuing `flush`.\n     +\n    -+mailmap <yes|no>::\n    -+\tEnable or disable mailmap for subsequent `contents` and `info`\n    -+\tcommands. When `yes` is given, mailmap data is loaded from disk on\n    -+\tfirst use and kept in memory; passing `yes` again does not reload it.\n    -+\tWhen `no` is given, mailmap is disabled but the data stays in memory\n    -+\tso that a later `mailmap yes` does not need to reload it from disk.\n    ++mailmap <bool>::\n    ++\tEnable or disable mailmap for subsequent commands.\n    +++\n    ++The `<bool>` argument accepts the same boolean values as\n    ++linkgit:git-config[1]. When enabled, mailmap data is loaded on first\n    ++use and kept in memory until the process exits.\n      --\n     \n      ## builtin/cat-file.c ##\n    +@@ builtin/cat-file.c: static int use_mailmap;\n     +\n     +static void load_mailmap(void)\n     +{\n     +\tif (mailmap.strdup_strings)\n     +\t\treturn;\n     +\n     +\tread_mailmap(the_repository, &mailmap);\n     +}\n     +\n     @@ builtin/cat-file.c: static void parse_cmd_info(struct batch_options *opt,\n      \tbatch_one_object(line, output, opt, data);\n      }\n    @@ builtin/cat-file.c: static void parse_cmd_info(struct batch_options *opt,\n     +{\n    -+\tif (!strcmp(line, \"yes\")) {\n    -+\t\tif (!mailmap_loaded) {\n    -+\t\t\tread_mailmap(the_repository, &mailmap);\n    -+\t\t\tmailmap_loaded = 1;\n    -+\t\t}\n    -+\t\tuse_mailmap = 1;\n    -+\t} else if (!strcmp(line, \"no\")) {\n    -+\t\tuse_mailmap = 0;\n    -+\t} else {\n    -+\t\tdie(_(\"mailmap: unknown argument '%s', expected 'yes' or 'no'\"), line);\n    -+\t}\n    ++\tint value = git_parse_maybe_bool(line);\n    ++\n    ++\tif (value < 0)\n    ++\t\tdie(_(\"mailmap: invalid boolean '%s'\"), line);\n    ++\n    ++\tif (value > 0)\n    ++\t\tload_mailmap();\n    ++\tuse_mailmap = value;\n     +}\n     +\n    @@ builtin/cat-file.c: static const struct parse_cmd {\n    -+\t{ \"use-mailmap\", parse_cmd_use_mailmap, 0 },\n    -+\t{ \"no-use-mailmap\", parse_cmd_disable_mailmap, 0 },\n    ++\t{ \"mailmap\", parse_cmd_mailmap, 1 },\n     +};\n     \n     @@ builtin/cat-file.c: int cmd_cat_file(int argc,\n      \tif (use_mailmap)\n    -+\t\tread_mailmap(the_repository, &mailmap);\n    ++\t\tload_mailmap();\n\nbase-commit: 5361983c075154725be47b65cca9a2421789e410\n-- \n2.53.0\n"},{"id":"540513","messageId":"20260331121111.9614-2-siddharthasthana31@gmail.com","threadId":"65377","inReplyTo":"20260331121111.9614-1-siddharthasthana31@gmail.com","subject":"[PATCH v3 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-03-31T12:11:11Z","receivedAt":"2026-03-31T12:11:23Z","isPatch":true,"body":"git-cat-file(1)'s --batch-command works with the --use-mailmap option,\nbut this option needs to be set when the process is created. This means\nwe cannot change this option mid-operation.\n\nAt GitLab, Gitaly keeps interacting with a long-lived git-cat-file\nprocess and it would be useful if --batch-command supported toggling\nmailmap dynamically on an existing process.\n\nAdd a `mailmap` subcommand to --batch-command that takes a boolean\nargument. The command now uses `git_parse_maybe_bool()` and supports all\nstandard Git boolean values. Mailmap data is loaded lazily and kept in\nmemory, while a helper centralizes the one-time load path used both at\nstartup and from the batch-command handler.\n\nExtend tests to cover runtime toggling, startup option interactions\n(`--mailmap`/`--no-mailmap`), accepted boolean forms, and invalid values.\n\nSigned-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n---\nCI: https://gitlab.com/gitlab-org/git/-/pipelines/2419600519\n\n Documentation/git-cat-file.adoc |   7 +++\n builtin/cat-file.c              |  32 ++++++++--\n t/t4203-mailmap.sh              | 105 ++++++++++++++++++++++++++++++++\n 3 files changed, 140 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc\nindex c139f55a16..3db925e1de 100644\n--- a/Documentation/git-cat-file.adoc\n+++ b/Documentation/git-cat-file.adoc\n@@ -174,6 +174,13 @@ flush::\n \tsince the beginning or since the last flush was issued. When `--buffer`\n \tis used, no output will come until a `flush` is issued. When `--buffer`\n \tis not used, commands are flushed each time without issuing `flush`.\n+\n+mailmap <bool>::\n+\tEnable or disable mailmap for subsequent commands.\n++\n+The `<bool>` argument accepts the same boolean values as\n+linkgit:git-config[1]. When enabled, mailmap data is loaded on first\n+use and kept in memory until the process exits.\n --\n +\n \ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex b6f12f41d6..a3dab0b40c 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -57,6 +57,14 @@ static int use_mailmap;\n \n static char *replace_idents_using_mailmap(char *, size_t *);\n \n+static void load_mailmap(void)\n+{\n+\tif (mailmap.strdup_strings)\n+\t\treturn;\n+\n+\tread_mailmap(the_repository, &mailmap);\n+}\n+\n static char *replace_idents_using_mailmap(char *object_buf, size_t *size)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n@@ -692,6 +700,21 @@ static void parse_cmd_info(struct batch_options *opt,\n \tbatch_one_object(line, output, opt, data);\n }\n \n+static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n+\t\t\t      const char *line,\n+\t\t\t      struct strbuf *output UNUSED,\n+\t\t\t      struct expand_data *data UNUSED)\n+{\n+\tint value = git_parse_maybe_bool(line);\n+\n+\tif (value < 0)\n+\t\tdie(_(\"mailmap: invalid boolean '%s'\"), line);\n+\n+\tif (value > 0)\n+\t\tload_mailmap();\n+\tuse_mailmap = value;\n+}\n+\n static void dispatch_calls(struct batch_options *opt,\n \t\tstruct strbuf *output,\n \t\tstruct expand_data *data,\n@@ -725,9 +748,10 @@ static const struct parse_cmd {\n \tparse_cmd_fn_t fn;\n \tunsigned takes_args;\n } commands[] = {\n-\t{ \"contents\", parse_cmd_contents, 1},\n-\t{ \"info\", parse_cmd_info, 1},\n-\t{ \"flush\", NULL, 0},\n+\t{ \"contents\", parse_cmd_contents, 1 },\n+\t{ \"info\", parse_cmd_info, 1 },\n+\t{ \"flush\", NULL, 0 },\n+\t{ \"mailmap\", parse_cmd_mailmap, 1 },\n };\n \n static void batch_objects_command(struct batch_options *opt,\n@@ -1128,7 +1152,7 @@ int cmd_cat_file(int argc,\n \topt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');\n \n \tif (use_mailmap)\n-\t\tread_mailmap(the_repository, &mailmap);\n+\t\tload_mailmap();\n \n \tswitch (batch.objects_filter.choice) {\n \tcase LOFC_DISABLED:\ndiff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh\nindex 74b7ddccb2..249548eb9b 100755\n--- a/t/t4203-mailmap.sh\n+++ b/t/t4203-mailmap.sh\n@@ -1133,6 +1133,111 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"info HEAD\\nmailmap yes\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n+\techo $commit_sha commit $size_no_mailmap >expect &&\n+\techo $commit_sha commit $size_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\nflush\\n\" | git cat-file --batch-command --buffer >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap no overrides startup --mailmap' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tprintf \"info HEAD\\nmailmap no\\ninfo HEAD\\n\" | \\\n+\t\tgit cat-file --mailmap --batch-command >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap yes overrides startup --no-mailmap' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"info HEAD\\nmailmap yes\\ninfo HEAD\\n\" | \\\n+\t\tgit cat-file --no-mailmap --batch-command >actual &&\n+\techo $commit_sha commit $size_no_mailmap >expect &&\n+\techo $commit_sha commit $size_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap accepts true/false' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"mailmap true\\ninfo HEAD\\nmailmap false\\ninfo HEAD\\n\" | \\\n+\t\tgit cat-file --batch-command >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap rejects invalid boolean' '\n+\techo \"mailmap maybe\" >in &&\n+\ttest_must_fail git cat-file --batch-command <in 2>err &&\n+\ttest_grep \"mailmap: invalid boolean .*maybe\" err\n+'\n+\n test_expect_success 'git cat-file --mailmap works with different author and committer' '\n \ttest_when_finished \"rm .mailmap\" &&\n \tcat >.mailmap <<-\\EOF &&\n-- \n2.53.0\n\n"},{"id":"540541","messageId":"2060629.PYKUYFuaPT@piment-oiseau","threadId":"65377","inReplyTo":"20260329082808.12609-2-siddharthasthana31@gmail.com","subject":"Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Jean-Noël AVILA","fromEmail":"jn.avila@free.fr","sentAt":"2026-03-31T17:11:13Z","receivedAt":"2026-03-31T17:11:23Z","isPatch":true,"body":"On Sunday, 29 March 2026 10:28:08 CEST Siddharth Asthana wrote:\n> git-cat-file(1)'s --batch-command works with the --use-mailmap option,\n> but this option needs to be set when the process is created. This means\n> we cannot change this option mid-operation.\n> \n> At GitLab, Gitaly caches git-cat-file processes and it would be useful\n> if --batch-command supported toggling mailmap dynamically with existing\n> processes.\n> \n> Add a `mailmap` subcommand to --batch-command that takes a single\n> argument: `yes` to enable mailmap and `no` to disable it. When enabled,\n> mailmap data is loaded from disk on first use and kept in memory so that\n> toggling back on does not require reloading.\n> \n> Suggested-by: Junio C Hamano <gitster@pobox.com>\n> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n> ---\n> CI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861\n> \n>  Documentation/git-cat-file.adoc |  7 +++++\n>  builtin/cat-file.c              | 30 ++++++++++++++++++---\n>  t/t4203-mailmap.sh              | 48 +++++++++++++++++++++++++++++++++\n>  3 files changed, 81 insertions(+), 4 deletions(-)\n> \n> diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-\nfile.adoc\n> index c139f55a16..af32e929a8 100644\n> --- a/Documentation/git-cat-file.adoc\n> +++ b/Documentation/git-cat-file.adoc\n> @@ -174,6 +174,13 @@ flush::\n>  \tsince the beginning or since the last flush was issued. When `--\nbuffer`\n>  \tis used, no output will come until a `flush` is issued. When `--\nbuffer`\n>  \tis not used, commands are flushed each time without issuing `flush`.\n> +\n> +mailmap <yes|no>::\n\n`yes` and `no` are keywords, and you want to express an alternative, do it \nlike this: `mailmap (yes|no)::`.\n\n> +\tEnable or disable mailmap for subsequent `contents` and `info`\n> +\tcommands. When `yes` is given, mailmap data is loaded from disk on\n> +\tfirst use and kept in memory; passing `yes` again does not reload \nit.\n> +\tWhen `no` is given, mailmap is disabled but the data stays in memory\n> +\tso that a later `mailmap yes` does not need to reload it from disk.\n>  --\n>  +\n> \n\nInstead of detailing the alternatives in the same chapter, you could break it \ninto a sub-list:\n\nEnable or disalbe mailmap for subsequent `contents` and `info` commands. \nPossible values are:\n`yes`;;\nmailmap data is loaded from disk on first use and kept in memory; passing \n`yes` again does not reload it.\n`no`;;\nmailmap is disabled but the data stays in memory so that a later `mailmap yes` \ndoes not need to reload it from disk.\n\nThanks\n\n\n"},{"id":"540542","messageId":"xmqqjyur28kn.fsf@gitster.g","threadId":"65377","inReplyTo":"2060629.PYKUYFuaPT@piment-oiseau","subject":"Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-31T17:49:12Z","receivedAt":"2026-03-31T17:49:15Z","isPatch":true,"body":"Jean-Noël AVILA <jn.avila@free.fr> writes:\n\n> On Sunday, 29 March 2026 10:28:08 CEST Siddharth Asthana wrote:\n>> git-cat-file(1)'s --batch-command works with the --use-mailmap option,\n>> but this option needs to be set when the process is created. This means\n>> we cannot change this option mid-operation.\n>> \n>> At GitLab, Gitaly caches git-cat-file processes and it would be useful\n>> if --batch-command supported toggling mailmap dynamically with existing\n>> processes.\n>> \n>> Add a `mailmap` subcommand to --batch-command that takes a single\n>> argument: `yes` to enable mailmap and `no` to disable it. When enabled,\n>> mailmap data is loaded from disk on first use and kept in memory so that\n>> toggling back on does not require reloading.\n>> \n>> Suggested-by: Junio C Hamano <gitster@pobox.com>\n>> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n>> ---\n>> CI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861\n>> \n>>  Documentation/git-cat-file.adoc |  7 +++++\n>>  builtin/cat-file.c              | 30 ++++++++++++++++++---\n>>  t/t4203-mailmap.sh              | 48 +++++++++++++++++++++++++++++++++\n>>  3 files changed, 81 insertions(+), 4 deletions(-)\n>> \n>> diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-\n> file.adoc\n>> index c139f55a16..af32e929a8 100644\n>> --- a/Documentation/git-cat-file.adoc\n>> +++ b/Documentation/git-cat-file.adoc\n>> @@ -174,6 +174,13 @@ flush::\n>>  \tsince the beginning or since the last flush was issued. When `--\n> buffer`\n>>  \tis used, no output will come until a `flush` is issued. When `--\n> buffer`\n>>  \tis not used, commands are flushed each time without issuing `flush`.\n>> +\n>> +mailmap <yes|no>::\n>\n> `yes` and `no` are keywords, and you want to express an alternative, do it \n> like this: `mailmap (yes|no)::`.\n\nNot \n\n    `mailmap (yes|no)`::\n\nIOW, shouldn't the closing quote come before the double-colon?\n\n>> +\tEnable or disable mailmap for subsequent `contents` and `info`\n>> +\tcommands. When `yes` is given, mailmap data is loaded from disk on\n>> +\tfirst use and kept in memory; passing `yes` again does not reload \n> it.\n>> +\tWhen `no` is given, mailmap is disabled but the data stays in memory\n>> +\tso that a later `mailmap yes` does not need to reload it from disk.\n>>  --\n>>  +\n>> \n>\n> Instead of detailing the alternatives in the same chapter, you could break it \n> into a sub-list:\n>\n> Enable or disalbe mailmap for subsequent `contents` and `info` commands. \n> Possible values are:\n> `yes`;;\n> mailmap data is loaded from disk on first use and kept in memory; passing \n> `yes` again does not reload it.\n> `no`;;\n> mailmap is disabled but the data stays in memory so that a later `mailmap yes` \n> does not need to reload it from disk.\n\nGreat.\n"},{"id":"540548","messageId":"xmqqo6k3ztxr.fsf@gitster.g","threadId":"65377","inReplyTo":"20260331121111.9614-2-siddharthasthana31@gmail.com","subject":"Re: [PATCH v3 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-31T19:21:20Z","receivedAt":"2026-03-31T19:21:24Z","isPatch":true,"body":"Siddharth Asthana <siddharthasthana31@gmail.com> writes:\n\n> git-cat-file(1)'s --batch-command works with the --use-mailmap option,\n> but this option needs to be set when the process is created. This means\n> we cannot change this option mid-operation.\n>\n> At GitLab, Gitaly keeps interacting with a long-lived git-cat-file\n> process and it would be useful if --batch-command supported toggling\n> mailmap dynamically on an existing process.\n>\n> Add a `mailmap` subcommand to --batch-command that takes a boolean\n> argument. The command now uses `git_parse_maybe_bool()` and supports all\n> standard Git boolean values. Mailmap data is loaded lazily and kept in\n\nI do not think you want to say \"now uses `git_parse_maybe_bool()`\".\nNobody is interested in the difference relative to what you did in\nthe previous iteration.\n\n    ... that takes a boolean argument (usual ways you can specify a\n    boolean value like 'yes', 'true', etc., are supported).\n\n> +static void load_mailmap(void)\n> +{\n> +\tif (mailmap.strdup_strings)\n> +\t\treturn;\n> +\n> +\tread_mailmap(the_repository, &mailmap);\n> +}\n\nThis, especially the early return condition, may deserve a bit of\nin-code comment, as \"a used string_list has the .strdup_strings bit\nset\" is not a generally applicable rule.\n\n    /*\n     * The mailmap is initialized with .strdup_strings set to 0,\n     * but read_mailmap() sets the bit to 1 (this is true even when\n     * not a single mailmap entry is read), so it can be used for\n     * lazy loading.\n     */\n\nor something, perhaps?\n\n> @@ -692,6 +700,21 @@ static void parse_cmd_info(struct batch_options *opt,\n>  \tbatch_one_object(line, output, opt, data);\n>  }\n>  \n> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n> +\t\t\t      const char *line,\n> +\t\t\t      struct strbuf *output UNUSED,\n> +\t\t\t      struct expand_data *data UNUSED)\n> +{\n> +\tint value = git_parse_maybe_bool(line);\n\nAs \"line\" is never NULL, one standard way to spell a boolean True is\nnot available to the callers, namely, \"mailmap<EOL>\" (like how a\nconfiguration file entry \"[core] bare\" means \"[core] bare = true\"),\nbut that is probably OK. \"mailmap<SP><EOL>\" may be interpreted as\nfeeding an empty string as an argument, which is \"false\" to the\ngit_parse_maybe_bool() function.  That might be surprising.\n\nNothing actionable in the above comment (other than perhaps as a\nhint for documentation update).\n\n> +\tif (value < 0)\n> +\t\tdie(_(\"mailmap: invalid boolean '%s'\"), line);\n> +\n> +\tif (value > 0)\n> +\t\tload_mailmap();\n> +\tuse_mailmap = value;\n> +}\n\nHmph, why not use use_mailmap from the beginning of the function\nwithout introducing the local variable \"value\"?  Nothing in\nload_mailmap() pays attention to the current value of use_mailmap\nso I do not see much point in preserving the current status until\nthe last minute.\n\nThanks.\n"},{"id":"540625","messageId":"025bbab6-0731-4df7-bc1f-a4969cb5ae13@free.fr","threadId":"65377","inReplyTo":"xmqqjyur28kn.fsf@gitster.g","subject":"Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Jean-Noël Avila","fromEmail":"jn.avila@free.fr","sentAt":"2026-04-01T10:11:20Z","receivedAt":"2026-04-01T10:11:37Z","isPatch":true,"body":"On 3/31/26 19:49, Junio C Hamano wrote:\n> Jean-Noël AVILA <jn.avila@free.fr> writes:\n> \n>> On Sunday, 29 March 2026 10:28:08 CEST Siddharth Asthana wrote:\n>>> git-cat-file(1)'s --batch-command works with the --use-mailmap option,\n>>> but this option needs to be set when the process is created. This means\n>>> we cannot change this option mid-operation.\n>>>\n>>> At GitLab, Gitaly caches git-cat-file processes and it would be useful\n>>> if --batch-command supported toggling mailmap dynamically with existing\n>>> processes.\n>>>\n>>> Add a `mailmap` subcommand to --batch-command that takes a single\n>>> argument: `yes` to enable mailmap and `no` to disable it. When enabled,\n>>> mailmap data is loaded from disk on first use and kept in memory so that\n>>> toggling back on does not require reloading.\n>>>\n>>> Suggested-by: Junio C Hamano <gitster@pobox.com>\n>>> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n>>> ---\n>>> CI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861\n>>>\n>>>  Documentation/git-cat-file.adoc |  7 +++++\n>>>  builtin/cat-file.c              | 30 ++++++++++++++++++---\n>>>  t/t4203-mailmap.sh              | 48 +++++++++++++++++++++++++++++++++\n>>>  3 files changed, 81 insertions(+), 4 deletions(-)\n>>>\n>>> diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-\n>> file.adoc\n>>> index c139f55a16..af32e929a8 100644\n>>> --- a/Documentation/git-cat-file.adoc\n>>> +++ b/Documentation/git-cat-file.adoc\n>>> @@ -174,6 +174,13 @@ flush::\n>>>  \tsince the beginning or since the last flush was issued. When `--\n>> buffer`\n>>>  \tis used, no output will come until a `flush` is issued. When `--\n>> buffer`\n>>>  \tis not used, commands are flushed each time without issuing `flush`.\n>>> +\n>>> +mailmap <yes|no>::\n>>\n>> `yes` and `no` are keywords, and you want to express an alternative, do it \n>> like this: `mailmap (yes|no)::`.\n> \n> Not \n> \n>     `mailmap (yes|no)`::\n> \n> IOW, shouldn't the closing quote come before the double-colon?\n\nOops, you're completely right!\n\n\n"},{"id":"541394","messageId":"xmqqv7dyoei6.fsf@gitster.g","threadId":"65377","inReplyTo":"xmqqo6k3ztxr.fsf@gitster.g","subject":"Re: [PATCH v3 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-04-10T18:29:37Z","receivedAt":"2026-04-10T18:29:40Z","isPatch":true,"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Siddharth Asthana <siddharthasthana31@gmail.com> writes:\n>\n>> git-cat-file(1)'s --batch-command works with the --use-mailmap option,\n>> but this option needs to be set when the process is created. This means\n>> we cannot change this option mid-operation.\n>>\n>> At GitLab, Gitaly keeps interacting with a long-lived git-cat-file\n>> process and it would be useful if --batch-command supported toggling\n>> mailmap dynamically on an existing process.\n>>\n>> Add a `mailmap` subcommand to --batch-command that takes a boolean\n>> argument. The command now uses `git_parse_maybe_bool()` and supports all\n>> standard Git boolean values. Mailmap data is loaded lazily and kept in\n>\n> I do not think you want to say \"now uses `git_parse_maybe_bool()`\".\n> Nobody is interested in the difference relative to what you did in\n> the previous iteration.\n>\n>     ... that takes a boolean argument (usual ways you can specify a\n>     boolean value like 'yes', 'true', etc., are supported).\n>\n>> +static void load_mailmap(void)\n>> +{\n>> +\tif (mailmap.strdup_strings)\n>> +\t\treturn;\n>> +\n>> +\tread_mailmap(the_repository, &mailmap);\n>> +}\n>\n> This, especially the early return condition, may deserve a bit of\n> in-code comment, as \"a used string_list has the .strdup_strings bit\n> set\" is not a generally applicable rule.\n>\n>     /*\n>      * The mailmap is initialized with .strdup_strings set to 0,\n>      * but read_mailmap() sets the bit to 1 (this is true even when\n>      * not a single mailmap entry is read), so it can be used for\n>      * lazy loading.\n>      */\n>\n> or something, perhaps?\n>\n>> @@ -692,6 +700,21 @@ static void parse_cmd_info(struct batch_options *opt,\n>>  \tbatch_one_object(line, output, opt, data);\n>>  }\n>>  \n>> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n>> +\t\t\t      const char *line,\n>> +\t\t\t      struct strbuf *output UNUSED,\n>> +\t\t\t      struct expand_data *data UNUSED)\n>> +{\n>> +\tint value = git_parse_maybe_bool(line);\n>\n> As \"line\" is never NULL, one standard way to spell a boolean True is\n> not available to the callers, namely, \"mailmap<EOL>\" (like how a\n> configuration file entry \"[core] bare\" means \"[core] bare = true\"),\n> but that is probably OK. \"mailmap<SP><EOL>\" may be interpreted as\n> feeding an empty string as an argument, which is \"false\" to the\n> git_parse_maybe_bool() function.  That might be surprising.\n>\n> Nothing actionable in the above comment (other than perhaps as a\n> hint for documentation update).\n>\n>> +\tif (value < 0)\n>> +\t\tdie(_(\"mailmap: invalid boolean '%s'\"), line);\n>> +\n>> +\tif (value > 0)\n>> +\t\tload_mailmap();\n>> +\tuse_mailmap = value;\n>> +}\n>\n> Hmph, why not use use_mailmap from the beginning of the function\n> without introducing the local variable \"value\"?  Nothing in\n> load_mailmap() pays attention to the current value of use_mailmap\n> so I do not see much point in preserving the current status until\n> the last minute.\n>\n> Thanks.\n\nThe thread went dark since this message.\n\nI do not want to see energy spent on a viable topic so far disappear\ninto a void without achieving anything.  Let's push the topic over\nthe finish line with futher work.\n\nThanks.\n"},{"id":"541658","messageId":"20260415150943.40493-1-siddharthasthana31@gmail.com","threadId":"65377","inReplyTo":"20260331121111.9614-1-siddharthasthana31@gmail.com","subject":"[PATCH v4 0/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-04-15T15:09:42Z","receivedAt":"2026-04-15T15:09:50Z","isPatch":true,"body":"git-cat-file(1)'s --batch-command works with the --use-mailmap option,\nbut this option needs to be set when the process is created. This means\nwe cannot change this option mid-operation.\n\nAt GitLab, Gitaly keeps interacting with a long-lived git-cat-file\nprocess and it would be useful if --batch-command supported toggling\nmailmap dynamically on an existing process.\n\nThis patch adds a `mailmap` subcommand to --batch-command that accepts\na boolean argument and toggles mailmap dynamically for subsequent\ncommands.\n\nThe series is based on top of 5361983c07 (The 22nd batch, 2026-03-21).\n\nCI: https://gitlab.com/gitlab-org/git/-/pipelines/2455043368\n\nChanges in v4:\n- Reword commit message: describe boolean support without mentioning\n  internal function names, following Junio's suggestion.\n- Add an in-code comment explaining why `mailmap.strdup_strings` can be\n  used as the \"already loaded\" check in `load_mailmap()`.\n- Drop local `value` variable in `parse_cmd_mailmap()` and assign\n  directly to `use_mailmap`.\n- Fix documentation syntax: place the closing backtick before `::`\n  and break the description into a `;;` sub-list for `true`/`false`\n  effects.\n- Link to v3: https://lore.kernel.org/git/xmqqv7dyoei6.fsf@gitster.g/T/#m0a109f3eb5129e619ecec5f2d58ead0c5a49a4f3\n- Link to v2: https://lore.kernel.org/git/xmqqv7dyoei6.fsf@gitster.g/T/#m445eab3b309bded92d1b130d225b882c73988ff2\n- Link to v1: https://public-inbox.org/git/a4ec7bfa-f16b-4505-9b37-d3dd137e93cb@gmail.com/T/#m5c62fb6ad0fbcc99a706dba4c78b66359c247acd\n\nThanks,\nSiddharth\n\n---\nSiddharth Asthana (1):\n  cat-file: add mailmap subcommand to --batch-command\n\n Documentation/git-cat-file.adoc |  12 +++++\n builtin/cat-file.c              |  37 ++++++++++++--\n t/t4203-mailmap.sh              | 105 ++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 150 insertions(+), 4 deletions(-)\n\nRange-diff versus v3:\n\n1:  dbc1a003a5 ! 1:  25ebffe39e cat-file: add mailmap subcommand to --batch-command\n    @@ Commit message\n         mailmap dynamically on an existing process.\n     \n         Add a `mailmap` subcommand to --batch-command that takes a boolean\n    -    argument. The command now uses `git_parse_maybe_bool()` and supports all\n    -    standard Git boolean values. Mailmap data is loaded lazily and kept in\n    -    memory, while a helper centralizes the one-time load path used both at\n    -    startup and from the batch-command handler.\n    +    argument (usual ways you can specify a boolean value like 'yes', 'true',\n    +    etc., are supported). Mailmap data is loaded lazily and kept in memory,\n    +    while a helper centralizes the one-time load path used both at startup\n    +    and from the batch-command handler.\n     \n         Extend tests to cover runtime toggling, startup option interactions\n         (`--mailmap`/`--no-mailmap`), accepted boolean forms, and invalid values.\n    @@ Documentation/git-cat-file.adoc: flush::\n      \tis used, no output will come until a `flush` is issued. When `--buffer`\n      \tis not used, commands are flushed each time without issuing `flush`.\n     +\n    -+mailmap <bool>::\n    -+\tEnable or disable mailmap for subsequent commands.\n    ++`mailmap (<bool>)`::\n    ++\tEnable or disable mailmap for subsequent commands. The `<bool>`\n    ++\targument accepts the same boolean values as linkgit:git-config[1].\n    ++\tPossible effects are:\n     ++\n    -+The `<bool>` argument accepts the same boolean values as\n    -+linkgit:git-config[1]. When enabled, mailmap data is loaded on first\n    -+use and kept in memory until the process exits.\n    ++`true`;;\n    ++\tMailmap data is loaded on first use and kept in memory until the\n    ++\tprocess exits. Passing `true` again does not reload the data.\n    ++`false`;;\n    ++\tMailmap replacements are disabled for subsequent commands, but data\n    ++\talready loaded stays in memory.\n      --\n      +\n      \n    @@ builtin/cat-file.c: static int use_mailmap;\n      \n      static char *replace_idents_using_mailmap(char *, size_t *);\n      \n    ++/*\n    ++ * The mailmap is initialized with .strdup_strings set to 0,\n    ++ * but read_mailmap() sets the bit to 1 (this is true even when\n    ++ * not a single mailmap entry is read), so it can be used for\n    ++ * lazy loading.\n    ++ */\n     +static void load_mailmap(void)\n     +{\n     +\tif (mailmap.strdup_strings)\n    @@ builtin/cat-file.c: static void parse_cmd_info(struct batch_options *opt,\n     +\t\t\t      struct strbuf *output UNUSED,\n     +\t\t\t      struct expand_data *data UNUSED)\n     +{\n    -+\tint value = git_parse_maybe_bool(line);\n    ++\tuse_mailmap = git_parse_maybe_bool(line);\n     +\n    -+\tif (value < 0)\n    ++\tif (use_mailmap < 0)\n     +\t\tdie(_(\"mailmap: invalid boolean '%s'\"), line);\n     +\n    -+\tif (value > 0)\n    ++\tif (use_mailmap)\n     +\t\tload_mailmap();\n    -+\tuse_mailmap = value;\n     +}\n     +\n      static void dispatch_calls(struct batch_options *opt,\n\nbase-commit: 5361983c075154725be47b65cca9a2421789e410\n-- \n2.53.0\n"},{"id":"541659","messageId":"20260415150943.40493-2-siddharthasthana31@gmail.com","threadId":"65377","inReplyTo":"20260415150943.40493-1-siddharthasthana31@gmail.com","subject":"[PATCH v4 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-04-15T15:09:43Z","receivedAt":"2026-04-15T15:09:55Z","isPatch":true,"body":"git-cat-file(1)'s --batch-command works with the --use-mailmap option,\nbut this option needs to be set when the process is created. This means\nwe cannot change this option mid-operation.\n\nAt GitLab, Gitaly keeps interacting with a long-lived git-cat-file\nprocess and it would be useful if --batch-command supported toggling\nmailmap dynamically on an existing process.\n\nAdd a `mailmap` subcommand to --batch-command that takes a boolean\nargument (usual ways you can specify a boolean value like 'yes', 'true',\netc., are supported). Mailmap data is loaded lazily and kept in memory,\nwhile a helper centralizes the one-time load path used both at startup\nand from the batch-command handler.\n\nExtend tests to cover runtime toggling, startup option interactions\n(`--mailmap`/`--no-mailmap`), accepted boolean forms, and invalid values.\n\nSigned-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n---\nCI: https://gitlab.com/gitlab-org/git/-/pipelines/2455043368\n\n Documentation/git-cat-file.adoc |  12 ++++\n builtin/cat-file.c              |  37 +++++++++--\n t/t4203-mailmap.sh              | 105 ++++++++++++++++++++++++++++++++\n 3 files changed, 150 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc\nindex c139f55a16..0f499c9d1b 100644\n--- a/Documentation/git-cat-file.adoc\n+++ b/Documentation/git-cat-file.adoc\n@@ -174,6 +174,18 @@ flush::\n \tsince the beginning or since the last flush was issued. When `--buffer`\n \tis used, no output will come until a `flush` is issued. When `--buffer`\n \tis not used, commands are flushed each time without issuing `flush`.\n+\n+`mailmap (<bool>)`::\n+\tEnable or disable mailmap for subsequent commands. The `<bool>`\n+\targument accepts the same boolean values as linkgit:git-config[1].\n+\tPossible effects are:\n++\n+`true`;;\n+\tMailmap data is loaded on first use and kept in memory until the\n+\tprocess exits. Passing `true` again does not reload the data.\n+`false`;;\n+\tMailmap replacements are disabled for subsequent commands, but data\n+\talready loaded stays in memory.\n --\n +\n \ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex d9fbad5358..fa45f774d7 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -57,6 +57,20 @@ static int use_mailmap;\n \n static char *replace_idents_using_mailmap(char *, size_t *);\n \n+/*\n+ * The mailmap is initialized with .strdup_strings set to 0,\n+ * but read_mailmap() sets the bit to 1 (this is true even when\n+ * not a single mailmap entry is read), so it can be used for\n+ * lazy loading.\n+ */\n+static void load_mailmap(void)\n+{\n+\tif (mailmap.strdup_strings)\n+\t\treturn;\n+\n+\tread_mailmap(the_repository, &mailmap);\n+}\n+\n static char *replace_idents_using_mailmap(char *object_buf, size_t *size)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n@@ -692,6 +706,20 @@ static void parse_cmd_info(struct batch_options *opt,\n \tbatch_one_object(line, output, opt, data);\n }\n \n+static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n+\t\t\t      const char *line,\n+\t\t\t      struct strbuf *output UNUSED,\n+\t\t\t      struct expand_data *data UNUSED)\n+{\n+\tuse_mailmap = git_parse_maybe_bool(line);\n+\n+\tif (use_mailmap < 0)\n+\t\tdie(_(\"mailmap: invalid boolean '%s'\"), line);\n+\n+\tif (use_mailmap)\n+\t\tload_mailmap();\n+}\n+\n static void dispatch_calls(struct batch_options *opt,\n \t\tstruct strbuf *output,\n \t\tstruct expand_data *data,\n@@ -725,9 +753,10 @@ static const struct parse_cmd {\n \tparse_cmd_fn_t fn;\n \tunsigned takes_args;\n } commands[] = {\n-\t{ \"contents\", parse_cmd_contents, 1},\n-\t{ \"info\", parse_cmd_info, 1},\n-\t{ \"flush\", NULL, 0},\n+\t{ \"contents\", parse_cmd_contents, 1 },\n+\t{ \"info\", parse_cmd_info, 1 },\n+\t{ \"flush\", NULL, 0 },\n+\t{ \"mailmap\", parse_cmd_mailmap, 1 },\n };\n \n static void batch_objects_command(struct batch_options *opt,\n@@ -1131,7 +1160,7 @@ int cmd_cat_file(int argc,\n \topt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');\n \n \tif (use_mailmap)\n-\t\tread_mailmap(the_repository, &mailmap);\n+\t\tload_mailmap();\n \n \tswitch (batch.objects_filter.choice) {\n \tcase LOFC_DISABLED:\ndiff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh\nindex 74b7ddccb2..249548eb9b 100755\n--- a/t/t4203-mailmap.sh\n+++ b/t/t4203-mailmap.sh\n@@ -1133,6 +1133,111 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"info HEAD\\nmailmap yes\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n+\techo $commit_sha commit $size_no_mailmap >expect &&\n+\techo $commit_sha commit $size_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\nflush\\n\" | git cat-file --batch-command --buffer >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap no overrides startup --mailmap' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tprintf \"info HEAD\\nmailmap no\\ninfo HEAD\\n\" | \\\n+\t\tgit cat-file --mailmap --batch-command >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap yes overrides startup --no-mailmap' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"info HEAD\\nmailmap yes\\ninfo HEAD\\n\" | \\\n+\t\tgit cat-file --no-mailmap --batch-command >actual &&\n+\techo $commit_sha commit $size_no_mailmap >expect &&\n+\techo $commit_sha commit $size_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap accepts true/false' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"mailmap true\\ninfo HEAD\\nmailmap false\\ninfo HEAD\\n\" | \\\n+\t\tgit cat-file --batch-command >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap rejects invalid boolean' '\n+\techo \"mailmap maybe\" >in &&\n+\ttest_must_fail git cat-file --batch-command <in 2>err &&\n+\ttest_grep \"mailmap: invalid boolean .*maybe\" err\n+'\n+\n test_expect_success 'git cat-file --mailmap works with different author and committer' '\n \ttest_when_finished \"rm .mailmap\" &&\n \tcat >.mailmap <<-\\EOF &&\n-- \n2.53.0\n\n"},{"id":"541688","messageId":"xmqqa4v46ptu.fsf@gitster.g","threadId":"65377","inReplyTo":"20260415150943.40493-2-siddharthasthana31@gmail.com","subject":"Re: [PATCH v4 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-04-15T18:28:13Z","receivedAt":"2026-04-15T18:28:16Z","isPatch":true,"body":"Siddharth Asthana <siddharthasthana31@gmail.com> writes:\n\n> diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc\n> index c139f55a16..0f499c9d1b 100644\n> --- a/Documentation/git-cat-file.adoc\n> +++ b/Documentation/git-cat-file.adoc\n> @@ -174,6 +174,18 @@ flush::\n>  \tsince the beginning or since the last flush was issued. When `--buffer`\n>  \tis used, no output will come until a `flush` is issued. When `--buffer`\n>  \tis not used, commands are flushed each time without issuing `flush`.\n> +\n> +`mailmap (<bool>)`::\n> +\tEnable or disable mailmap for subsequent commands. The `<bool>`\n> +\targument accepts the same boolean values as linkgit:git-config[1].\n> +\tPossible effects are:\n> ++\n> +`true`;;\n> +\tMailmap data is loaded on first use and kept in memory until the\n> +\tprocess exits. Passing `true` again does not reload the data.\n> +`false`;;\n> +\tMailmap replacements are disabled for subsequent commands, but data\n> +\talready loaded stays in memory.\n>  --\n>  +\n\nWhile the above may not be telling any lies, I think the focus of\nthe explanation is placed on a wrong thing.  What primarily matters\nto end-users is that toggling 'mailmap' to true makes the mailmap\napplied to identities before they appear in the output and false\nmakes the identities output without modification.  The fact that you\nread the mailmap data only once and keep it around even when\ntoggling the feature off, just in case the feature gets turned on\nagain, is an implementation detail that is of much lessor interest\nto end users, no?\n\nPerhaps delete everything from \"Possible effects are\" and replace it\nwith a brief explanation, e.g.,\n\n`mailmap (<bool>)`::\n\tEnable or disable mailmap for subsequent commands. The `<bool>`\n\targument accepts the same boolean values as linkgit:git-config[1].\n\tThe mailmap data is read upon the first use and only once,\n\teven after the `mailmap` command is given multiple times to\n\ttoggle it off and then on back again.\n\nwould be sufficient (I would omit \"even after ...\" part, if I were\nwriting it).  What is more important than the optimization aspect of\nthis implementation detail to end users is that we do not re-read,\nso if you update the file while you are running \"cat-file --batch\",\neven giving 'mailmap off; mailmap on' would not cause it to re-read\nthe updated data, and \"upon the first use and only once\" should be\nsufficient to understand that.\n\nThe implementation looks great.  I do not recall how good the tests\nwere but this round does not change anything there since the\nprevious iteration.\n"},{"id":"541707","messageId":"3e07118b-f98a-4bf2-ac7a-39c1f114a651@gmail.com","threadId":"65377","inReplyTo":"xmqqa4v46ptu.fsf@gitster.g","subject":"Re: [PATCH v4 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-04-16T03:08:36Z","receivedAt":"2026-04-16T03:08:42Z","isPatch":true,"body":"\n\nOn 15/04/26 23:58, Junio C Hamano wrote:\n> Siddharth Asthana <siddharthasthana31@gmail.com> writes:\n> \n>> diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc\n>> index c139f55a16..0f499c9d1b 100644\n>> --- a/Documentation/git-cat-file.adoc\n>> +++ b/Documentation/git-cat-file.adoc\n>> @@ -174,6 +174,18 @@ flush::\n>>   \tsince the beginning or since the last flush was issued. When `--buffer`\n>>   \tis used, no output will come until a `flush` is issued. When `--buffer`\n>>   \tis not used, commands are flushed each time without issuing `flush`.\n>> +\n>> +`mailmap (<bool>)`::\n>> +\tEnable or disable mailmap for subsequent commands. The `<bool>`\n>> +\targument accepts the same boolean values as linkgit:git-config[1].\n>> +\tPossible effects are:\n>> ++\n>> +`true`;;\n>> +\tMailmap data is loaded on first use and kept in memory until the\n>> +\tprocess exits. Passing `true` again does not reload the data.\n>> +`false`;;\n>> +\tMailmap replacements are disabled for subsequent commands, but data\n>> +\talready loaded stays in memory.\n>>   --\n>>   +\n> \n> While the above may not be telling any lies, I think the focus of\n> the explanation is placed on a wrong thing.  What primarily matters\n> to end-users is that toggling 'mailmap' to true makes the mailmap\n> applied to identities before they appear in the output and false\n> makes the identities output without modification.  The fact that you\n\n\nMake sense, the sub-list was over-explaining implementation details that \nusers don't need to care about.\n\n\n> read the mailmap data only once and keep it around even when\n> toggling the feature off, just in case the feature gets turned on\n> again, is an implementation detail that is of much lessor interest\n> to end users, no?\n> \n> Perhaps delete everything from \"Possible effects are\" and replace it\n> with a brief explanation, e.g.,\n> \n> `mailmap (<bool>)`::\n> \tEnable or disable mailmap for subsequent commands. The `<bool>`\n> \targument accepts the same boolean values as linkgit:git-config[1].\n> \tThe mailmap data is read upon the first use and only once,\n> \teven after the `mailmap` command is given multiple times to\n> \ttoggle it off and then on back again.\n> \n> would be sufficient (I would omit \"even after ...\" part, if I were\n> writing it).  What is more important than the optimization aspect of\n\n\n\nAgreed, I wend with the shorter version without the \"even after\" part.\n\n\n> this implementation detail to end users is that we do not re-read,\n> so if you update the file while you are running \"cat-file --batch\",\n> even giving 'mailmap off; mailmap on' would not cause it to re-read\n> the updated data, and \"upon the first use and only once\" should be\n> sufficient to understand that.\n> \n> The implementation looks great.  I do not recall how good the tests\n> were but this round does not change anything there since the\n> previous iteration.\n\n\nThnaks! I will send v5 with just this doc change.\n\nSiddharth\n\n\n"},{"id":"541708","messageId":"20260416033250.4327-1-siddharthasthana31@gmail.com","threadId":"65377","inReplyTo":"20260415150943.40493-1-siddharthasthana31@gmail.com","subject":"[PATCH v5 0/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-04-16T03:32:49Z","receivedAt":"2026-04-16T03:32:55Z","isPatch":true,"body":"git-cat-file(1)'s --batch-command works with the --use-mailmap option,\nbut this option needs to be set when the process is created. This means\nwe cannot change this option mid-operation.\n\nAt GitLab, Gitaly keeps interacting with a long-lived git-cat-file\nprocess and it would be useful if --batch-command supported toggling\nmailmap dynamically on an existing process.\n\nThis patch adds a `mailmap` subcommand to --batch-command that accepts\na boolean argument and toggles mailmap dynamically for subsequent\ncommands.\n\nThe series is based on top of 5361983c07 (The 22nd batch, 2026-03-21).\n\nCI: https://gitlab.com/gitlab-org/git/-/pipelines/2456596910\n\nChanges in v5:\n- Simplify documentation: remove the `;;` sub-list describing\n  `true`/`false` effects and replace with a single sentence noting\n  that mailmap data is read upon the first use and only once.\n- Link to v4: https://lore.kernel.org/git/20260415150943.40493-1-siddharthasthana31@gmail.com/T/#m5226263dafcf5c774c080a6688e9af0f402003c0\n- Link to v3: https://lore.kernel.org/git/xmqqv7dyoei6.fsf@gitster.g/T/#m0a109f3eb5129e619ecec5f2d58ead0c5a49a4f3\n- Link to v2: https://lore.kernel.org/git/xmqqv7dyoei6.fsf@gitster.g/T/#m445eab3b309bded92d1b130d225b882c73988ff2\n- Link to v1: https://public-inbox.org/git/a4ec7bfa-f16b-4505-9b37-d3dd137e93cb@gmail.com/T/#m5c62fb6ad0fbcc99a706dba4c78b66359c247acd\n\nThanks,\nSiddharth\n\n---\nSiddharth Asthana (1):\n  cat-file: add mailmap subcommand to --batch-command\n\n Documentation/git-cat-file.adoc |   5 ++\n builtin/cat-file.c              |  37 ++++++++++++--\n t/t4203-mailmap.sh              | 105 ++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 143 insertions(+), 4 deletions(-)\n\nRange-diff versus v4:\n\n1:  25ebffe39e ! 1:  b4d6f08b43 cat-file: add mailmap subcommand to --batch-command\n    @@ Documentation/git-cat-file.adoc: flush::\n     +`mailmap (<bool>)`::\n     +\tEnable or disable mailmap for subsequent commands. The `<bool>`\n     +\targument accepts the same boolean values as linkgit:git-config[1].\n    -+\tPossible effects are:\n    -++\n    -+`true`;;\n    -+\tMailmap data is loaded on first use and kept in memory until the\n    -+\tprocess exits. Passing `true` again does not reload the data.\n    -+`false`;;\n    -+\tMailmap replacements are disabled for subsequent commands, but data\n    -+\talready loaded stays in memory.\n    ++\tThe mailmap data is read upon the first use and only once.\n      --\n      +\n      \n\nbase-commit: 5361983c075154725be47b65cca9a2421789e410\n-- \n2.53.0\n"},{"id":"541709","messageId":"20260416033250.4327-2-siddharthasthana31@gmail.com","threadId":"65377","inReplyTo":"20260416033250.4327-1-siddharthasthana31@gmail.com","subject":"[PATCH v5 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Siddharth Asthana","fromEmail":"siddharthasthana31@gmail.com","sentAt":"2026-04-16T03:32:50Z","receivedAt":"2026-04-16T03:33:00Z","isPatch":true,"body":"git-cat-file(1)'s --batch-command works with the --use-mailmap option,\nbut this option needs to be set when the process is created. This means\nwe cannot change this option mid-operation.\n\nAt GitLab, Gitaly keeps interacting with a long-lived git-cat-file\nprocess and it would be useful if --batch-command supported toggling\nmailmap dynamically on an existing process.\n\nAdd a `mailmap` subcommand to --batch-command that takes a boolean\nargument (usual ways you can specify a boolean value like 'yes', 'true',\netc., are supported). Mailmap data is loaded lazily and kept in memory,\nwhile a helper centralizes the one-time load path used both at startup\nand from the batch-command handler.\n\nExtend tests to cover runtime toggling, startup option interactions\n(`--mailmap`/`--no-mailmap`), accepted boolean forms, and invalid values.\n\nSigned-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n---\nCI: https://gitlab.com/gitlab-org/git/-/pipelines/2456596910\n\n Documentation/git-cat-file.adoc |   5 ++\n builtin/cat-file.c              |  37 +++++++++--\n t/t4203-mailmap.sh              | 105 ++++++++++++++++++++++++++++++++\n 3 files changed, 143 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc\nindex c139f55a16..86b9181599 100644\n--- a/Documentation/git-cat-file.adoc\n+++ b/Documentation/git-cat-file.adoc\n@@ -174,6 +174,11 @@ flush::\n \tsince the beginning or since the last flush was issued. When `--buffer`\n \tis used, no output will come until a `flush` is issued. When `--buffer`\n \tis not used, commands are flushed each time without issuing `flush`.\n+\n+`mailmap (<bool>)`::\n+\tEnable or disable mailmap for subsequent commands. The `<bool>`\n+\targument accepts the same boolean values as linkgit:git-config[1].\n+\tThe mailmap data is read upon the first use and only once.\n --\n +\n \ndiff --git a/builtin/cat-file.c b/builtin/cat-file.c\nindex d9fbad5358..fa45f774d7 100644\n--- a/builtin/cat-file.c\n+++ b/builtin/cat-file.c\n@@ -57,6 +57,20 @@ static int use_mailmap;\n \n static char *replace_idents_using_mailmap(char *, size_t *);\n \n+/*\n+ * The mailmap is initialized with .strdup_strings set to 0,\n+ * but read_mailmap() sets the bit to 1 (this is true even when\n+ * not a single mailmap entry is read), so it can be used for\n+ * lazy loading.\n+ */\n+static void load_mailmap(void)\n+{\n+\tif (mailmap.strdup_strings)\n+\t\treturn;\n+\n+\tread_mailmap(the_repository, &mailmap);\n+}\n+\n static char *replace_idents_using_mailmap(char *object_buf, size_t *size)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n@@ -692,6 +706,20 @@ static void parse_cmd_info(struct batch_options *opt,\n \tbatch_one_object(line, output, opt, data);\n }\n \n+static void parse_cmd_mailmap(struct batch_options *opt UNUSED,\n+\t\t\t      const char *line,\n+\t\t\t      struct strbuf *output UNUSED,\n+\t\t\t      struct expand_data *data UNUSED)\n+{\n+\tuse_mailmap = git_parse_maybe_bool(line);\n+\n+\tif (use_mailmap < 0)\n+\t\tdie(_(\"mailmap: invalid boolean '%s'\"), line);\n+\n+\tif (use_mailmap)\n+\t\tload_mailmap();\n+}\n+\n static void dispatch_calls(struct batch_options *opt,\n \t\tstruct strbuf *output,\n \t\tstruct expand_data *data,\n@@ -725,9 +753,10 @@ static const struct parse_cmd {\n \tparse_cmd_fn_t fn;\n \tunsigned takes_args;\n } commands[] = {\n-\t{ \"contents\", parse_cmd_contents, 1},\n-\t{ \"info\", parse_cmd_info, 1},\n-\t{ \"flush\", NULL, 0},\n+\t{ \"contents\", parse_cmd_contents, 1 },\n+\t{ \"info\", parse_cmd_info, 1 },\n+\t{ \"flush\", NULL, 0 },\n+\t{ \"mailmap\", parse_cmd_mailmap, 1 },\n };\n \n static void batch_objects_command(struct batch_options *opt,\n@@ -1131,7 +1160,7 @@ int cmd_cat_file(int argc,\n \topt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');\n \n \tif (use_mailmap)\n-\t\tread_mailmap(the_repository, &mailmap);\n+\t\tload_mailmap();\n \n \tswitch (batch.objects_filter.choice) {\n \tcase LOFC_DISABLED:\ndiff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh\nindex 74b7ddccb2..249548eb9b 100755\n--- a/t/t4203-mailmap.sh\n+++ b/t/t4203-mailmap.sh\n@@ -1133,6 +1133,111 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"info HEAD\\nmailmap yes\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n+\techo $commit_sha commit $size_no_mailmap >expect &&\n+\techo $commit_sha commit $size_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\n\" | git cat-file --batch-command >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"mailmap yes\\ninfo HEAD\\nmailmap no\\ninfo HEAD\\nflush\\n\" | git cat-file --batch-command --buffer >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap no overrides startup --mailmap' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tprintf \"info HEAD\\nmailmap no\\ninfo HEAD\\n\" | \\\n+\t\tgit cat-file --mailmap --batch-command >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap yes overrides startup --no-mailmap' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"info HEAD\\nmailmap yes\\ninfo HEAD\\n\" | \\\n+\t\tgit cat-file --no-mailmap --batch-command >actual &&\n+\techo $commit_sha commit $size_no_mailmap >expect &&\n+\techo $commit_sha commit $size_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap accepts true/false' '\n+\ttest_when_finished \"rm .mailmap\" &&\n+\tcat >.mailmap <<-\\EOF &&\n+\tC O Mitter <committer@example.com> Orig <orig@example.com>\n+\tEOF\n+\tcommit_sha=$(git rev-parse HEAD) &&\n+\tgit cat-file commit HEAD >commit_no_mailmap.out &&\n+\tsize_no_mailmap=$(wc -c <commit_no_mailmap.out) &&\n+\tgit cat-file --use-mailmap commit HEAD >commit_mailmap.out &&\n+\tsize_mailmap=$(wc -c <commit_mailmap.out) &&\n+\tprintf \"mailmap true\\ninfo HEAD\\nmailmap false\\ninfo HEAD\\n\" | \\\n+\t\tgit cat-file --batch-command >actual &&\n+\techo $commit_sha commit $size_mailmap >expect &&\n+\techo $commit_sha commit $size_no_mailmap >>expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success 'git cat-file --batch-command mailmap rejects invalid boolean' '\n+\techo \"mailmap maybe\" >in &&\n+\ttest_must_fail git cat-file --batch-command <in 2>err &&\n+\ttest_grep \"mailmap: invalid boolean .*maybe\" err\n+'\n+\n test_expect_success 'git cat-file --mailmap works with different author and committer' '\n \ttest_when_finished \"rm .mailmap\" &&\n \tcat >.mailmap <<-\\EOF &&\n-- \n2.53.0\n\n"},{"id":"543724","messageId":"xmqqwlwy4v7t.fsf@gitster.g","threadId":"65377","inReplyTo":"20260416033250.4327-2-siddharthasthana31@gmail.com","subject":"Re: [PATCH v5 1/1] cat-file: add mailmap subcommand to --batch-command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-05-20T03:26:46Z","receivedAt":"2026-05-20T03:26:50Z","isPatch":true,"body":"Siddharth Asthana <siddharthasthana31@gmail.com> writes:\n\n> git-cat-file(1)'s --batch-command works with the --use-mailmap option,\n> but this option needs to be set when the process is created. This means\n> we cannot change this option mid-operation.\n>\n> At GitLab, Gitaly keeps interacting with a long-lived git-cat-file\n> process and it would be useful if --batch-command supported toggling\n> mailmap dynamically on an existing process.\n>\n> Add a `mailmap` subcommand to --batch-command that takes a boolean\n> argument (usual ways you can specify a boolean value like 'yes', 'true',\n> etc., are supported). Mailmap data is loaded lazily and kept in memory,\n> while a helper centralizes the one-time load path used both at startup\n> and from the batch-command handler.\n>\n> Extend tests to cover runtime toggling, startup option interactions\n> (`--mailmap`/`--no-mailmap`), accepted boolean forms, and invalid values.\n>\n> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>\n> ---\n> CI: https://gitlab.com/gitlab-org/git/-/pipelines/2456596910\n\nI do not think we have heard any comment on this iteration, and it\nseems to address the points raised in the reviews in previous\nrounds.  Shall we mark the topic for 'next'?\n\nThanks.\n"}]}