* [PATCH v1 1/1] cat-file: add use-mailmap/no-use-mailmap to --batch-command @ 2026-03-28 20:36 Siddharth Asthana 2026-03-29 0:50 ` Junio C Hamano 2026-03-29 8:28 ` [PATCH v2 0/1] cat-file: add mailmap subcommand " Siddharth Asthana 0 siblings, 2 replies; 27+ messages in thread From: Siddharth Asthana @ 2026-03-28 20:36 UTC (permalink / raw) To: git; +Cc: karthik.188, christian.couder, ps, gitster, toon, Siddharth Asthana git-cat-file(1)'s --batch-command works with the --use-mailmap option, but this option needs to be set when the process is created. This means we cannot change this option mid-operation. At GitLab, Gitaly caches git-cat-file processes and it would be useful if --batch-command supported toggling mailmap dynamically with existing processes. Add `use-mailmap` and `no-use-mailmap` as new subcommands to --batch-command. `use-mailmap` enables the mailmap mechanism for subsequent `contents` and `info` commands, lazily loading the mailmap data from disk on first invocation. `no-use-mailmap` disables it but keeps the data in memory so re-enabling doesn't require reloading. The subcommand names mirror the existing --use-mailmap/--no-use-mailmap CLI options to keep the interface consistent. Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> --- CI: https://gitlab.com/gitlab-org/git/-/pipelines/2415084557 Documentation/git-cat-file.adoc | 9 +++++++ builtin/cat-file.c | 33 ++++++++++++++++++++--- t/t4203-mailmap.sh | 48 +++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 4 deletions(-) diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc index c139f55a16..03aadbbe89 100644 --- a/Documentation/git-cat-file.adoc +++ b/Documentation/git-cat-file.adoc @@ -174,6 +174,15 @@ flush:: since the beginning or since the last flush was issued. When `--buffer` is used, no output will come until a `flush` is issued. When `--buffer` is not used, commands are flushed each time without issuing `flush`. + +use-mailmap:: + Enable mailmap for subsequent `contents` and `info` commands. If the + mailmap has not been loaded yet, it is read from disk at this point. + +no-use-mailmap:: + Disable mailmap for subsequent `contents` and `info` commands. The + mailmap data is kept in memory so that a later `use-mailmap` command + does not need to reload it from disk. -- + diff --git a/builtin/cat-file.c b/builtin/cat-file.c index b6f12f41d6..7772d4d41b 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -54,6 +54,7 @@ static const char *force_path; static struct string_list mailmap = STRING_LIST_INIT_NODUP; static int use_mailmap; +static int mailmap_loaded; static char *replace_idents_using_mailmap(char *, size_t *); @@ -692,6 +693,26 @@ static void parse_cmd_info(struct batch_options *opt, batch_one_object(line, output, opt, data); } +static void parse_cmd_use_mailmap(struct batch_options *opt UNUSED, + const char *line UNUSED, + struct strbuf *output UNUSED, + struct expand_data *data UNUSED) +{ + if (!mailmap_loaded) { + read_mailmap(the_repository, &mailmap); + mailmap_loaded = 1; + } + use_mailmap = 1; +} + +static void parse_cmd_disable_mailmap(struct batch_options *opt UNUSED, + const char *line UNUSED, + struct strbuf *output UNUSED, + struct expand_data *data UNUSED) +{ + use_mailmap = 0; +} + static void dispatch_calls(struct batch_options *opt, struct strbuf *output, struct expand_data *data, @@ -725,9 +746,11 @@ static const struct parse_cmd { parse_cmd_fn_t fn; unsigned takes_args; } commands[] = { - { "contents", parse_cmd_contents, 1}, - { "info", parse_cmd_info, 1}, - { "flush", NULL, 0}, + { "contents", parse_cmd_contents, 1 }, + { "info", parse_cmd_info, 1 }, + { "flush", NULL, 0 }, + { "use-mailmap", parse_cmd_use_mailmap, 0 }, + { "no-use-mailmap", parse_cmd_disable_mailmap, 0 }, }; static void batch_objects_command(struct batch_options *opt, @@ -1127,8 +1150,10 @@ int cmd_cat_file(int argc, opt_cw = (opt == 'c' || opt == 'w'); opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's'); - if (use_mailmap) + if (use_mailmap) { read_mailmap(the_repository, &mailmap); + mailmap_loaded = 1; + } switch (batch.objects_filter.choice) { case LOFC_DISABLED: diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 74b7ddccb2..2ae063e5c3 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -1133,6 +1133,54 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us test_cmp expect actual ' +test_expect_success 'git cat-file --batch-command use-mailmap enables mailmap mid-stream' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "info HEAD\nuse-mailmap\ninfo HEAD\n" | git cat-file --batch-command >actual && + echo $commit_sha commit $size_no_mailmap >expect && + echo $commit_sha commit $size_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command no-use-mailmap disables mailmap mid-stream' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "use-mailmap\ninfo HEAD\nno-use-mailmap\ninfo HEAD\n" | git cat-file --batch-command >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command use-mailmap works in --buffer mode' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "use-mailmap\ninfo HEAD\nno-use-mailmap\ninfo HEAD\nflush\n" | git cat-file --batch-command --buffer >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + test_expect_success 'git cat-file --mailmap works with different author and committer' ' test_when_finished "rm .mailmap" && cat >.mailmap <<-\EOF && -- 2.51.0 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH v1 1/1] cat-file: add use-mailmap/no-use-mailmap to --batch-command 2026-03-28 20:36 [PATCH v1 1/1] cat-file: add use-mailmap/no-use-mailmap to --batch-command Siddharth Asthana @ 2026-03-29 0:50 ` Junio C Hamano 2026-03-29 7:25 ` Siddharth Asthana 2026-03-29 8:28 ` [PATCH v2 0/1] cat-file: add mailmap subcommand " Siddharth Asthana 1 sibling, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2026-03-29 0:50 UTC (permalink / raw) To: Siddharth Asthana; +Cc: git, karthik.188, christian.couder, ps, toon Siddharth Asthana <siddharthasthana31@gmail.com> writes: > git-cat-file(1)'s --batch-command works with the --use-mailmap option, > but this option needs to be set when the process is created. This means > we cannot change this option mid-operation. > > At GitLab, Gitaly caches git-cat-file processes and it would be useful > if --batch-command supported toggling mailmap dynamically with existing > processes. > > Add `use-mailmap` and `no-use-mailmap` as new subcommands to > --batch-command. `use-mailmap` enables the mailmap mechanism for > subsequent `contents` and `info` commands, lazily loading the mailmap > data from disk on first invocation. `no-use-mailmap` disables it but > keeps the data in memory so re-enabling doesn't require reloading. And the cached information in process, if any, would be flushed? Because in your design, these command words are parsed separately from and have nothing in common with the command line options, I wonder if it is easier to understand if you added just a single command, "mailmap", that takes a single parameter "yes" or "no"? Then this hunk would ... > + { "contents", parse_cmd_contents, 1 }, > + { "info", parse_cmd_info, 1 }, > + { "flush", NULL, 0 }, > + { "use-mailmap", parse_cmd_use_mailmap, 0 }, > + { "no-use-mailmap", parse_cmd_disable_mailmap, 0 }, ... need only one addition instead of two entries and you do not have to write boilerplate-rich helper functions twice. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v1 1/1] cat-file: add use-mailmap/no-use-mailmap to --batch-command 2026-03-29 0:50 ` Junio C Hamano @ 2026-03-29 7:25 ` Siddharth Asthana 2026-03-29 20:55 ` Junio C Hamano 0 siblings, 1 reply; 27+ messages in thread From: Siddharth Asthana @ 2026-03-29 7:25 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, karthik.188, christian.couder, ps, toon On 29/03/26 06:20, Junio C Hamano wrote: > Siddharth Asthana <siddharthasthana31@gmail.com> writes: > >> git-cat-file(1)'s --batch-command works with the --use-mailmap option, >> but this option needs to be set when the process is created. This means >> we cannot change this option mid-operation. >> >> At GitLab, Gitaly caches git-cat-file processes and it would be useful >> if --batch-command supported toggling mailmap dynamically with existing >> processes. >> >> Add `use-mailmap` and `no-use-mailmap` as new subcommands to >> --batch-command. `use-mailmap` enables the mailmap mechanism for >> subsequent `contents` and `info` commands, lazily loading the mailmap >> data from disk on first invocation. `no-use-mailmap` disables it but >> keeps the data in memory so re-enabling doesn't require reloading. > > And the cached information in process, if any, would be flushed? No. The mailmap data is kept in memory. Turning it off only disables application of mailmap; turning it back on reuses already loaded data. > > Because in your design, these command words are parsed separately > from and have nothing in common with the command line options, I > wonder if it is easier to understand if you added just a single > command, "mailmap", that takes a single parameter "yes" or "no"? Agreed, this is cleaner. I will rerolled this as a single `mailmap` subcommand with `yes|no`, so the dispatch table has one entry and the handling is in one function I'll send v2 with this update. Thanks, Siddharth > Then this hunk would ... > >> + { "contents", parse_cmd_contents, 1 }, >> + { "info", parse_cmd_info, 1 }, >> + { "flush", NULL, 0 }, >> + { "use-mailmap", parse_cmd_use_mailmap, 0 }, >> + { "no-use-mailmap", parse_cmd_disable_mailmap, 0 }, > > ... need only one addition instead of two entries and you do not > have to write boilerplate-rich helper functions twice. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v1 1/1] cat-file: add use-mailmap/no-use-mailmap to --batch-command 2026-03-29 7:25 ` Siddharth Asthana @ 2026-03-29 20:55 ` Junio C Hamano 0 siblings, 0 replies; 27+ messages in thread From: Junio C Hamano @ 2026-03-29 20:55 UTC (permalink / raw) To: Siddharth Asthana; +Cc: git, karthik.188, christian.couder, ps, toon Siddharth Asthana <siddharthasthana31@gmail.com> writes: >> And the cached information in process, if any, would be flushed? > > No. The mailmap data is kept in memory. Turning it off only disables > application of mailmap; turning it back on reuses already loaded data. I was asking if the rewritten commmit objects were kept around in memory and how long; after you show an object once with mapped author data, toggled the mailmap use, and then try to show the same object again, you would want to avoid reusing the mapped result again. But it turns out that the command, with or without your patch, reads the object data and maps the author/commit in it every time an object is requested. In fact, in a bad case, I think it calls replace_idents_using_mailmap() twice, once in batch_object_write() only to grab the size of the munged object, then again in print_object_or_die() for both contents and the size. So there is no "tainted data retained across the mode switch" problem. ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 0/1] cat-file: add mailmap subcommand to --batch-command 2026-03-28 20:36 [PATCH v1 1/1] cat-file: add use-mailmap/no-use-mailmap to --batch-command Siddharth Asthana 2026-03-29 0:50 ` Junio C Hamano @ 2026-03-29 8:28 ` Siddharth Asthana 2026-03-29 8:28 ` [PATCH v2 1/1] " Siddharth Asthana 2026-03-31 12:11 ` [PATCH v3 0/1] " Siddharth Asthana 1 sibling, 2 replies; 27+ messages in thread From: Siddharth Asthana @ 2026-03-29 8:28 UTC (permalink / raw) To: git; +Cc: karthik.188, christian.couder, ps, gitster, toon, Siddharth Asthana git-cat-file(1)'s --batch-command works with the --use-mailmap option, but this option needs to be set when the process is created. This means we cannot change this option mid-operation. At GitLab, Gitaly caches git-cat-file processes and it would be useful if --batch-command supported toggling mailmap dynamically with existing processes. This patch adds a `mailmap` subcommand to --batch-command that takes `yes` or `no` as its argument. When enabled, mailmap data is loaded from disk on first use and kept in memory so that toggling back on does not require reloading. The series is based on top of 5361983c07 (The 22nd batch, 2026-03-21). CI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861 Changes in v2: - Replace two separate `use-mailmap` / `no-use-mailmap` zero-argument subcommands with a single `mailmap` subcommand that takes `yes` or `no` as its argument. This reduces the dispatch table to one entry and the implementation to one function. - Link to v1: https://public-inbox.org/git/a4ec7bfa-f16b-4505-9b37-d3dd137e93cb@gmail.com/T/#m5c62fb6ad0fbcc99a706dba4c78b66359c247acd Thanks, Siddharth --- Siddharth Asthana (1): cat-file: add mailmap subcommand to --batch-command Documentation/git-cat-file.adoc | 7 +++++ builtin/cat-file.c | 30 ++++++++++++++++++--- t/t4203-mailmap.sh | 48 +++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 4 deletions(-) Range-diff versus v1: 1: 39f40e9cb7 ! 1: 936ca27419 cat-file: add use-mailmap/no-use-mailmap to --batch-command @@ Metadata Author: Siddharth Asthana <siddharthasthana31@gmail.com> ## Commit message ## - cat-file: add use-mailmap/no-use-mailmap to --batch-command + cat-file: add mailmap subcommand to --batch-command git-cat-file(1)'s --batch-command works with the --use-mailmap option, but this option needs to be set when the process is created. This means @@ Commit message if --batch-command supported toggling mailmap dynamically with existing processes. - Add `use-mailmap` and `no-use-mailmap` as new subcommands to - --batch-command. `use-mailmap` enables the mailmap mechanism for - subsequent `contents` and `info` commands, lazily loading the mailmap - data from disk on first invocation. `no-use-mailmap` disables it but - keeps the data in memory so re-enabling doesn't require reloading. - - The subcommand names mirror the existing --use-mailmap/--no-use-mailmap - CLI options to keep the interface consistent. + Add a `mailmap` subcommand to --batch-command that takes a single + argument: `yes` to enable mailmap and `no` to disable it. When enabled, + mailmap data is loaded from disk on first use and kept in memory so that + toggling back on does not require reloading. + Suggested-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> @@ Documentation/git-cat-file.adoc: flush:: is used, no output will come until a `flush` is issued. When `--buffer` is not used, commands are flushed each time without issuing `flush`. + -+use-mailmap:: -+ Enable mailmap for subsequent `contents` and `info` commands. If the -+ mailmap has not been loaded yet, it is read from disk at this point. -+ -+no-use-mailmap:: -+ Disable mailmap for subsequent `contents` and `info` commands. The -+ mailmap data is kept in memory so that a later `use-mailmap` command -+ does not need to reload it from disk. ++mailmap <yes|no>:: ++ Enable or disable mailmap for subsequent `contents` and `info` ++ commands. When `yes` is given, mailmap data is loaded from disk on ++ first use and kept in memory; passing `yes` again does not reload it. ++ When `no` is given, mailmap is disabled but the data stays in memory ++ so that a later `mailmap yes` does not need to reload it from disk. -- @@ builtin/cat-file.c: static void parse_cmd_info(struct batch_options *opt, batch_one_object(line, output, opt, data); } -+static void parse_cmd_use_mailmap(struct batch_options *opt UNUSED, -+ const char *line UNUSED, -+ struct strbuf *output UNUSED, -+ struct expand_data *data UNUSED) ++static void parse_cmd_mailmap(struct batch_options *opt UNUSED, ++ const char *line, ++ struct strbuf *output UNUSED, ++ struct expand_data *data UNUSED) +{ -+ if (!mailmap_loaded) { -+ read_mailmap(the_repository, &mailmap); -+ mailmap_loaded = 1; ++ if (!strcmp(line, "yes")) { ++ if (!mailmap_loaded) { ++ read_mailmap(the_repository, &mailmap); ++ mailmap_loaded = 1; ++ } ++ use_mailmap = 1; ++ } else if (!strcmp(line, "no")) { ++ use_mailmap = 0; ++ } else { ++ die(_("mailmap: unknown argument '%s', expected 'yes' or 'no'"), line); + } -+ use_mailmap = 1; -+} -+ -+static void parse_cmd_disable_mailmap(struct batch_options *opt UNUSED, -+ const char *line UNUSED, -+ struct strbuf *output UNUSED, -+ struct expand_data *data UNUSED) -+{ -+ use_mailmap = 0; +} @@ builtin/cat-file.c: static const struct parse_cmd { + { "contents", parse_cmd_contents, 1 }, + { "info", parse_cmd_info, 1 }, + { "flush", NULL, 0 }, -+ { "use-mailmap", parse_cmd_use_mailmap, 0 }, -+ { "no-use-mailmap", parse_cmd_disable_mailmap, 0 }, ++ { "mailmap", parse_cmd_mailmap, 1 }, }; @@ t/t4203-mailmap.sh: test_expect_success 'git cat-file --batch-command returns co -+test_expect_success 'git cat-file --batch-command use-mailmap enables mailmap mid-stream' ' ++test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' ' + ... -+ printf "info HEAD\nuse-mailmap\ninfo HEAD\n" | git cat-file --batch-command >actual && ++ printf "info HEAD\nmailmap yes\ninfo HEAD\n" | git cat-file --batch-command >actual && -+test_expect_success 'git cat-file --batch-command no-use-mailmap disables mailmap mid-stream' ' ++test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' ' + ... -+ printf "use-mailmap\ninfo HEAD\nno-use-mailmap\ninfo HEAD\n" | git cat-file --batch-command >actual && ++ printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\n" | git cat-file --batch-command >actual && -+test_expect_success 'git cat-file --batch-command use-mailmap works in --buffer mode' ' ++test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' ' + ... -+ printf "use-mailmap\ninfo HEAD\nno-use-mailmap\ninfo HEAD\nflush\n" | git cat-file --batch-command --buffer >actual && ++ printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\nflush\n" | git cat-file --batch-command --buffer >actual && base-commit: 5361983c075154725be47b65cca9a2421789e410 -- 2.51.0 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-29 8:28 ` [PATCH v2 0/1] cat-file: add mailmap subcommand " Siddharth Asthana @ 2026-03-29 8:28 ` Siddharth Asthana 2026-03-30 2:12 ` Junio C Hamano ` (3 more replies) 2026-03-31 12:11 ` [PATCH v3 0/1] " Siddharth Asthana 1 sibling, 4 replies; 27+ messages in thread From: Siddharth Asthana @ 2026-03-29 8:28 UTC (permalink / raw) To: git; +Cc: karthik.188, christian.couder, ps, gitster, toon, Siddharth Asthana git-cat-file(1)'s --batch-command works with the --use-mailmap option, but this option needs to be set when the process is created. This means we cannot change this option mid-operation. At GitLab, Gitaly caches git-cat-file processes and it would be useful if --batch-command supported toggling mailmap dynamically with existing processes. Add a `mailmap` subcommand to --batch-command that takes a single argument: `yes` to enable mailmap and `no` to disable it. When enabled, mailmap data is loaded from disk on first use and kept in memory so that toggling back on does not require reloading. Suggested-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> --- CI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861 Documentation/git-cat-file.adoc | 7 +++++ builtin/cat-file.c | 30 ++++++++++++++++++--- t/t4203-mailmap.sh | 48 +++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 4 deletions(-) diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc index c139f55a16..af32e929a8 100644 --- a/Documentation/git-cat-file.adoc +++ b/Documentation/git-cat-file.adoc @@ -174,6 +174,13 @@ flush:: since the beginning or since the last flush was issued. When `--buffer` is used, no output will come until a `flush` is issued. When `--buffer` is not used, commands are flushed each time without issuing `flush`. + +mailmap <yes|no>:: + Enable or disable mailmap for subsequent `contents` and `info` + commands. When `yes` is given, mailmap data is loaded from disk on + first use and kept in memory; passing `yes` again does not reload it. + When `no` is given, mailmap is disabled but the data stays in memory + so that a later `mailmap yes` does not need to reload it from disk. -- + diff --git a/builtin/cat-file.c b/builtin/cat-file.c index b6f12f41d6..a53926d2bb 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -54,6 +54,7 @@ static const char *force_path; static struct string_list mailmap = STRING_LIST_INIT_NODUP; static int use_mailmap; +static int mailmap_loaded; static char *replace_idents_using_mailmap(char *, size_t *); @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt, batch_one_object(line, output, opt, data); } +static void parse_cmd_mailmap(struct batch_options *opt UNUSED, + const char *line, + struct strbuf *output UNUSED, + struct expand_data *data UNUSED) +{ + if (!strcmp(line, "yes")) { + if (!mailmap_loaded) { + read_mailmap(the_repository, &mailmap); + mailmap_loaded = 1; + } + use_mailmap = 1; + } else if (!strcmp(line, "no")) { + use_mailmap = 0; + } else { + die(_("mailmap: unknown argument '%s', expected 'yes' or 'no'"), line); + } +} + static void dispatch_calls(struct batch_options *opt, struct strbuf *output, struct expand_data *data, @@ -725,9 +744,10 @@ static const struct parse_cmd { parse_cmd_fn_t fn; unsigned takes_args; } commands[] = { - { "contents", parse_cmd_contents, 1}, - { "info", parse_cmd_info, 1}, - { "flush", NULL, 0}, + { "contents", parse_cmd_contents, 1 }, + { "info", parse_cmd_info, 1 }, + { "flush", NULL, 0 }, + { "mailmap", parse_cmd_mailmap, 1 }, }; static void batch_objects_command(struct batch_options *opt, @@ -1127,8 +1147,10 @@ int cmd_cat_file(int argc, opt_cw = (opt == 'c' || opt == 'w'); opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's'); - if (use_mailmap) + if (use_mailmap) { read_mailmap(the_repository, &mailmap); + mailmap_loaded = 1; + } switch (batch.objects_filter.choice) { case LOFC_DISABLED: diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 74b7ddccb2..f66637cd86 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -1133,6 +1133,54 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us test_cmp expect actual ' +test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "info HEAD\nmailmap yes\ninfo HEAD\n" | git cat-file --batch-command >actual && + echo $commit_sha commit $size_no_mailmap >expect && + echo $commit_sha commit $size_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\n" | git cat-file --batch-command >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\nflush\n" | git cat-file --batch-command --buffer >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + test_expect_success 'git cat-file --mailmap works with different author and committer' ' test_when_finished "rm .mailmap" && cat >.mailmap <<-\EOF && -- 2.51.0 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-29 8:28 ` [PATCH v2 1/1] " Siddharth Asthana @ 2026-03-30 2:12 ` Junio C Hamano 2026-03-31 1:40 ` Siddharth Asthana 2026-03-30 9:44 ` Karthik Nayak ` (2 subsequent siblings) 3 siblings, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2026-03-30 2:12 UTC (permalink / raw) To: Siddharth Asthana; +Cc: git, karthik.188, christian.couder, ps, toon Siddharth Asthana <siddharthasthana31@gmail.com> writes: > git-cat-file(1)'s --batch-command works with the --use-mailmap option, > but this option needs to be set when the process is created. This means > we cannot change this option mid-operation. > > At GitLab, Gitaly caches git-cat-file processes and it would be useful Would "keeps interacting with a single 'cat-file' process" be more accurate than "caches"? The latter gives, at least to me, connotations that may not be necessarily true, like (1) there is a pool of cat-file processes waiting for Gitaly to connect and serve, (2) a running Gitaly may decide to disconnect from cat-file from time to time, and then reconnect to one of them when it becomes necessary again, etc. > if --batch-command supported toggling mailmap dynamically with existing > processes. > > Add a `mailmap` subcommand to --batch-command that takes a single > argument: `yes` to enable mailmap and `no` to disable it. When enabled, > mailmap data is loaded from disk on first use and kept in memory so that > toggling back on does not require reloading. > > Suggested-by: Junio C Hamano <gitster@pobox.com> This is over-crediting me. The idea to unify the two commands into one may have come from me, but that is at most helped-by but it is perfectly fine without any credit. > Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> > --- > diff --git a/builtin/cat-file.c b/builtin/cat-file.c > index b6f12f41d6..a53926d2bb 100644 > --- a/builtin/cat-file.c > +++ b/builtin/cat-file.c > @@ -54,6 +54,7 @@ static const char *force_path; > > static struct string_list mailmap = STRING_LIST_INIT_NODUP; > static int use_mailmap; > +static int mailmap_loaded; Not part of this topic, but in case less experienced developers who are watching from the sidelines wonder if we want to add this file-scope global variable, this is perfectly fine. Anything under builtin/foo.c are meant to serve a single command "git foo" and does not benefit from "let's sift globals into classes that belong to different concepts in the system; most of which will be per repository, so make them some part of the repository object" movement as much as more library-ish parts of the system. Until a specific command starts working on multiple repositories at one time, that is. > @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt, > batch_one_object(line, output, opt, data); > } > > +static void parse_cmd_mailmap(struct batch_options *opt UNUSED, > + const char *line, > + struct strbuf *output UNUSED, > + struct expand_data *data UNUSED) > +{ > + if (!strcmp(line, "yes")) { > + if (!mailmap_loaded) { > + read_mailmap(the_repository, &mailmap); > + mailmap_loaded = 1; > + } > + use_mailmap = 1; > + } else if (!strcmp(line, "no")) { > + use_mailmap = 0; > + } else { > + die(_("mailmap: unknown argument '%s', expected 'yes' or 'no'"), line); > + } > +} OK. > @@ -725,9 +744,10 @@ static const struct parse_cmd { > parse_cmd_fn_t fn; > unsigned takes_args; > } commands[] = { > - { "contents", parse_cmd_contents, 1}, > - { "info", parse_cmd_info, 1}, > - { "flush", NULL, 0}, > + { "contents", parse_cmd_contents, 1 }, > + { "info", parse_cmd_info, 1 }, > + { "flush", NULL, 0 }, > + { "mailmap", parse_cmd_mailmap, 1 }, > }; Mixing style fixes to existing entries in the same patch that adds a new feature by adding a new entry to the table is annoying than having a preliminary clean-up patch that only fixes style and then the main patch that adds the feature. > static void batch_objects_command(struct batch_options *opt, > @@ -1127,8 +1147,10 @@ int cmd_cat_file(int argc, > opt_cw = (opt == 'c' || opt == 'w'); > opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's'); > > - if (use_mailmap) > + if (use_mailmap) { > read_mailmap(the_repository, &mailmap); > + mailmap_loaded = 1; > + } Hmph, interesting. Two points. * It would make it easier to follow if these two lines are made into a small helper function to be called from here and from the "parse_cmd_mailmap()"? * Can we somehow make mailmap object itself slightly smarter so that it knows if it has already been asked to read the data from its sources? It is a pretty dumb string_list, but from a cursory read of the code flow, it seems that mailmap.strdup_strings is initialized to be false in builtin/cat-file.c and then one of the first things done in mailmap.c::read_mailmap() is to flip that bit on, so the "yes" part of the parse_cmd_mailmap() might become if (yes) load_mailmap(); with the helper load_mailmap() that may look like: static void load_mailmap(void) { if (mailmap.strdup_strings) return; /* we know read_mailmap() flips it on */ read_mailmap(the_repository, &mailmap); } The first bullet point to introduce a small common helper will help hiding such an ugly implementation detail there. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-30 2:12 ` Junio C Hamano @ 2026-03-31 1:40 ` Siddharth Asthana 2026-03-31 3:41 ` Junio C Hamano 0 siblings, 1 reply; 27+ messages in thread From: Siddharth Asthana @ 2026-03-31 1:40 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, karthik.188, christian.couder, ps, toon On 30/03/26 07:42, Junio C Hamano wrote: > Siddharth Asthana <siddharthasthana31@gmail.com> writes: > >> git-cat-file(1)'s --batch-command works with the --use-mailmap option, >> but this option needs to be set when the process is created. This means >> we cannot change this option mid-operation. >> >> At GitLab, Gitaly caches git-cat-file processes and it would be useful > > Would "keeps interacting with a single 'cat-file' process" be more > accurate than "caches"? The latter gives, at least to me, Thanks Junio Make sense, I will update that wording in v3! > connotations that may not be necessarily true, like (1) there is a > pool of cat-file processes waiting for Gitaly to connect and serve, > (2) a running Gitaly may decide to disconnect from cat-file from > time to time, and then reconnect to one of them when it becomes > necessary again, etc. > >> if --batch-command supported toggling mailmap dynamically with existing >> processes. >> >> Add a `mailmap` subcommand to --batch-command that takes a single >> argument: `yes` to enable mailmap and `no` to disable it. When enabled, >> mailmap data is loaded from disk on first use and kept in memory so that >> toggling back on does not require reloading. >> >> Suggested-by: Junio C Hamano <gitster@pobox.com> > > This is over-crediting me. The idea to unify the two commands into > one may have come from me, but that is at most helped-by but it is > perfectly fine without any credit. Got it, thanks for pointing that out. > >> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> >> --- > >> diff --git a/builtin/cat-file.c b/builtin/cat-file.c >> index b6f12f41d6..a53926d2bb 100644 >> --- a/builtin/cat-file.c >> +++ b/builtin/cat-file.c >> @@ -54,6 +54,7 @@ static const char *force_path; >> >> static struct string_list mailmap = STRING_LIST_INIT_NODUP; >> static int use_mailmap; >> +static int mailmap_loaded; > > Not part of this topic, but in case less experienced developers who > are watching from the sidelines wonder if we want to add this > file-scope global variable, this is perfectly fine. Anything under > builtin/foo.c are meant to serve a single command "git foo" and does > not benefit from "let's sift globals into classes that belong to > different concepts in the system; most of which will be per > repository, so make them some part of the repository object" > movement as much as more library-ish parts of the system. > > Until a specific command starts working on multiple repositories at > one time, that is. > > >> @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt, >> batch_one_object(line, output, opt, data); >> } >> >> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED, >> + const char *line, >> + struct strbuf *output UNUSED, >> + struct expand_data *data UNUSED) >> +{ >> + if (!strcmp(line, "yes")) { >> + if (!mailmap_loaded) { >> + read_mailmap(the_repository, &mailmap); >> + mailmap_loaded = 1; >> + } >> + use_mailmap = 1; >> + } else if (!strcmp(line, "no")) { >> + use_mailmap = 0; >> + } else { >> + die(_("mailmap: unknown argument '%s', expected 'yes' or 'no'"), line); >> + } >> +} > > OK. > >> @@ -725,9 +744,10 @@ static const struct parse_cmd { >> parse_cmd_fn_t fn; >> unsigned takes_args; >> } commands[] = { >> - { "contents", parse_cmd_contents, 1}, >> - { "info", parse_cmd_info, 1}, >> - { "flush", NULL, 0}, >> + { "contents", parse_cmd_contents, 1 }, >> + { "info", parse_cmd_info, 1 }, >> + { "flush", NULL, 0 }, >> + { "mailmap", parse_cmd_mailmap, 1 }, >> }; > > Mixing style fixes to existing entries in the same patch that adds a > new feature by adding a new entry to the table is annoying than > having a preliminary clean-up patch that only fixes style and then > the main patch that adds the feature. Agreed. I will avoid mixing style-only cleanup with the feature change in v3. > >> static void batch_objects_command(struct batch_options *opt, >> @@ -1127,8 +1147,10 @@ int cmd_cat_file(int argc, >> opt_cw = (opt == 'c' || opt == 'w'); >> opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's'); >> >> - if (use_mailmap) >> + if (use_mailmap) { >> read_mailmap(the_repository, &mailmap); >> + mailmap_loaded = 1; >> + } > > Hmph, interesting. Two points. > > * It would make it easier to follow if these two lines are made > into a small helper function to be called from here and from the > "parse_cmd_mailmap()"? > > * Can we somehow make mailmap object itself slightly smarter so > that it knows if it has already been asked to read the data from > its sources? It is a pretty dumb string_list, but from a cursory > read of the code flow, it seems that mailmap.strdup_strings is > initialized to be false in builtin/cat-file.c and then one of the > first things done in mailmap.c::read_mailmap() is to flip that > bit on, so the "yes" part of the parse_cmd_mailmap() might become > > if (yes) > load_mailmap(); > > with the helper load_mailmap() that may look like: > > static void load_mailmap(void) > { > if (mailmap.strdup_strings) > return; /* we know read_mailmap() flips it on */ > read_mailmap(the_repository, &mailmap); > } > > The first bullet point to introduce a small common helper will > help hiding such an ugly implementation detail there. Thanks, this is helpful. I will introduce a small helper and call it from both places so the flow is easier to follow. I will also avoid publicating the load check in each callsite ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-31 1:40 ` Siddharth Asthana @ 2026-03-31 3:41 ` Junio C Hamano 0 siblings, 0 replies; 27+ messages in thread From: Junio C Hamano @ 2026-03-31 3:41 UTC (permalink / raw) To: Siddharth Asthana; +Cc: git, karthik.188, christian.couder, ps, toon Siddharth Asthana <siddharthasthana31@gmail.com> writes: >> * Can we somehow make mailmap object itself slightly smarter so >> that it knows if it has already been asked to read the data from >> its sources? It is a pretty dumb string_list, but from a cursory >> read of the code flow, it seems that mailmap.strdup_strings is >> initialized to be false in builtin/cat-file.c and then one of the >> first things done in mailmap.c::read_mailmap() is to flip that >> bit on, so the "yes" part of the parse_cmd_mailmap() might become >> >> if (yes) >> load_mailmap(); >> >> with the helper load_mailmap() that may look like: This part was a bit misstated. What I meant was more like if (!strcmp(...yes)) use_mailmap = 1; else if (!strcmp(...no)) use_mailmap = 0; else die(_("misconfigured")); if (use_mailmap) load_mailmap(); ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-29 8:28 ` [PATCH v2 1/1] " Siddharth Asthana 2026-03-30 2:12 ` Junio C Hamano @ 2026-03-30 9:44 ` Karthik Nayak 2026-03-31 1:42 ` Siddharth Asthana 2026-03-30 10:37 ` Patrick Steinhardt 2026-03-31 17:11 ` Jean-Noël AVILA 3 siblings, 1 reply; 27+ messages in thread From: Karthik Nayak @ 2026-03-30 9:44 UTC (permalink / raw) To: Siddharth Asthana, git; +Cc: christian.couder, ps, gitster, toon [-- Attachment #1: Type: text/plain, Size: 7486 bytes --] Siddharth Asthana <siddharthasthana31@gmail.com> writes: > git-cat-file(1)'s --batch-command works with the --use-mailmap option, > but this option needs to be set when the process is created. This means > we cannot change this option mid-operation. > > At GitLab, Gitaly caches git-cat-file processes and it would be useful > if --batch-command supported toggling mailmap dynamically with existing > processes. > > Add a `mailmap` subcommand to --batch-command that takes a single > argument: `yes` to enable mailmap and `no` to disable it. When enabled, > mailmap data is loaded from disk on first use and kept in memory so that > toggling back on does not require reloading. > > Suggested-by: Junio C Hamano <gitster@pobox.com> > Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> > --- > CI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861 > > Documentation/git-cat-file.adoc | 7 +++++ > builtin/cat-file.c | 30 ++++++++++++++++++--- > t/t4203-mailmap.sh | 48 +++++++++++++++++++++++++++++++++ > 3 files changed, 81 insertions(+), 4 deletions(-) > > diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc > index c139f55a16..af32e929a8 100644 > --- a/Documentation/git-cat-file.adoc > +++ b/Documentation/git-cat-file.adoc > @@ -174,6 +174,13 @@ flush:: > since the beginning or since the last flush was issued. When `--buffer` > is used, no output will come until a `flush` is issued. When `--buffer` > is not used, commands are flushed each time without issuing `flush`. > + > +mailmap <yes|no>:: > + Enable or disable mailmap for subsequent `contents` and `info` > + commands. When `yes` is given, mailmap data is loaded from disk on Are there any commands that the mailmap wouldn't apply to? Would it make sense to simply say Enable or disable mailmap for subsequent commands. also we can s/is given//. > + first use and kept in memory; passing `yes` again does not reload it. > + When `no` is given, mailmap is disabled but the data stays in memory > + so that a later `mailmap yes` does not need to reload it from disk. I think the first sentense here jumps directly into the the caching mechanism on using `yes`. It's more important for users to know what `yes` implies. So perhaps: When `yes` mailmap data is used and disabled on `no`. The first `yes` caches the mailmap data until the command exits. > -- > + > > diff --git a/builtin/cat-file.c b/builtin/cat-file.c > index b6f12f41d6..a53926d2bb 100644 > --- a/builtin/cat-file.c > +++ b/builtin/cat-file.c > @@ -54,6 +54,7 @@ static const char *force_path; > > static struct string_list mailmap = STRING_LIST_INIT_NODUP; > static int use_mailmap; > +static int mailmap_loaded; > Nit: should we use a 'bool' here? So we use a variable and not simple rely on checking `mailmap.nr` because it is possible that we do load the mailmap but there are no entries. I assume we could rely on `maimap.cmp` being non-NULL, but that's getting into implementation details. > static char *replace_idents_using_mailmap(char *, size_t *); > > @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt, > batch_one_object(line, output, opt, data); > } > > +static void parse_cmd_mailmap(struct batch_options *opt UNUSED, > + const char *line, > + struct strbuf *output UNUSED, > + struct expand_data *data UNUSED) > +{ > + if (!strcmp(line, "yes")) { > + if (!mailmap_loaded) { > + read_mailmap(the_repository, &mailmap); > + mailmap_loaded = 1; > + } > + use_mailmap = 1; > + } else if (!strcmp(line, "no")) { > + use_mailmap = 0; > + } else { > + die(_("mailmap: unknown argument '%s', expected 'yes' or 'no'"), line); > + } > +} > + > static void dispatch_calls(struct batch_options *opt, > struct strbuf *output, > struct expand_data *data, > @@ -725,9 +744,10 @@ static const struct parse_cmd { > parse_cmd_fn_t fn; > unsigned takes_args; > } commands[] = { > - { "contents", parse_cmd_contents, 1}, > - { "info", parse_cmd_info, 1}, > - { "flush", NULL, 0}, > + { "contents", parse_cmd_contents, 1 }, > + { "info", parse_cmd_info, 1 }, > + { "flush", NULL, 0 }, > + { "mailmap", parse_cmd_mailmap, 1 }, > }; > > static void batch_objects_command(struct batch_options *opt, > @@ -1127,8 +1147,10 @@ int cmd_cat_file(int argc, > opt_cw = (opt == 'c' || opt == 'w'); > opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's'); > > - if (use_mailmap) > + if (use_mailmap) { > read_mailmap(the_repository, &mailmap); > + mailmap_loaded = 1; > + } > The rest of the code looks good. > switch (batch.objects_filter.choice) { > case LOFC_DISABLED: > diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh > index 74b7ddccb2..f66637cd86 100755 > --- a/t/t4203-mailmap.sh > +++ b/t/t4203-mailmap.sh > @@ -1133,6 +1133,54 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us > test_cmp expect actual > ' > > +test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' ' > + test_when_finished "rm .mailmap" && > + cat >.mailmap <<-\EOF && > + C O Mitter <committer@example.com> Orig <orig@example.com> > + EOF > + commit_sha=$(git rev-parse HEAD) && > + git cat-file commit HEAD >commit_no_mailmap.out && > + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && > + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && > + size_mailmap=$(wc -c <commit_mailmap.out) && > + printf "info HEAD\nmailmap yes\ninfo HEAD\n" | git cat-file --batch-command >actual && > + echo $commit_sha commit $size_no_mailmap >expect && > + echo $commit_sha commit $size_mailmap >>expect && > + test_cmp expect actual > +' > + > +test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' ' > + test_when_finished "rm .mailmap" && > + cat >.mailmap <<-\EOF && > + C O Mitter <committer@example.com> Orig <orig@example.com> > + EOF > + commit_sha=$(git rev-parse HEAD) && > + git cat-file commit HEAD >commit_no_mailmap.out && > + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && > + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && > + size_mailmap=$(wc -c <commit_mailmap.out) && > + printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\n" | git cat-file --batch-command >actual && > + echo $commit_sha commit $size_mailmap >expect && > + echo $commit_sha commit $size_no_mailmap >>expect && > + test_cmp expect actual > +' > + > +test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' ' > + test_when_finished "rm .mailmap" && > + cat >.mailmap <<-\EOF && > + C O Mitter <committer@example.com> Orig <orig@example.com> > + EOF > + commit_sha=$(git rev-parse HEAD) && > + git cat-file commit HEAD >commit_no_mailmap.out && > + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && > + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && > + size_mailmap=$(wc -c <commit_mailmap.out) && > + printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\nflush\n" | git cat-file --batch-command --buffer >actual && > + echo $commit_sha commit $size_mailmap >expect && > + echo $commit_sha commit $size_no_mailmap >>expect && > + test_cmp expect actual > +' Shouldn't we also add tests for how this interacts with '--mailmap' and '--no-mailmap'? > test_expect_success 'git cat-file --mailmap works with different author and committer' ' > test_when_finished "rm .mailmap" && > cat >.mailmap <<-\EOF && > -- > 2.51.0 [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 690 bytes --] ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-30 9:44 ` Karthik Nayak @ 2026-03-31 1:42 ` Siddharth Asthana 0 siblings, 0 replies; 27+ messages in thread From: Siddharth Asthana @ 2026-03-31 1:42 UTC (permalink / raw) To: Karthik Nayak, git; +Cc: christian.couder, ps, gitster, toon On 30/03/26 15:14, Karthik Nayak wrote: > Siddharth Asthana <siddharthasthana31@gmail.com> writes: > >> git-cat-file(1)'s --batch-command works with the --use-mailmap option, >> but this option needs to be set when the process is created. This means >> we cannot change this option mid-operation. >> >> At GitLab, Gitaly caches git-cat-file processes and it would be useful >> if --batch-command supported toggling mailmap dynamically with existing >> processes. >> >> Add a `mailmap` subcommand to --batch-command that takes a single >> argument: `yes` to enable mailmap and `no` to disable it. When enabled, >> mailmap data is loaded from disk on first use and kept in memory so that >> toggling back on does not require reloading. >> >> Suggested-by: Junio C Hamano <gitster@pobox.com> >> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> >> --- >> CI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861 >> >> Documentation/git-cat-file.adoc | 7 +++++ >> builtin/cat-file.c | 30 ++++++++++++++++++--- >> t/t4203-mailmap.sh | 48 +++++++++++++++++++++++++++++++++ >> 3 files changed, 81 insertions(+), 4 deletions(-) >> >> diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc >> index c139f55a16..af32e929a8 100644 >> --- a/Documentation/git-cat-file.adoc >> +++ b/Documentation/git-cat-file.adoc >> @@ -174,6 +174,13 @@ flush:: >> since the beginning or since the last flush was issued. When `--buffer` >> is used, no output will come until a `flush` is issued. When `--buffer` >> is not used, commands are flushed each time without issuing `flush`. >> + >> +mailmap <yes|no>:: >> + Enable or disable mailmap for subsequent `contents` and `info` >> + commands. When `yes` is given, mailmap data is loaded from disk on > > Are there any commands that the mailmap wouldn't apply to? Would it make > sense to simply say > > Enable or disable mailmap for subsequent commands. Good point, agreed. I will simplify the wording in v3 and avoid listing specific commands there. > > also we can s/is given//. > >> + first use and kept in memory; passing `yes` again does not reload it. >> + When `no` is given, mailmap is disabled but the data stays in memory >> + so that a later `mailmap yes` does not need to reload it from disk. > > I think the first sentense here jumps directly into the the caching > mechanism on using `yes`. It's more important for users to know what > `yes` implies. So perhaps: > > When `yes` mailmap data is used and disabled on `no`. The first > `yes` caches the mailmap data until the command exits. > >> -- >> + >> >> diff --git a/builtin/cat-file.c b/builtin/cat-file.c >> index b6f12f41d6..a53926d2bb 100644 >> --- a/builtin/cat-file.c >> +++ b/builtin/cat-file.c >> @@ -54,6 +54,7 @@ static const char *force_path; >> >> static struct string_list mailmap = STRING_LIST_INIT_NODUP; >> static int use_mailmap; >> +static int mailmap_loaded; >> > > Nit: should we use a 'bool' here? Yes, makes sense. I will switch that to bool in v3. > > So we use a variable and not simple rely on checking `mailmap.nr` > because it is possible that we do load the mailmap but there are no > entries. I assume we could rely on `maimap.cmp` being non-NULL, but > that's getting into implementation details. > >> static char *replace_idents_using_mailmap(char *, size_t *); >> >> @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt, >> batch_one_object(line, output, opt, data); >> } >> >> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED, >> + const char *line, >> + struct strbuf *output UNUSED, >> + struct expand_data *data UNUSED) >> +{ >> + if (!strcmp(line, "yes")) { >> + if (!mailmap_loaded) { >> + read_mailmap(the_repository, &mailmap); >> + mailmap_loaded = 1; >> + } >> + use_mailmap = 1; >> + } else if (!strcmp(line, "no")) { >> + use_mailmap = 0; >> + } else { >> + die(_("mailmap: unknown argument '%s', expected 'yes' or 'no'"), line); >> + } >> +} >> + >> static void dispatch_calls(struct batch_options *opt, >> struct strbuf *output, >> struct expand_data *data, >> @@ -725,9 +744,10 @@ static const struct parse_cmd { >> parse_cmd_fn_t fn; >> unsigned takes_args; >> } commands[] = { >> - { "contents", parse_cmd_contents, 1}, >> - { "info", parse_cmd_info, 1}, >> - { "flush", NULL, 0}, >> + { "contents", parse_cmd_contents, 1 }, >> + { "info", parse_cmd_info, 1 }, >> + { "flush", NULL, 0 }, >> + { "mailmap", parse_cmd_mailmap, 1 }, >> }; >> >> static void batch_objects_command(struct batch_options *opt, >> @@ -1127,8 +1147,10 @@ int cmd_cat_file(int argc, >> opt_cw = (opt == 'c' || opt == 'w'); >> opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's'); >> >> - if (use_mailmap) >> + if (use_mailmap) { >> read_mailmap(the_repository, &mailmap); >> + mailmap_loaded = 1; >> + } >> > > The rest of the code looks good. > >> switch (batch.objects_filter.choice) { >> case LOFC_DISABLED: >> diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh >> index 74b7ddccb2..f66637cd86 100755 >> --- a/t/t4203-mailmap.sh >> +++ b/t/t4203-mailmap.sh >> @@ -1133,6 +1133,54 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us >> test_cmp expect actual >> ' >> >> +test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' ' >> + test_when_finished "rm .mailmap" && >> + cat >.mailmap <<-\EOF && >> + C O Mitter <committer@example.com> Orig <orig@example.com> >> + EOF >> + commit_sha=$(git rev-parse HEAD) && >> + git cat-file commit HEAD >commit_no_mailmap.out && >> + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && >> + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && >> + size_mailmap=$(wc -c <commit_mailmap.out) && >> + printf "info HEAD\nmailmap yes\ninfo HEAD\n" | git cat-file --batch-command >actual && >> + echo $commit_sha commit $size_no_mailmap >expect && >> + echo $commit_sha commit $size_mailmap >>expect && >> + test_cmp expect actual >> +' >> + >> +test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' ' >> + test_when_finished "rm .mailmap" && >> + cat >.mailmap <<-\EOF && >> + C O Mitter <committer@example.com> Orig <orig@example.com> >> + EOF >> + commit_sha=$(git rev-parse HEAD) && >> + git cat-file commit HEAD >commit_no_mailmap.out && >> + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && >> + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && >> + size_mailmap=$(wc -c <commit_mailmap.out) && >> + printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\n" | git cat-file --batch-command >actual && >> + echo $commit_sha commit $size_mailmap >expect && >> + echo $commit_sha commit $size_no_mailmap >>expect && >> + test_cmp expect actual >> +' >> + >> +test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' ' >> + test_when_finished "rm .mailmap" && >> + cat >.mailmap <<-\EOF && >> + C O Mitter <committer@example.com> Orig <orig@example.com> >> + EOF >> + commit_sha=$(git rev-parse HEAD) && >> + git cat-file commit HEAD >commit_no_mailmap.out && >> + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && >> + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && >> + size_mailmap=$(wc -c <commit_mailmap.out) && >> + printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\nflush\n" | git cat-file --batch-command --buffer >actual && >> + echo $commit_sha commit $size_mailmap >expect && >> + echo $commit_sha commit $size_no_mailmap >>expect && >> + test_cmp expect actual >> +' > > Shouldn't we also add tests for how this interacts with '--mailmap' and > '--no-mailmap'? Agreed, that coverage is missing. I will add tests for startup option + runtime toggle interaction in v3. > >> test_expect_success 'git cat-file --mailmap works with different author and committer' ' >> test_when_finished "rm .mailmap" && >> cat >.mailmap <<-\EOF && >> -- >> 2.51.0 ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-29 8:28 ` [PATCH v2 1/1] " Siddharth Asthana 2026-03-30 2:12 ` Junio C Hamano 2026-03-30 9:44 ` Karthik Nayak @ 2026-03-30 10:37 ` Patrick Steinhardt 2026-03-30 14:53 ` Junio C Hamano 2026-03-31 1:43 ` Siddharth Asthana 2026-03-31 17:11 ` Jean-Noël AVILA 3 siblings, 2 replies; 27+ messages in thread From: Patrick Steinhardt @ 2026-03-30 10:37 UTC (permalink / raw) To: Siddharth Asthana; +Cc: git, karthik.188, christian.couder, gitster, toon On Sun, Mar 29, 2026 at 01:58:08PM +0530, Siddharth Asthana wrote: > diff --git a/builtin/cat-file.c b/builtin/cat-file.c > index b6f12f41d6..a53926d2bb 100644 > --- a/builtin/cat-file.c > +++ b/builtin/cat-file.c > @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt, > batch_one_object(line, output, opt, data); > } > > +static void parse_cmd_mailmap(struct batch_options *opt UNUSED, > + const char *line, > + struct strbuf *output UNUSED, > + struct expand_data *data UNUSED) > +{ > + if (!strcmp(line, "yes")) { > + if (!mailmap_loaded) { > + read_mailmap(the_repository, &mailmap); > + mailmap_loaded = 1; > + } > + use_mailmap = 1; > + } else if (!strcmp(line, "no")) { > + use_mailmap = 0; > + } else { > + die(_("mailmap: unknown argument '%s', expected 'yes' or 'no'"), line); > + } > +} Not commenting on the overall chanegchange, but I guess we should use `git_parse_maybe_bool()` here? Patrick ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-30 10:37 ` Patrick Steinhardt @ 2026-03-30 14:53 ` Junio C Hamano 2026-03-31 1:43 ` Siddharth Asthana 1 sibling, 0 replies; 27+ messages in thread From: Junio C Hamano @ 2026-03-30 14:53 UTC (permalink / raw) To: Patrick Steinhardt Cc: Siddharth Asthana, git, karthik.188, christian.couder, toon Patrick Steinhardt <ps@pks.im> writes: > On Sun, Mar 29, 2026 at 01:58:08PM +0530, Siddharth Asthana wrote: >> diff --git a/builtin/cat-file.c b/builtin/cat-file.c >> index b6f12f41d6..a53926d2bb 100644 >> --- a/builtin/cat-file.c >> +++ b/builtin/cat-file.c >> @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt, >> batch_one_object(line, output, opt, data); >> } >> >> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED, >> + const char *line, >> + struct strbuf *output UNUSED, >> + struct expand_data *data UNUSED) >> +{ >> + if (!strcmp(line, "yes")) { >> + if (!mailmap_loaded) { >> + read_mailmap(the_repository, &mailmap); >> + mailmap_loaded = 1; >> + } >> + use_mailmap = 1; >> + } else if (!strcmp(line, "no")) { >> + use_mailmap = 0; >> + } else { >> + die(_("mailmap: unknown argument '%s', expected 'yes' or 'no'"), line); >> + } >> +} > > Not commenting on the overall chanegchange, but I guess we should use > `git_parse_maybe_bool()` here? The saame thought occureed to me. Also I agree with Karthik that we should not say "applies only to this and that commands". Thanks, all. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-30 10:37 ` Patrick Steinhardt 2026-03-30 14:53 ` Junio C Hamano @ 2026-03-31 1:43 ` Siddharth Asthana 1 sibling, 0 replies; 27+ messages in thread From: Siddharth Asthana @ 2026-03-31 1:43 UTC (permalink / raw) To: Patrick Steinhardt; +Cc: git, karthik.188, christian.couder, gitster, toon On 30/03/26 16:07, Patrick Steinhardt wrote: > On Sun, Mar 29, 2026 at 01:58:08PM +0530, Siddharth Asthana wrote: >> diff --git a/builtin/cat-file.c b/builtin/cat-file.c >> index b6f12f41d6..a53926d2bb 100644 >> --- a/builtin/cat-file.c >> +++ b/builtin/cat-file.c >> @@ -692,6 +693,24 @@ static void parse_cmd_info(struct batch_options *opt, >> batch_one_object(line, output, opt, data); >> } >> >> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED, >> + const char *line, >> + struct strbuf *output UNUSED, >> + struct expand_data *data UNUSED) >> +{ >> + if (!strcmp(line, "yes")) { >> + if (!mailmap_loaded) { >> + read_mailmap(the_repository, &mailmap); >> + mailmap_loaded = 1; >> + } >> + use_mailmap = 1; >> + } else if (!strcmp(line, "no")) { >> + use_mailmap = 0; >> + } else { >> + die(_("mailmap: unknown argument '%s', expected 'yes' or 'no'"), line); >> + } >> +} > > Not commenting on the overall chanegchange, but I guess we should use > `git_parse_maybe_bool()` here? Yep, agreed. I will switch to git_parse_maybe_bool() in v3. > > Patrick ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-29 8:28 ` [PATCH v2 1/1] " Siddharth Asthana ` (2 preceding siblings ...) 2026-03-30 10:37 ` Patrick Steinhardt @ 2026-03-31 17:11 ` Jean-Noël AVILA 2026-03-31 17:49 ` Junio C Hamano 3 siblings, 1 reply; 27+ messages in thread From: Jean-Noël AVILA @ 2026-03-31 17:11 UTC (permalink / raw) To: git, Siddharth Asthana Cc: karthik.188, christian.couder, ps, gitster, toon, Siddharth Asthana On Sunday, 29 March 2026 10:28:08 CEST Siddharth Asthana wrote: > git-cat-file(1)'s --batch-command works with the --use-mailmap option, > but this option needs to be set when the process is created. This means > we cannot change this option mid-operation. > > At GitLab, Gitaly caches git-cat-file processes and it would be useful > if --batch-command supported toggling mailmap dynamically with existing > processes. > > Add a `mailmap` subcommand to --batch-command that takes a single > argument: `yes` to enable mailmap and `no` to disable it. When enabled, > mailmap data is loaded from disk on first use and kept in memory so that > toggling back on does not require reloading. > > Suggested-by: Junio C Hamano <gitster@pobox.com> > Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> > --- > CI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861 > > Documentation/git-cat-file.adoc | 7 +++++ > builtin/cat-file.c | 30 ++++++++++++++++++--- > t/t4203-mailmap.sh | 48 +++++++++++++++++++++++++++++++++ > 3 files changed, 81 insertions(+), 4 deletions(-) > > diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat- file.adoc > index c139f55a16..af32e929a8 100644 > --- a/Documentation/git-cat-file.adoc > +++ b/Documentation/git-cat-file.adoc > @@ -174,6 +174,13 @@ flush:: > since the beginning or since the last flush was issued. When `-- buffer` > is used, no output will come until a `flush` is issued. When `-- buffer` > is not used, commands are flushed each time without issuing `flush`. > + > +mailmap <yes|no>:: `yes` and `no` are keywords, and you want to express an alternative, do it like this: `mailmap (yes|no)::`. > + Enable or disable mailmap for subsequent `contents` and `info` > + commands. When `yes` is given, mailmap data is loaded from disk on > + first use and kept in memory; passing `yes` again does not reload it. > + When `no` is given, mailmap is disabled but the data stays in memory > + so that a later `mailmap yes` does not need to reload it from disk. > -- > + > Instead of detailing the alternatives in the same chapter, you could break it into a sub-list: Enable or disalbe mailmap for subsequent `contents` and `info` commands. Possible values are: `yes`;; mailmap data is loaded from disk on first use and kept in memory; passing `yes` again does not reload it. `no`;; mailmap is disabled but the data stays in memory so that a later `mailmap yes` does not need to reload it from disk. Thanks ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-31 17:11 ` Jean-Noël AVILA @ 2026-03-31 17:49 ` Junio C Hamano 2026-04-01 10:11 ` Jean-Noël Avila 0 siblings, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2026-03-31 17:49 UTC (permalink / raw) To: Jean-Noël AVILA Cc: git, Siddharth Asthana, karthik.188, christian.couder, ps, toon Jean-Noël AVILA <jn.avila@free.fr> writes: > On Sunday, 29 March 2026 10:28:08 CEST Siddharth Asthana wrote: >> git-cat-file(1)'s --batch-command works with the --use-mailmap option, >> but this option needs to be set when the process is created. This means >> we cannot change this option mid-operation. >> >> At GitLab, Gitaly caches git-cat-file processes and it would be useful >> if --batch-command supported toggling mailmap dynamically with existing >> processes. >> >> Add a `mailmap` subcommand to --batch-command that takes a single >> argument: `yes` to enable mailmap and `no` to disable it. When enabled, >> mailmap data is loaded from disk on first use and kept in memory so that >> toggling back on does not require reloading. >> >> Suggested-by: Junio C Hamano <gitster@pobox.com> >> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> >> --- >> CI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861 >> >> Documentation/git-cat-file.adoc | 7 +++++ >> builtin/cat-file.c | 30 ++++++++++++++++++--- >> t/t4203-mailmap.sh | 48 +++++++++++++++++++++++++++++++++ >> 3 files changed, 81 insertions(+), 4 deletions(-) >> >> diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat- > file.adoc >> index c139f55a16..af32e929a8 100644 >> --- a/Documentation/git-cat-file.adoc >> +++ b/Documentation/git-cat-file.adoc >> @@ -174,6 +174,13 @@ flush:: >> since the beginning or since the last flush was issued. When `-- > buffer` >> is used, no output will come until a `flush` is issued. When `-- > buffer` >> is not used, commands are flushed each time without issuing `flush`. >> + >> +mailmap <yes|no>:: > > `yes` and `no` are keywords, and you want to express an alternative, do it > like this: `mailmap (yes|no)::`. Not `mailmap (yes|no)`:: IOW, shouldn't the closing quote come before the double-colon? >> + Enable or disable mailmap for subsequent `contents` and `info` >> + commands. When `yes` is given, mailmap data is loaded from disk on >> + first use and kept in memory; passing `yes` again does not reload > it. >> + When `no` is given, mailmap is disabled but the data stays in memory >> + so that a later `mailmap yes` does not need to reload it from disk. >> -- >> + >> > > Instead of detailing the alternatives in the same chapter, you could break it > into a sub-list: > > Enable or disalbe mailmap for subsequent `contents` and `info` commands. > Possible values are: > `yes`;; > mailmap data is loaded from disk on first use and kept in memory; passing > `yes` again does not reload it. > `no`;; > mailmap is disabled but the data stays in memory so that a later `mailmap yes` > does not need to reload it from disk. Great. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-31 17:49 ` Junio C Hamano @ 2026-04-01 10:11 ` Jean-Noël Avila 0 siblings, 0 replies; 27+ messages in thread From: Jean-Noël Avila @ 2026-04-01 10:11 UTC (permalink / raw) To: Junio C Hamano Cc: git, Siddharth Asthana, karthik.188, christian.couder, ps, toon On 3/31/26 19:49, Junio C Hamano wrote: > Jean-Noël AVILA <jn.avila@free.fr> writes: > >> On Sunday, 29 March 2026 10:28:08 CEST Siddharth Asthana wrote: >>> git-cat-file(1)'s --batch-command works with the --use-mailmap option, >>> but this option needs to be set when the process is created. This means >>> we cannot change this option mid-operation. >>> >>> At GitLab, Gitaly caches git-cat-file processes and it would be useful >>> if --batch-command supported toggling mailmap dynamically with existing >>> processes. >>> >>> Add a `mailmap` subcommand to --batch-command that takes a single >>> argument: `yes` to enable mailmap and `no` to disable it. When enabled, >>> mailmap data is loaded from disk on first use and kept in memory so that >>> toggling back on does not require reloading. >>> >>> Suggested-by: Junio C Hamano <gitster@pobox.com> >>> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> >>> --- >>> CI: https://gitlab.com/gitlab-org/git/-/pipelines/2416081861 >>> >>> Documentation/git-cat-file.adoc | 7 +++++ >>> builtin/cat-file.c | 30 ++++++++++++++++++--- >>> t/t4203-mailmap.sh | 48 +++++++++++++++++++++++++++++++++ >>> 3 files changed, 81 insertions(+), 4 deletions(-) >>> >>> diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat- >> file.adoc >>> index c139f55a16..af32e929a8 100644 >>> --- a/Documentation/git-cat-file.adoc >>> +++ b/Documentation/git-cat-file.adoc >>> @@ -174,6 +174,13 @@ flush:: >>> since the beginning or since the last flush was issued. When `-- >> buffer` >>> is used, no output will come until a `flush` is issued. When `-- >> buffer` >>> is not used, commands are flushed each time without issuing `flush`. >>> + >>> +mailmap <yes|no>:: >> >> `yes` and `no` are keywords, and you want to express an alternative, do it >> like this: `mailmap (yes|no)::`. > > Not > > `mailmap (yes|no)`:: > > IOW, shouldn't the closing quote come before the double-colon? Oops, you're completely right! ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v3 0/1] cat-file: add mailmap subcommand to --batch-command 2026-03-29 8:28 ` [PATCH v2 0/1] cat-file: add mailmap subcommand " Siddharth Asthana 2026-03-29 8:28 ` [PATCH v2 1/1] " Siddharth Asthana @ 2026-03-31 12:11 ` Siddharth Asthana 2026-03-31 12:11 ` [PATCH v3 1/1] " Siddharth Asthana 2026-04-15 15:09 ` [PATCH v4 0/1] " Siddharth Asthana 1 sibling, 2 replies; 27+ messages in thread From: Siddharth Asthana @ 2026-03-31 12:11 UTC (permalink / raw) To: git; +Cc: karthik.188, christian.couder, ps, gitster, toon, Siddharth Asthana git-cat-file(1)'s --batch-command works with the --use-mailmap option, but this option needs to be set when the process is created. This means we cannot change this option mid-operation. At GitLab, Gitaly keeps interacting with a long-lived git-cat-file process and it would be useful if --batch-command supported toggling mailmap dynamically on an existing process. This patch adds a `mailmap` subcommand to --batch-command that accepts a boolean argument and toggles mailmap dynamically for subsequent commands. The series is based on top of 5361983c07 (The 22nd batch, 2026-03-21). CI: https://gitlab.com/gitlab-org/git/-/pipelines/2419600519 Changes in v3: - Use "keeps interacting with a long-lived git-cat-file process" wording in the commit message and cover letter. - Drop the `Suggested-by` trailer. - Avoid style-only churn in the `commands[]` table by keeping existing initializer style and only adding the new command entry. - Introduce a `load_mailmap()` helper used by both startup and `parse_cmd_mailmap()`. - Parse `mailmap <bool>` using `git_parse_maybe_bool()` instead of handling only `yes`/`no`. - Update docs to describe `mailmap <bool>` and reference Git's boolean syntax from `git-config(1)`. - Add tests for startup option interaction (`--mailmap`/`--no-mailmap`), accepted boolean values (`true`/`false`), and invalid boolean input. - Link to v2: https://public-inbox.org/git/20260329082804.53400-1-siddharthasthana31@gmail.com/ - Link to v1: https://public-inbox.org/git/a4ec7bfa-f16b-4505-9b37-d3dd137e93cb@gmail.com/T/#m5c62fb6ad0fbcc99a706dba4c78b66359c247acd Thanks, Siddharth --- Siddharth Asthana (1): cat-file: add mailmap subcommand to --batch-command Documentation/git-cat-file.adoc | 7 +++ builtin/cat-file.c | 32 ++++++++++-- t/t4203-mailmap.sh | 105 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 4 deletions(-) Range-diff versus v2: 1: 936ca27419 ! 1: df446d7ca3 cat-file: add mailmap subcommand to --batch-command @@ Commit message but this option needs to be set when the process is created. This means we cannot change this option mid-operation. - At GitLab, Gitaly caches git-cat-file processes and it would be useful - if --batch-command supported toggling mailmap dynamically with existing - processes. + At GitLab, Gitaly keeps interacting with a long-lived git-cat-file + process and it would be useful if --batch-command supported toggling + mailmap dynamically on an existing process. - Add a `mailmap` subcommand to --batch-command that takes a single - argument: `yes` to enable mailmap and `no` to disable it. When enabled, - mailmap data is loaded from disk on first use and kept in memory so that - toggling back on does not require reloading. + Add a `mailmap` subcommand to --batch-command that takes a boolean + argument. The command now uses `git_parse_maybe_bool()` and supports all + standard Git boolean values. Mailmap data is loaded lazily and kept in + memory, while a helper centralizes the one-time load path used both at + startup and from the batch-command handler. + + Extend tests to cover runtime toggling, startup option interactions + (`--mailmap`/`--no-mailmap`), accepted boolean forms, and invalid values. - Suggested-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> ## Documentation/git-cat-file.adoc ## @@ Documentation/git-cat-file.adoc: flush:: is used, no output will come until a `flush` is issued. When `--buffer` is not used, commands are flushed each time without issuing `flush`. + -+mailmap <yes|no>:: -+ Enable or disable mailmap for subsequent `contents` and `info` -+ commands. When `yes` is given, mailmap data is loaded from disk on -+ first use and kept in memory; passing `yes` again does not reload it. -+ When `no` is given, mailmap is disabled but the data stays in memory -+ so that a later `mailmap yes` does not need to reload it from disk. ++mailmap <bool>:: ++ Enable or disable mailmap for subsequent commands. +++ ++The `<bool>` argument accepts the same boolean values as ++linkgit:git-config[1]. When enabled, mailmap data is loaded on first ++use and kept in memory until the process exits. -- ## builtin/cat-file.c ## +@@ builtin/cat-file.c: static int use_mailmap; + +static void load_mailmap(void) +{ + if (mailmap.strdup_strings) + return; + + read_mailmap(the_repository, &mailmap); +} + @@ builtin/cat-file.c: static void parse_cmd_info(struct batch_options *opt, batch_one_object(line, output, opt, data); } @@ builtin/cat-file.c: static void parse_cmd_info(struct batch_options *opt, +{ -+ if (!strcmp(line, "yes")) { -+ if (!mailmap_loaded) { -+ read_mailmap(the_repository, &mailmap); -+ mailmap_loaded = 1; -+ } -+ use_mailmap = 1; -+ } else if (!strcmp(line, "no")) { -+ use_mailmap = 0; -+ } else { -+ die(_("mailmap: unknown argument '%s', expected 'yes' or 'no'"), line); -+ } ++ int value = git_parse_maybe_bool(line); ++ ++ if (value < 0) ++ die(_("mailmap: invalid boolean '%s'"), line); ++ ++ if (value > 0) ++ load_mailmap(); ++ use_mailmap = value; +} + @@ builtin/cat-file.c: static const struct parse_cmd { -+ { "use-mailmap", parse_cmd_use_mailmap, 0 }, -+ { "no-use-mailmap", parse_cmd_disable_mailmap, 0 }, ++ { "mailmap", parse_cmd_mailmap, 1 }, +}; @@ builtin/cat-file.c: int cmd_cat_file(int argc, if (use_mailmap) -+ read_mailmap(the_repository, &mailmap); ++ load_mailmap(); base-commit: 5361983c075154725be47b65cca9a2421789e410 -- 2.53.0 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v3 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-31 12:11 ` [PATCH v3 0/1] " Siddharth Asthana @ 2026-03-31 12:11 ` Siddharth Asthana 2026-03-31 19:21 ` Junio C Hamano 2026-04-15 15:09 ` [PATCH v4 0/1] " Siddharth Asthana 1 sibling, 1 reply; 27+ messages in thread From: Siddharth Asthana @ 2026-03-31 12:11 UTC (permalink / raw) To: git; +Cc: karthik.188, christian.couder, ps, gitster, toon, Siddharth Asthana git-cat-file(1)'s --batch-command works with the --use-mailmap option, but this option needs to be set when the process is created. This means we cannot change this option mid-operation. At GitLab, Gitaly keeps interacting with a long-lived git-cat-file process and it would be useful if --batch-command supported toggling mailmap dynamically on an existing process. Add a `mailmap` subcommand to --batch-command that takes a boolean argument. The command now uses `git_parse_maybe_bool()` and supports all standard Git boolean values. Mailmap data is loaded lazily and kept in memory, while a helper centralizes the one-time load path used both at startup and from the batch-command handler. Extend tests to cover runtime toggling, startup option interactions (`--mailmap`/`--no-mailmap`), accepted boolean forms, and invalid values. Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> --- CI: https://gitlab.com/gitlab-org/git/-/pipelines/2419600519 Documentation/git-cat-file.adoc | 7 +++ builtin/cat-file.c | 32 ++++++++-- t/t4203-mailmap.sh | 105 ++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 4 deletions(-) diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc index c139f55a16..3db925e1de 100644 --- a/Documentation/git-cat-file.adoc +++ b/Documentation/git-cat-file.adoc @@ -174,6 +174,13 @@ flush:: since the beginning or since the last flush was issued. When `--buffer` is used, no output will come until a `flush` is issued. When `--buffer` is not used, commands are flushed each time without issuing `flush`. + +mailmap <bool>:: + Enable or disable mailmap for subsequent commands. ++ +The `<bool>` argument accepts the same boolean values as +linkgit:git-config[1]. When enabled, mailmap data is loaded on first +use and kept in memory until the process exits. -- + diff --git a/builtin/cat-file.c b/builtin/cat-file.c index b6f12f41d6..a3dab0b40c 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -57,6 +57,14 @@ static int use_mailmap; static char *replace_idents_using_mailmap(char *, size_t *); +static void load_mailmap(void) +{ + if (mailmap.strdup_strings) + return; + + read_mailmap(the_repository, &mailmap); +} + static char *replace_idents_using_mailmap(char *object_buf, size_t *size) { struct strbuf sb = STRBUF_INIT; @@ -692,6 +700,21 @@ static void parse_cmd_info(struct batch_options *opt, batch_one_object(line, output, opt, data); } +static void parse_cmd_mailmap(struct batch_options *opt UNUSED, + const char *line, + struct strbuf *output UNUSED, + struct expand_data *data UNUSED) +{ + int value = git_parse_maybe_bool(line); + + if (value < 0) + die(_("mailmap: invalid boolean '%s'"), line); + + if (value > 0) + load_mailmap(); + use_mailmap = value; +} + static void dispatch_calls(struct batch_options *opt, struct strbuf *output, struct expand_data *data, @@ -725,9 +748,10 @@ static const struct parse_cmd { parse_cmd_fn_t fn; unsigned takes_args; } commands[] = { - { "contents", parse_cmd_contents, 1}, - { "info", parse_cmd_info, 1}, - { "flush", NULL, 0}, + { "contents", parse_cmd_contents, 1 }, + { "info", parse_cmd_info, 1 }, + { "flush", NULL, 0 }, + { "mailmap", parse_cmd_mailmap, 1 }, }; static void batch_objects_command(struct batch_options *opt, @@ -1128,7 +1152,7 @@ int cmd_cat_file(int argc, opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's'); if (use_mailmap) - read_mailmap(the_repository, &mailmap); + load_mailmap(); switch (batch.objects_filter.choice) { case LOFC_DISABLED: diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 74b7ddccb2..249548eb9b 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -1133,6 +1133,111 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us test_cmp expect actual ' +test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "info HEAD\nmailmap yes\ninfo HEAD\n" | git cat-file --batch-command >actual && + echo $commit_sha commit $size_no_mailmap >expect && + echo $commit_sha commit $size_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\n" | git cat-file --batch-command >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\nflush\n" | git cat-file --batch-command --buffer >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap no overrides startup --mailmap' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_mailmap=$(wc -c <commit_mailmap.out) && + git cat-file commit HEAD >commit_no_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + printf "info HEAD\nmailmap no\ninfo HEAD\n" | \ + git cat-file --mailmap --batch-command >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap yes overrides startup --no-mailmap' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "info HEAD\nmailmap yes\ninfo HEAD\n" | \ + git cat-file --no-mailmap --batch-command >actual && + echo $commit_sha commit $size_no_mailmap >expect && + echo $commit_sha commit $size_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap accepts true/false' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "mailmap true\ninfo HEAD\nmailmap false\ninfo HEAD\n" | \ + git cat-file --batch-command >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap rejects invalid boolean' ' + echo "mailmap maybe" >in && + test_must_fail git cat-file --batch-command <in 2>err && + test_grep "mailmap: invalid boolean .*maybe" err +' + test_expect_success 'git cat-file --mailmap works with different author and committer' ' test_when_finished "rm .mailmap" && cat >.mailmap <<-\EOF && -- 2.53.0 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH v3 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-31 12:11 ` [PATCH v3 1/1] " Siddharth Asthana @ 2026-03-31 19:21 ` Junio C Hamano 2026-04-10 18:29 ` Junio C Hamano 0 siblings, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2026-03-31 19:21 UTC (permalink / raw) To: Siddharth Asthana; +Cc: git, karthik.188, christian.couder, ps, toon Siddharth Asthana <siddharthasthana31@gmail.com> writes: > git-cat-file(1)'s --batch-command works with the --use-mailmap option, > but this option needs to be set when the process is created. This means > we cannot change this option mid-operation. > > At GitLab, Gitaly keeps interacting with a long-lived git-cat-file > process and it would be useful if --batch-command supported toggling > mailmap dynamically on an existing process. > > Add a `mailmap` subcommand to --batch-command that takes a boolean > argument. The command now uses `git_parse_maybe_bool()` and supports all > standard Git boolean values. Mailmap data is loaded lazily and kept in I do not think you want to say "now uses `git_parse_maybe_bool()`". Nobody is interested in the difference relative to what you did in the previous iteration. ... that takes a boolean argument (usual ways you can specify a boolean value like 'yes', 'true', etc., are supported). > +static void load_mailmap(void) > +{ > + if (mailmap.strdup_strings) > + return; > + > + read_mailmap(the_repository, &mailmap); > +} This, especially the early return condition, may deserve a bit of in-code comment, as "a used string_list has the .strdup_strings bit set" is not a generally applicable rule. /* * The mailmap is initialized with .strdup_strings set to 0, * but read_mailmap() sets the bit to 1 (this is true even when * not a single mailmap entry is read), so it can be used for * lazy loading. */ or something, perhaps? > @@ -692,6 +700,21 @@ static void parse_cmd_info(struct batch_options *opt, > batch_one_object(line, output, opt, data); > } > > +static void parse_cmd_mailmap(struct batch_options *opt UNUSED, > + const char *line, > + struct strbuf *output UNUSED, > + struct expand_data *data UNUSED) > +{ > + int value = git_parse_maybe_bool(line); As "line" is never NULL, one standard way to spell a boolean True is not available to the callers, namely, "mailmap<EOL>" (like how a configuration file entry "[core] bare" means "[core] bare = true"), but that is probably OK. "mailmap<SP><EOL>" may be interpreted as feeding an empty string as an argument, which is "false" to the git_parse_maybe_bool() function. That might be surprising. Nothing actionable in the above comment (other than perhaps as a hint for documentation update). > + if (value < 0) > + die(_("mailmap: invalid boolean '%s'"), line); > + > + if (value > 0) > + load_mailmap(); > + use_mailmap = value; > +} Hmph, why not use use_mailmap from the beginning of the function without introducing the local variable "value"? Nothing in load_mailmap() pays attention to the current value of use_mailmap so I do not see much point in preserving the current status until the last minute. Thanks. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v3 1/1] cat-file: add mailmap subcommand to --batch-command 2026-03-31 19:21 ` Junio C Hamano @ 2026-04-10 18:29 ` Junio C Hamano 0 siblings, 0 replies; 27+ messages in thread From: Junio C Hamano @ 2026-04-10 18:29 UTC (permalink / raw) To: Siddharth Asthana; +Cc: git, karthik.188, christian.couder, ps, toon Junio C Hamano <gitster@pobox.com> writes: > Siddharth Asthana <siddharthasthana31@gmail.com> writes: > >> git-cat-file(1)'s --batch-command works with the --use-mailmap option, >> but this option needs to be set when the process is created. This means >> we cannot change this option mid-operation. >> >> At GitLab, Gitaly keeps interacting with a long-lived git-cat-file >> process and it would be useful if --batch-command supported toggling >> mailmap dynamically on an existing process. >> >> Add a `mailmap` subcommand to --batch-command that takes a boolean >> argument. The command now uses `git_parse_maybe_bool()` and supports all >> standard Git boolean values. Mailmap data is loaded lazily and kept in > > I do not think you want to say "now uses `git_parse_maybe_bool()`". > Nobody is interested in the difference relative to what you did in > the previous iteration. > > ... that takes a boolean argument (usual ways you can specify a > boolean value like 'yes', 'true', etc., are supported). > >> +static void load_mailmap(void) >> +{ >> + if (mailmap.strdup_strings) >> + return; >> + >> + read_mailmap(the_repository, &mailmap); >> +} > > This, especially the early return condition, may deserve a bit of > in-code comment, as "a used string_list has the .strdup_strings bit > set" is not a generally applicable rule. > > /* > * The mailmap is initialized with .strdup_strings set to 0, > * but read_mailmap() sets the bit to 1 (this is true even when > * not a single mailmap entry is read), so it can be used for > * lazy loading. > */ > > or something, perhaps? > >> @@ -692,6 +700,21 @@ static void parse_cmd_info(struct batch_options *opt, >> batch_one_object(line, output, opt, data); >> } >> >> +static void parse_cmd_mailmap(struct batch_options *opt UNUSED, >> + const char *line, >> + struct strbuf *output UNUSED, >> + struct expand_data *data UNUSED) >> +{ >> + int value = git_parse_maybe_bool(line); > > As "line" is never NULL, one standard way to spell a boolean True is > not available to the callers, namely, "mailmap<EOL>" (like how a > configuration file entry "[core] bare" means "[core] bare = true"), > but that is probably OK. "mailmap<SP><EOL>" may be interpreted as > feeding an empty string as an argument, which is "false" to the > git_parse_maybe_bool() function. That might be surprising. > > Nothing actionable in the above comment (other than perhaps as a > hint for documentation update). > >> + if (value < 0) >> + die(_("mailmap: invalid boolean '%s'"), line); >> + >> + if (value > 0) >> + load_mailmap(); >> + use_mailmap = value; >> +} > > Hmph, why not use use_mailmap from the beginning of the function > without introducing the local variable "value"? Nothing in > load_mailmap() pays attention to the current value of use_mailmap > so I do not see much point in preserving the current status until > the last minute. > > Thanks. The thread went dark since this message. I do not want to see energy spent on a viable topic so far disappear into a void without achieving anything. Let's push the topic over the finish line with futher work. Thanks. ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v4 0/1] cat-file: add mailmap subcommand to --batch-command 2026-03-31 12:11 ` [PATCH v3 0/1] " Siddharth Asthana 2026-03-31 12:11 ` [PATCH v3 1/1] " Siddharth Asthana @ 2026-04-15 15:09 ` Siddharth Asthana 2026-04-15 15:09 ` [PATCH v4 1/1] " Siddharth Asthana 2026-04-16 3:32 ` [PATCH v5 0/1] " Siddharth Asthana 1 sibling, 2 replies; 27+ messages in thread From: Siddharth Asthana @ 2026-04-15 15:09 UTC (permalink / raw) To: git Cc: karthik.188, christian.couder, ps, gitster, toon, jn.avila, Siddharth Asthana git-cat-file(1)'s --batch-command works with the --use-mailmap option, but this option needs to be set when the process is created. This means we cannot change this option mid-operation. At GitLab, Gitaly keeps interacting with a long-lived git-cat-file process and it would be useful if --batch-command supported toggling mailmap dynamically on an existing process. This patch adds a `mailmap` subcommand to --batch-command that accepts a boolean argument and toggles mailmap dynamically for subsequent commands. The series is based on top of 5361983c07 (The 22nd batch, 2026-03-21). CI: https://gitlab.com/gitlab-org/git/-/pipelines/2455043368 Changes in v4: - Reword commit message: describe boolean support without mentioning internal function names, following Junio's suggestion. - Add an in-code comment explaining why `mailmap.strdup_strings` can be used as the "already loaded" check in `load_mailmap()`. - Drop local `value` variable in `parse_cmd_mailmap()` and assign directly to `use_mailmap`. - Fix documentation syntax: place the closing backtick before `::` and break the description into a `;;` sub-list for `true`/`false` effects. - Link to v3: https://lore.kernel.org/git/xmqqv7dyoei6.fsf@gitster.g/T/#m0a109f3eb5129e619ecec5f2d58ead0c5a49a4f3 - Link to v2: https://lore.kernel.org/git/xmqqv7dyoei6.fsf@gitster.g/T/#m445eab3b309bded92d1b130d225b882c73988ff2 - Link to v1: https://public-inbox.org/git/a4ec7bfa-f16b-4505-9b37-d3dd137e93cb@gmail.com/T/#m5c62fb6ad0fbcc99a706dba4c78b66359c247acd Thanks, Siddharth --- Siddharth Asthana (1): cat-file: add mailmap subcommand to --batch-command Documentation/git-cat-file.adoc | 12 +++++ builtin/cat-file.c | 37 ++++++++++++-- t/t4203-mailmap.sh | 105 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 4 deletions(-) Range-diff versus v3: 1: dbc1a003a5 ! 1: 25ebffe39e cat-file: add mailmap subcommand to --batch-command @@ Commit message mailmap dynamically on an existing process. Add a `mailmap` subcommand to --batch-command that takes a boolean - argument. The command now uses `git_parse_maybe_bool()` and supports all - standard Git boolean values. Mailmap data is loaded lazily and kept in - memory, while a helper centralizes the one-time load path used both at - startup and from the batch-command handler. + argument (usual ways you can specify a boolean value like 'yes', 'true', + etc., are supported). Mailmap data is loaded lazily and kept in memory, + while a helper centralizes the one-time load path used both at startup + and from the batch-command handler. Extend tests to cover runtime toggling, startup option interactions (`--mailmap`/`--no-mailmap`), accepted boolean forms, and invalid values. @@ Documentation/git-cat-file.adoc: flush:: is used, no output will come until a `flush` is issued. When `--buffer` is not used, commands are flushed each time without issuing `flush`. + -+mailmap <bool>:: -+ Enable or disable mailmap for subsequent commands. ++`mailmap (<bool>)`:: ++ Enable or disable mailmap for subsequent commands. The `<bool>` ++ argument accepts the same boolean values as linkgit:git-config[1]. ++ Possible effects are: ++ -+The `<bool>` argument accepts the same boolean values as -+linkgit:git-config[1]. When enabled, mailmap data is loaded on first -+use and kept in memory until the process exits. ++`true`;; ++ Mailmap data is loaded on first use and kept in memory until the ++ process exits. Passing `true` again does not reload the data. ++`false`;; ++ Mailmap replacements are disabled for subsequent commands, but data ++ already loaded stays in memory. -- + @@ builtin/cat-file.c: static int use_mailmap; static char *replace_idents_using_mailmap(char *, size_t *); ++/* ++ * The mailmap is initialized with .strdup_strings set to 0, ++ * but read_mailmap() sets the bit to 1 (this is true even when ++ * not a single mailmap entry is read), so it can be used for ++ * lazy loading. ++ */ +static void load_mailmap(void) +{ + if (mailmap.strdup_strings) @@ builtin/cat-file.c: static void parse_cmd_info(struct batch_options *opt, + struct strbuf *output UNUSED, + struct expand_data *data UNUSED) +{ -+ int value = git_parse_maybe_bool(line); ++ use_mailmap = git_parse_maybe_bool(line); + -+ if (value < 0) ++ if (use_mailmap < 0) + die(_("mailmap: invalid boolean '%s'"), line); + -+ if (value > 0) ++ if (use_mailmap) + load_mailmap(); -+ use_mailmap = value; +} + static void dispatch_calls(struct batch_options *opt, base-commit: 5361983c075154725be47b65cca9a2421789e410 -- 2.53.0 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v4 1/1] cat-file: add mailmap subcommand to --batch-command 2026-04-15 15:09 ` [PATCH v4 0/1] " Siddharth Asthana @ 2026-04-15 15:09 ` Siddharth Asthana 2026-04-15 18:28 ` Junio C Hamano 2026-04-16 3:32 ` [PATCH v5 0/1] " Siddharth Asthana 1 sibling, 1 reply; 27+ messages in thread From: Siddharth Asthana @ 2026-04-15 15:09 UTC (permalink / raw) To: git Cc: karthik.188, christian.couder, ps, gitster, toon, jn.avila, Siddharth Asthana git-cat-file(1)'s --batch-command works with the --use-mailmap option, but this option needs to be set when the process is created. This means we cannot change this option mid-operation. At GitLab, Gitaly keeps interacting with a long-lived git-cat-file process and it would be useful if --batch-command supported toggling mailmap dynamically on an existing process. Add a `mailmap` subcommand to --batch-command that takes a boolean argument (usual ways you can specify a boolean value like 'yes', 'true', etc., are supported). Mailmap data is loaded lazily and kept in memory, while a helper centralizes the one-time load path used both at startup and from the batch-command handler. Extend tests to cover runtime toggling, startup option interactions (`--mailmap`/`--no-mailmap`), accepted boolean forms, and invalid values. Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> --- CI: https://gitlab.com/gitlab-org/git/-/pipelines/2455043368 Documentation/git-cat-file.adoc | 12 ++++ builtin/cat-file.c | 37 +++++++++-- t/t4203-mailmap.sh | 105 ++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 4 deletions(-) diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc index c139f55a16..0f499c9d1b 100644 --- a/Documentation/git-cat-file.adoc +++ b/Documentation/git-cat-file.adoc @@ -174,6 +174,18 @@ flush:: since the beginning or since the last flush was issued. When `--buffer` is used, no output will come until a `flush` is issued. When `--buffer` is not used, commands are flushed each time without issuing `flush`. + +`mailmap (<bool>)`:: + Enable or disable mailmap for subsequent commands. The `<bool>` + argument accepts the same boolean values as linkgit:git-config[1]. + Possible effects are: ++ +`true`;; + Mailmap data is loaded on first use and kept in memory until the + process exits. Passing `true` again does not reload the data. +`false`;; + Mailmap replacements are disabled for subsequent commands, but data + already loaded stays in memory. -- + diff --git a/builtin/cat-file.c b/builtin/cat-file.c index d9fbad5358..fa45f774d7 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -57,6 +57,20 @@ static int use_mailmap; static char *replace_idents_using_mailmap(char *, size_t *); +/* + * The mailmap is initialized with .strdup_strings set to 0, + * but read_mailmap() sets the bit to 1 (this is true even when + * not a single mailmap entry is read), so it can be used for + * lazy loading. + */ +static void load_mailmap(void) +{ + if (mailmap.strdup_strings) + return; + + read_mailmap(the_repository, &mailmap); +} + static char *replace_idents_using_mailmap(char *object_buf, size_t *size) { struct strbuf sb = STRBUF_INIT; @@ -692,6 +706,20 @@ static void parse_cmd_info(struct batch_options *opt, batch_one_object(line, output, opt, data); } +static void parse_cmd_mailmap(struct batch_options *opt UNUSED, + const char *line, + struct strbuf *output UNUSED, + struct expand_data *data UNUSED) +{ + use_mailmap = git_parse_maybe_bool(line); + + if (use_mailmap < 0) + die(_("mailmap: invalid boolean '%s'"), line); + + if (use_mailmap) + load_mailmap(); +} + static void dispatch_calls(struct batch_options *opt, struct strbuf *output, struct expand_data *data, @@ -725,9 +753,10 @@ static const struct parse_cmd { parse_cmd_fn_t fn; unsigned takes_args; } commands[] = { - { "contents", parse_cmd_contents, 1}, - { "info", parse_cmd_info, 1}, - { "flush", NULL, 0}, + { "contents", parse_cmd_contents, 1 }, + { "info", parse_cmd_info, 1 }, + { "flush", NULL, 0 }, + { "mailmap", parse_cmd_mailmap, 1 }, }; static void batch_objects_command(struct batch_options *opt, @@ -1131,7 +1160,7 @@ int cmd_cat_file(int argc, opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's'); if (use_mailmap) - read_mailmap(the_repository, &mailmap); + load_mailmap(); switch (batch.objects_filter.choice) { case LOFC_DISABLED: diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 74b7ddccb2..249548eb9b 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -1133,6 +1133,111 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us test_cmp expect actual ' +test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "info HEAD\nmailmap yes\ninfo HEAD\n" | git cat-file --batch-command >actual && + echo $commit_sha commit $size_no_mailmap >expect && + echo $commit_sha commit $size_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\n" | git cat-file --batch-command >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\nflush\n" | git cat-file --batch-command --buffer >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap no overrides startup --mailmap' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_mailmap=$(wc -c <commit_mailmap.out) && + git cat-file commit HEAD >commit_no_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + printf "info HEAD\nmailmap no\ninfo HEAD\n" | \ + git cat-file --mailmap --batch-command >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap yes overrides startup --no-mailmap' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "info HEAD\nmailmap yes\ninfo HEAD\n" | \ + git cat-file --no-mailmap --batch-command >actual && + echo $commit_sha commit $size_no_mailmap >expect && + echo $commit_sha commit $size_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap accepts true/false' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "mailmap true\ninfo HEAD\nmailmap false\ninfo HEAD\n" | \ + git cat-file --batch-command >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap rejects invalid boolean' ' + echo "mailmap maybe" >in && + test_must_fail git cat-file --batch-command <in 2>err && + test_grep "mailmap: invalid boolean .*maybe" err +' + test_expect_success 'git cat-file --mailmap works with different author and committer' ' test_when_finished "rm .mailmap" && cat >.mailmap <<-\EOF && -- 2.53.0 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH v4 1/1] cat-file: add mailmap subcommand to --batch-command 2026-04-15 15:09 ` [PATCH v4 1/1] " Siddharth Asthana @ 2026-04-15 18:28 ` Junio C Hamano 2026-04-16 3:08 ` Siddharth Asthana 0 siblings, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2026-04-15 18:28 UTC (permalink / raw) To: Siddharth Asthana; +Cc: git, karthik.188, christian.couder, ps, toon, jn.avila Siddharth Asthana <siddharthasthana31@gmail.com> writes: > diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc > index c139f55a16..0f499c9d1b 100644 > --- a/Documentation/git-cat-file.adoc > +++ b/Documentation/git-cat-file.adoc > @@ -174,6 +174,18 @@ flush:: > since the beginning or since the last flush was issued. When `--buffer` > is used, no output will come until a `flush` is issued. When `--buffer` > is not used, commands are flushed each time without issuing `flush`. > + > +`mailmap (<bool>)`:: > + Enable or disable mailmap for subsequent commands. The `<bool>` > + argument accepts the same boolean values as linkgit:git-config[1]. > + Possible effects are: > ++ > +`true`;; > + Mailmap data is loaded on first use and kept in memory until the > + process exits. Passing `true` again does not reload the data. > +`false`;; > + Mailmap replacements are disabled for subsequent commands, but data > + already loaded stays in memory. > -- > + While the above may not be telling any lies, I think the focus of the explanation is placed on a wrong thing. What primarily matters to end-users is that toggling 'mailmap' to true makes the mailmap applied to identities before they appear in the output and false makes the identities output without modification. The fact that you read the mailmap data only once and keep it around even when toggling the feature off, just in case the feature gets turned on again, is an implementation detail that is of much lessor interest to end users, no? Perhaps delete everything from "Possible effects are" and replace it with a brief explanation, e.g., `mailmap (<bool>)`:: Enable or disable mailmap for subsequent commands. The `<bool>` argument accepts the same boolean values as linkgit:git-config[1]. The mailmap data is read upon the first use and only once, even after the `mailmap` command is given multiple times to toggle it off and then on back again. would be sufficient (I would omit "even after ..." part, if I were writing it). What is more important than the optimization aspect of this implementation detail to end users is that we do not re-read, so if you update the file while you are running "cat-file --batch", even giving 'mailmap off; mailmap on' would not cause it to re-read the updated data, and "upon the first use and only once" should be sufficient to understand that. The implementation looks great. I do not recall how good the tests were but this round does not change anything there since the previous iteration. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v4 1/1] cat-file: add mailmap subcommand to --batch-command 2026-04-15 18:28 ` Junio C Hamano @ 2026-04-16 3:08 ` Siddharth Asthana 0 siblings, 0 replies; 27+ messages in thread From: Siddharth Asthana @ 2026-04-16 3:08 UTC (permalink / raw) To: Junio C Hamano; +Cc: git, karthik.188, christian.couder, ps, toon, jn.avila On 15/04/26 23:58, Junio C Hamano wrote: > Siddharth Asthana <siddharthasthana31@gmail.com> writes: > >> diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc >> index c139f55a16..0f499c9d1b 100644 >> --- a/Documentation/git-cat-file.adoc >> +++ b/Documentation/git-cat-file.adoc >> @@ -174,6 +174,18 @@ flush:: >> since the beginning or since the last flush was issued. When `--buffer` >> is used, no output will come until a `flush` is issued. When `--buffer` >> is not used, commands are flushed each time without issuing `flush`. >> + >> +`mailmap (<bool>)`:: >> + Enable or disable mailmap for subsequent commands. The `<bool>` >> + argument accepts the same boolean values as linkgit:git-config[1]. >> + Possible effects are: >> ++ >> +`true`;; >> + Mailmap data is loaded on first use and kept in memory until the >> + process exits. Passing `true` again does not reload the data. >> +`false`;; >> + Mailmap replacements are disabled for subsequent commands, but data >> + already loaded stays in memory. >> -- >> + > > While the above may not be telling any lies, I think the focus of > the explanation is placed on a wrong thing. What primarily matters > to end-users is that toggling 'mailmap' to true makes the mailmap > applied to identities before they appear in the output and false > makes the identities output without modification. The fact that you Make sense, the sub-list was over-explaining implementation details that users don't need to care about. > read the mailmap data only once and keep it around even when > toggling the feature off, just in case the feature gets turned on > again, is an implementation detail that is of much lessor interest > to end users, no? > > Perhaps delete everything from "Possible effects are" and replace it > with a brief explanation, e.g., > > `mailmap (<bool>)`:: > Enable or disable mailmap for subsequent commands. The `<bool>` > argument accepts the same boolean values as linkgit:git-config[1]. > The mailmap data is read upon the first use and only once, > even after the `mailmap` command is given multiple times to > toggle it off and then on back again. > > would be sufficient (I would omit "even after ..." part, if I were > writing it). What is more important than the optimization aspect of Agreed, I wend with the shorter version without the "even after" part. > this implementation detail to end users is that we do not re-read, > so if you update the file while you are running "cat-file --batch", > even giving 'mailmap off; mailmap on' would not cause it to re-read > the updated data, and "upon the first use and only once" should be > sufficient to understand that. > > The implementation looks great. I do not recall how good the tests > were but this round does not change anything there since the > previous iteration. Thnaks! I will send v5 with just this doc change. Siddharth ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v5 0/1] cat-file: add mailmap subcommand to --batch-command 2026-04-15 15:09 ` [PATCH v4 0/1] " Siddharth Asthana 2026-04-15 15:09 ` [PATCH v4 1/1] " Siddharth Asthana @ 2026-04-16 3:32 ` Siddharth Asthana 2026-04-16 3:32 ` [PATCH v5 1/1] " Siddharth Asthana 1 sibling, 1 reply; 27+ messages in thread From: Siddharth Asthana @ 2026-04-16 3:32 UTC (permalink / raw) To: git Cc: karthik.188, christian.couder, ps, gitster, toon, jn.avila, Siddharth Asthana git-cat-file(1)'s --batch-command works with the --use-mailmap option, but this option needs to be set when the process is created. This means we cannot change this option mid-operation. At GitLab, Gitaly keeps interacting with a long-lived git-cat-file process and it would be useful if --batch-command supported toggling mailmap dynamically on an existing process. This patch adds a `mailmap` subcommand to --batch-command that accepts a boolean argument and toggles mailmap dynamically for subsequent commands. The series is based on top of 5361983c07 (The 22nd batch, 2026-03-21). CI: https://gitlab.com/gitlab-org/git/-/pipelines/2456596910 Changes in v5: - Simplify documentation: remove the `;;` sub-list describing `true`/`false` effects and replace with a single sentence noting that mailmap data is read upon the first use and only once. - Link to v4: https://lore.kernel.org/git/20260415150943.40493-1-siddharthasthana31@gmail.com/T/#m5226263dafcf5c774c080a6688e9af0f402003c0 - Link to v3: https://lore.kernel.org/git/xmqqv7dyoei6.fsf@gitster.g/T/#m0a109f3eb5129e619ecec5f2d58ead0c5a49a4f3 - Link to v2: https://lore.kernel.org/git/xmqqv7dyoei6.fsf@gitster.g/T/#m445eab3b309bded92d1b130d225b882c73988ff2 - Link to v1: https://public-inbox.org/git/a4ec7bfa-f16b-4505-9b37-d3dd137e93cb@gmail.com/T/#m5c62fb6ad0fbcc99a706dba4c78b66359c247acd Thanks, Siddharth --- Siddharth Asthana (1): cat-file: add mailmap subcommand to --batch-command Documentation/git-cat-file.adoc | 5 ++ builtin/cat-file.c | 37 ++++++++++++-- t/t4203-mailmap.sh | 105 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 4 deletions(-) Range-diff versus v4: 1: 25ebffe39e ! 1: b4d6f08b43 cat-file: add mailmap subcommand to --batch-command @@ Documentation/git-cat-file.adoc: flush:: +`mailmap (<bool>)`:: + Enable or disable mailmap for subsequent commands. The `<bool>` + argument accepts the same boolean values as linkgit:git-config[1]. -+ Possible effects are: -++ -+`true`;; -+ Mailmap data is loaded on first use and kept in memory until the -+ process exits. Passing `true` again does not reload the data. -+`false`;; -+ Mailmap replacements are disabled for subsequent commands, but data -+ already loaded stays in memory. ++ The mailmap data is read upon the first use and only once. -- + base-commit: 5361983c075154725be47b65cca9a2421789e410 -- 2.53.0 ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v5 1/1] cat-file: add mailmap subcommand to --batch-command 2026-04-16 3:32 ` [PATCH v5 0/1] " Siddharth Asthana @ 2026-04-16 3:32 ` Siddharth Asthana 0 siblings, 0 replies; 27+ messages in thread From: Siddharth Asthana @ 2026-04-16 3:32 UTC (permalink / raw) To: git Cc: karthik.188, christian.couder, ps, gitster, toon, jn.avila, Siddharth Asthana git-cat-file(1)'s --batch-command works with the --use-mailmap option, but this option needs to be set when the process is created. This means we cannot change this option mid-operation. At GitLab, Gitaly keeps interacting with a long-lived git-cat-file process and it would be useful if --batch-command supported toggling mailmap dynamically on an existing process. Add a `mailmap` subcommand to --batch-command that takes a boolean argument (usual ways you can specify a boolean value like 'yes', 'true', etc., are supported). Mailmap data is loaded lazily and kept in memory, while a helper centralizes the one-time load path used both at startup and from the batch-command handler. Extend tests to cover runtime toggling, startup option interactions (`--mailmap`/`--no-mailmap`), accepted boolean forms, and invalid values. Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> --- CI: https://gitlab.com/gitlab-org/git/-/pipelines/2456596910 Documentation/git-cat-file.adoc | 5 ++ builtin/cat-file.c | 37 +++++++++-- t/t4203-mailmap.sh | 105 ++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 4 deletions(-) diff --git a/Documentation/git-cat-file.adoc b/Documentation/git-cat-file.adoc index c139f55a16..86b9181599 100644 --- a/Documentation/git-cat-file.adoc +++ b/Documentation/git-cat-file.adoc @@ -174,6 +174,11 @@ flush:: since the beginning or since the last flush was issued. When `--buffer` is used, no output will come until a `flush` is issued. When `--buffer` is not used, commands are flushed each time without issuing `flush`. + +`mailmap (<bool>)`:: + Enable or disable mailmap for subsequent commands. The `<bool>` + argument accepts the same boolean values as linkgit:git-config[1]. + The mailmap data is read upon the first use and only once. -- + diff --git a/builtin/cat-file.c b/builtin/cat-file.c index d9fbad5358..fa45f774d7 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -57,6 +57,20 @@ static int use_mailmap; static char *replace_idents_using_mailmap(char *, size_t *); +/* + * The mailmap is initialized with .strdup_strings set to 0, + * but read_mailmap() sets the bit to 1 (this is true even when + * not a single mailmap entry is read), so it can be used for + * lazy loading. + */ +static void load_mailmap(void) +{ + if (mailmap.strdup_strings) + return; + + read_mailmap(the_repository, &mailmap); +} + static char *replace_idents_using_mailmap(char *object_buf, size_t *size) { struct strbuf sb = STRBUF_INIT; @@ -692,6 +706,20 @@ static void parse_cmd_info(struct batch_options *opt, batch_one_object(line, output, opt, data); } +static void parse_cmd_mailmap(struct batch_options *opt UNUSED, + const char *line, + struct strbuf *output UNUSED, + struct expand_data *data UNUSED) +{ + use_mailmap = git_parse_maybe_bool(line); + + if (use_mailmap < 0) + die(_("mailmap: invalid boolean '%s'"), line); + + if (use_mailmap) + load_mailmap(); +} + static void dispatch_calls(struct batch_options *opt, struct strbuf *output, struct expand_data *data, @@ -725,9 +753,10 @@ static const struct parse_cmd { parse_cmd_fn_t fn; unsigned takes_args; } commands[] = { - { "contents", parse_cmd_contents, 1}, - { "info", parse_cmd_info, 1}, - { "flush", NULL, 0}, + { "contents", parse_cmd_contents, 1 }, + { "info", parse_cmd_info, 1 }, + { "flush", NULL, 0 }, + { "mailmap", parse_cmd_mailmap, 1 }, }; static void batch_objects_command(struct batch_options *opt, @@ -1131,7 +1160,7 @@ int cmd_cat_file(int argc, opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's'); if (use_mailmap) - read_mailmap(the_repository, &mailmap); + load_mailmap(); switch (batch.objects_filter.choice) { case LOFC_DISABLED: diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 74b7ddccb2..249548eb9b 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -1133,6 +1133,111 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us test_cmp expect actual ' +test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "info HEAD\nmailmap yes\ninfo HEAD\n" | git cat-file --batch-command >actual && + echo $commit_sha commit $size_no_mailmap >expect && + echo $commit_sha commit $size_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\n" | git cat-file --batch-command >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\nflush\n" | git cat-file --batch-command --buffer >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap no overrides startup --mailmap' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_mailmap=$(wc -c <commit_mailmap.out) && + git cat-file commit HEAD >commit_no_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + printf "info HEAD\nmailmap no\ninfo HEAD\n" | \ + git cat-file --mailmap --batch-command >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap yes overrides startup --no-mailmap' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "info HEAD\nmailmap yes\ninfo HEAD\n" | \ + git cat-file --no-mailmap --batch-command >actual && + echo $commit_sha commit $size_no_mailmap >expect && + echo $commit_sha commit $size_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap accepts true/false' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-\EOF && + C O Mitter <committer@example.com> Orig <orig@example.com> + EOF + commit_sha=$(git rev-parse HEAD) && + git cat-file commit HEAD >commit_no_mailmap.out && + size_no_mailmap=$(wc -c <commit_no_mailmap.out) && + git cat-file --use-mailmap commit HEAD >commit_mailmap.out && + size_mailmap=$(wc -c <commit_mailmap.out) && + printf "mailmap true\ninfo HEAD\nmailmap false\ninfo HEAD\n" | \ + git cat-file --batch-command >actual && + echo $commit_sha commit $size_mailmap >expect && + echo $commit_sha commit $size_no_mailmap >>expect && + test_cmp expect actual +' + +test_expect_success 'git cat-file --batch-command mailmap rejects invalid boolean' ' + echo "mailmap maybe" >in && + test_must_fail git cat-file --batch-command <in 2>err && + test_grep "mailmap: invalid boolean .*maybe" err +' + test_expect_success 'git cat-file --mailmap works with different author and committer' ' test_when_finished "rm .mailmap" && cat >.mailmap <<-\EOF && -- 2.53.0 ^ permalink raw reply related [flat|nested] 27+ messages in thread
end of thread, other threads:[~2026-04-16 3:33 UTC | newest] Thread overview: 27+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-03-28 20:36 [PATCH v1 1/1] cat-file: add use-mailmap/no-use-mailmap to --batch-command Siddharth Asthana 2026-03-29 0:50 ` Junio C Hamano 2026-03-29 7:25 ` Siddharth Asthana 2026-03-29 20:55 ` Junio C Hamano 2026-03-29 8:28 ` [PATCH v2 0/1] cat-file: add mailmap subcommand " Siddharth Asthana 2026-03-29 8:28 ` [PATCH v2 1/1] " Siddharth Asthana 2026-03-30 2:12 ` Junio C Hamano 2026-03-31 1:40 ` Siddharth Asthana 2026-03-31 3:41 ` Junio C Hamano 2026-03-30 9:44 ` Karthik Nayak 2026-03-31 1:42 ` Siddharth Asthana 2026-03-30 10:37 ` Patrick Steinhardt 2026-03-30 14:53 ` Junio C Hamano 2026-03-31 1:43 ` Siddharth Asthana 2026-03-31 17:11 ` Jean-Noël AVILA 2026-03-31 17:49 ` Junio C Hamano 2026-04-01 10:11 ` Jean-Noël Avila 2026-03-31 12:11 ` [PATCH v3 0/1] " Siddharth Asthana 2026-03-31 12:11 ` [PATCH v3 1/1] " Siddharth Asthana 2026-03-31 19:21 ` Junio C Hamano 2026-04-10 18:29 ` Junio C Hamano 2026-04-15 15:09 ` [PATCH v4 0/1] " Siddharth Asthana 2026-04-15 15:09 ` [PATCH v4 1/1] " Siddharth Asthana 2026-04-15 18:28 ` Junio C Hamano 2026-04-16 3:08 ` Siddharth Asthana 2026-04-16 3:32 ` [PATCH v5 0/1] " Siddharth Asthana 2026-04-16 3:32 ` [PATCH v5 1/1] " Siddharth Asthana
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox