cat-file: add mailmap support to --batch-check option

Even though the cat-file command with `--batch-check` option does not complain when `--use-mailmap` option is given, the latter option is ignored. Compute the size of the object after replacing the idents and report it instead. In order to make `--batch-check` option honour the mailmap mechanism we have to read the contents of the commit/tag object. There were two ways to do it: 1. Make two calls to `oid_object_info_extended()`. If `--use-mailmap` option is given, the first call will get us the type of the object and second call will only be made if the object type is either a commit or tag to get the contents of the object. 2. Make one call to `oid_object_info_extended()` to get the type of the object. Then, if the object type is either of commit or tag, make a call to `repo_read_object_file()` to read the contents of the object. I benchmarked the following command with both the above approaches and compared against the current implementation where `--use-mailmap` option is ignored: `git cat-file --use-mailmap --batch-all-objects --batch-check --buffer --unordered` The results can be summarized as follows: Time (mean ± σ) default 827.7 ms ± 104.8 ms first approach 6.197 s ± 0.093 s second approach 1.975 s ± 0.217 s Since, the second approach is faster than the first one, I implemented it in this patch. The command git cat-file can now use the mailmap mechanism to replace idents with canonical versions for commit and tag objects. There are several options like `--batch`, `--batch-check` and `--batch-command` that can be combined with `--use-mailmap`. But the documentation for `--batch`, `--batch-check` and `--batch-command` doesn't say so. This patch fixes that documentation. Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: John Cai <johncai86@gmail.com> Helped-by: Taylor Blau <me@ttaylorr.com> Helped-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Siddharth Asthana committed Dec 20, 2022 at 11:31 UTC a797c0ea042af697d82ad475b9f354c4a33a9047
3 files changed +87 -13
Documentation/git-cat-file.txt
+36 -13
@@ -91,26 +91,49 @@ OPTIONS
91 --batch::
92 --batch=<format>::
93 Print object information and contents for each object provided
94 - on stdin. May not be combined with any other options or arguments
95 - except `--textconv` or `--filters`, in which case the input lines
96 - also need to specify the path, separated by whitespace. See the
97 - section `BATCH OUTPUT` below for details.
94 + on stdin. May not be combined with any other options or arguments
95 + except `--textconv`, `--filters`, or `--use-mailmap`.
96 + +
97 + * When used with `--textconv` or `--filters`, the input lines
98 + must specify the path, separated by whitespace. See the section
99 + `BATCH OUTPUT` below for details.
100 + +
101 + * When used with `--use-mailmap`, for commit and tag objects, the
102 + contents part of the output shows the identities replaced using the
103 + mailmap mechanism, while the information part of the output shows
104 + the size of the object as if it actually recorded the replacement
105 + identities.
106
107 --batch-check::
108 --batch-check=<format>::
101 - Print object information for each object provided on stdin. May
102 - not be combined with any other options or arguments except
103 - `--textconv` or `--filters`, in which case the input lines also
104 - need to specify the path, separated by whitespace. See the
105 - section `BATCH OUTPUT` below for details.
109 + Print object information for each object provided on stdin. May not be
110 + combined with any other options or arguments except `--textconv`, `--filters`
111 + or `--use-mailmap`.
112 + +
113 + * When used with `--textconv` or `--filters`, the input lines must
114 + specify the path, separated by whitespace. See the section
115 + `BATCH OUTPUT` below for details.
116 + +
117 + * When used with `--use-mailmap`, for commit and tag objects, the
118 + printed object information shows the size of the object as if the
119 + identities recorded in it were replaced by the mailmap mechanism.
120
121 --batch-command::
122 --batch-command=<format>::
123 Enter a command mode that reads commands and arguments from stdin. May
110 - only be combined with `--buffer`, `--textconv` or `--filters`. In the
111 - case of `--textconv` or `--filters`, the input lines also need to specify
112 - the path, separated by whitespace. See the section `BATCH OUTPUT` below
113 - for details.
124 + only be combined with `--buffer`, `--textconv`, `--use-mailmap` or
125 + `--filters`.
126 + +
127 + * When used with `--textconv` or `--filters`, the input lines must
128 + specify the path, separated by whitespace. See the section
129 + `BATCH OUTPUT` below for details.
130 + +
131 + * When used with `--use-mailmap`, for commit and tag objects, the
132 + `contents` command shows the identities replaced using the
133 + mailmap mechanism, while the `info` command shows the size
134 + of the object as if it actually recorded the replacement
135 + identities.
136 +
137 +
138 `--batch-command` recognizes the following commands:
139 +
builtin/cat-file.c
+15
@@ -444,6 +444,9 @@ static void batch_object_write(const char *obj_name,
444 if (!data->skip_object_info) {
445 int ret;
446
447 + if (use_mailmap)
448 + data->info.typep = &data->type;
449 +
450 if (pack)
451 ret = packed_object_info(the_repository, pack, offset,
452 &data->info);
@@ -457,6 +460,18 @@ static void batch_object_write(const char *obj_name,
460 fflush(stdout);
461 return;
462 }
463 +
464 + if (use_mailmap && (data->type == OBJ_COMMIT || data->type == OBJ_TAG)) {
465 + size_t s = data->size;
466 + char *buf = NULL;
467 +
468 + buf = repo_read_object_file(the_repository, &data->oid, &data->type,
469 + &data->size);
470 + buf = replace_idents_using_mailmap(buf, &s);
471 + data->size = cast_size_t_to_ulong(s);
472 +
473 + free(buf);
474 + }
475 }
476
477 strbuf_reset(scratch);
t/t4203-mailmap.sh
+36
@@ -1051,4 +1051,40 @@ test_expect_success 'git cat-file -s returns correct size with --use-mailmap for
1051 test_cmp expect actual
1052 '
1053
1054 +test_expect_success 'git cat-file --batch-check returns correct size with --use-mailmap' '
1055 + test_when_finished "rm .mailmap" &&
1056 + cat >.mailmap <<-\EOF &&
1057 + C O Mitter <committer@example.com> Orig <orig@example.com>
1058 + EOF
1059 + git cat-file commit HEAD >commit.out &&
1060 + commit_size=$(wc -c <commit.out) &&
1061 + commit_sha=$(git rev-parse HEAD) &&
1062 + echo $commit_sha commit $commit_size >expect &&
1063 + git cat-file --use-mailmap commit HEAD >commit.out &&
1064 + commit_size=$(wc -c <commit.out) &&
1065 + echo $commit_sha commit $commit_size >>expect &&
1066 + echo "HEAD" >in &&
1067 + git cat-file --batch-check <in >actual &&
1068 + git cat-file --use-mailmap --batch-check <in >>actual &&
1069 + test_cmp expect actual
1070 +'
1071 +
1072 +test_expect_success 'git cat-file --batch-command returns correct size with --use-mailmap' '
1073 + test_when_finished "rm .mailmap" &&
1074 + cat >.mailmap <<-\EOF &&
1075 + C O Mitter <committer@example.com> Orig <orig@example.com>
1076 + EOF
1077 + git cat-file commit HEAD >commit.out &&
1078 + commit_size=$(wc -c <commit.out) &&
1079 + commit_sha=$(git rev-parse HEAD) &&
1080 + echo $commit_sha commit $commit_size >expect &&
1081 + git cat-file --use-mailmap commit HEAD >commit.out &&
1082 + commit_size=$(wc -c <commit.out) &&
1083 + echo $commit_sha commit $commit_size >>expect &&
1084 + echo "info HEAD" >in &&
1085 + git cat-file --batch-command <in >actual &&
1086 + git cat-file --use-mailmap --batch-command <in >>actual &&
1087 + test_cmp expect actual
1088 +'
1089 +
1090 test_done