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(-)
Show changes to 3 files +86 −4
Documentation/git-cat-file.adoc, builtin/cat-file.c, t/t4203-mailmap.sh
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