Skip to content

Commit 8811bb9

Browse files
edith007gitster
authored andcommitted
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 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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 5361983 commit 8811bb9

File tree

3 files changed

+150
-4
lines changed

3 files changed

+150
-4
lines changed

Documentation/git-cat-file.adoc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,18 @@ flush::
174174
since the beginning or since the last flush was issued. When `--buffer`
175175
is used, no output will come until a `flush` is issued. When `--buffer`
176176
is not used, commands are flushed each time without issuing `flush`.
177+
178+
`mailmap (<bool>)`::
179+
Enable or disable mailmap for subsequent commands. The `<bool>`
180+
argument accepts the same boolean values as linkgit:git-config[1].
181+
Possible effects are:
182+
+
183+
`true`;;
184+
Mailmap data is loaded on first use and kept in memory until the
185+
process exits. Passing `true` again does not reload the data.
186+
`false`;;
187+
Mailmap replacements are disabled for subsequent commands, but data
188+
already loaded stays in memory.
177189
--
178190
+
179191

builtin/cat-file.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,20 @@ static int use_mailmap;
5757

5858
static char *replace_idents_using_mailmap(char *, size_t *);
5959

60+
/*
61+
* The mailmap is initialized with .strdup_strings set to 0,
62+
* but read_mailmap() sets the bit to 1 (this is true even when
63+
* not a single mailmap entry is read), so it can be used for
64+
* lazy loading.
65+
*/
66+
static void load_mailmap(void)
67+
{
68+
if (mailmap.strdup_strings)
69+
return;
70+
71+
read_mailmap(the_repository, &mailmap);
72+
}
73+
6074
static char *replace_idents_using_mailmap(char *object_buf, size_t *size)
6175
{
6276
struct strbuf sb = STRBUF_INIT;
@@ -692,6 +706,20 @@ static void parse_cmd_info(struct batch_options *opt,
692706
batch_one_object(line, output, opt, data);
693707
}
694708

709+
static void parse_cmd_mailmap(struct batch_options *opt UNUSED,
710+
const char *line,
711+
struct strbuf *output UNUSED,
712+
struct expand_data *data UNUSED)
713+
{
714+
use_mailmap = git_parse_maybe_bool(line);
715+
716+
if (use_mailmap < 0)
717+
die(_("mailmap: invalid boolean '%s'"), line);
718+
719+
if (use_mailmap)
720+
load_mailmap();
721+
}
722+
695723
static void dispatch_calls(struct batch_options *opt,
696724
struct strbuf *output,
697725
struct expand_data *data,
@@ -725,9 +753,10 @@ static const struct parse_cmd {
725753
parse_cmd_fn_t fn;
726754
unsigned takes_args;
727755
} commands[] = {
728-
{ "contents", parse_cmd_contents, 1},
729-
{ "info", parse_cmd_info, 1},
730-
{ "flush", NULL, 0},
756+
{ "contents", parse_cmd_contents, 1 },
757+
{ "info", parse_cmd_info, 1 },
758+
{ "flush", NULL, 0 },
759+
{ "mailmap", parse_cmd_mailmap, 1 },
731760
};
732761

733762
static void batch_objects_command(struct batch_options *opt,
@@ -1128,7 +1157,7 @@ int cmd_cat_file(int argc,
11281157
opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');
11291158

11301159
if (use_mailmap)
1131-
read_mailmap(the_repository, &mailmap);
1160+
load_mailmap();
11321161

11331162
switch (batch.objects_filter.choice) {
11341163
case LOFC_DISABLED:

t/t4203-mailmap.sh

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,111 @@ test_expect_success 'git cat-file --batch-command returns correct size with --us
11331133
test_cmp expect actual
11341134
'
11351135

1136+
test_expect_success 'git cat-file --batch-command mailmap yes enables mailmap mid-stream' '
1137+
test_when_finished "rm .mailmap" &&
1138+
cat >.mailmap <<-\EOF &&
1139+
C O Mitter <committer@example.com> Orig <orig@example.com>
1140+
EOF
1141+
commit_sha=$(git rev-parse HEAD) &&
1142+
git cat-file commit HEAD >commit_no_mailmap.out &&
1143+
git cat-file --use-mailmap commit HEAD >commit_mailmap.out &&
1144+
size_no_mailmap=$(wc -c <commit_no_mailmap.out) &&
1145+
size_mailmap=$(wc -c <commit_mailmap.out) &&
1146+
printf "info HEAD\nmailmap yes\ninfo HEAD\n" | git cat-file --batch-command >actual &&
1147+
echo $commit_sha commit $size_no_mailmap >expect &&
1148+
echo $commit_sha commit $size_mailmap >>expect &&
1149+
test_cmp expect actual
1150+
'
1151+
1152+
test_expect_success 'git cat-file --batch-command mailmap no disables mailmap mid-stream' '
1153+
test_when_finished "rm .mailmap" &&
1154+
cat >.mailmap <<-\EOF &&
1155+
C O Mitter <committer@example.com> Orig <orig@example.com>
1156+
EOF
1157+
commit_sha=$(git rev-parse HEAD) &&
1158+
git cat-file commit HEAD >commit_no_mailmap.out &&
1159+
git cat-file --use-mailmap commit HEAD >commit_mailmap.out &&
1160+
size_no_mailmap=$(wc -c <commit_no_mailmap.out) &&
1161+
size_mailmap=$(wc -c <commit_mailmap.out) &&
1162+
printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\n" | git cat-file --batch-command >actual &&
1163+
echo $commit_sha commit $size_mailmap >expect &&
1164+
echo $commit_sha commit $size_no_mailmap >>expect &&
1165+
test_cmp expect actual
1166+
'
1167+
1168+
test_expect_success 'git cat-file --batch-command mailmap works in --buffer mode' '
1169+
test_when_finished "rm .mailmap" &&
1170+
cat >.mailmap <<-\EOF &&
1171+
C O Mitter <committer@example.com> Orig <orig@example.com>
1172+
EOF
1173+
commit_sha=$(git rev-parse HEAD) &&
1174+
git cat-file commit HEAD >commit_no_mailmap.out &&
1175+
git cat-file --use-mailmap commit HEAD >commit_mailmap.out &&
1176+
size_no_mailmap=$(wc -c <commit_no_mailmap.out) &&
1177+
size_mailmap=$(wc -c <commit_mailmap.out) &&
1178+
printf "mailmap yes\ninfo HEAD\nmailmap no\ninfo HEAD\nflush\n" | git cat-file --batch-command --buffer >actual &&
1179+
echo $commit_sha commit $size_mailmap >expect &&
1180+
echo $commit_sha commit $size_no_mailmap >>expect &&
1181+
test_cmp expect actual
1182+
'
1183+
1184+
test_expect_success 'git cat-file --batch-command mailmap no overrides startup --mailmap' '
1185+
test_when_finished "rm .mailmap" &&
1186+
cat >.mailmap <<-\EOF &&
1187+
C O Mitter <committer@example.com> Orig <orig@example.com>
1188+
EOF
1189+
commit_sha=$(git rev-parse HEAD) &&
1190+
git cat-file --use-mailmap commit HEAD >commit_mailmap.out &&
1191+
size_mailmap=$(wc -c <commit_mailmap.out) &&
1192+
git cat-file commit HEAD >commit_no_mailmap.out &&
1193+
size_no_mailmap=$(wc -c <commit_no_mailmap.out) &&
1194+
printf "info HEAD\nmailmap no\ninfo HEAD\n" | \
1195+
git cat-file --mailmap --batch-command >actual &&
1196+
echo $commit_sha commit $size_mailmap >expect &&
1197+
echo $commit_sha commit $size_no_mailmap >>expect &&
1198+
test_cmp expect actual
1199+
'
1200+
1201+
test_expect_success 'git cat-file --batch-command mailmap yes overrides startup --no-mailmap' '
1202+
test_when_finished "rm .mailmap" &&
1203+
cat >.mailmap <<-\EOF &&
1204+
C O Mitter <committer@example.com> Orig <orig@example.com>
1205+
EOF
1206+
commit_sha=$(git rev-parse HEAD) &&
1207+
git cat-file commit HEAD >commit_no_mailmap.out &&
1208+
size_no_mailmap=$(wc -c <commit_no_mailmap.out) &&
1209+
git cat-file --use-mailmap commit HEAD >commit_mailmap.out &&
1210+
size_mailmap=$(wc -c <commit_mailmap.out) &&
1211+
printf "info HEAD\nmailmap yes\ninfo HEAD\n" | \
1212+
git cat-file --no-mailmap --batch-command >actual &&
1213+
echo $commit_sha commit $size_no_mailmap >expect &&
1214+
echo $commit_sha commit $size_mailmap >>expect &&
1215+
test_cmp expect actual
1216+
'
1217+
1218+
test_expect_success 'git cat-file --batch-command mailmap accepts true/false' '
1219+
test_when_finished "rm .mailmap" &&
1220+
cat >.mailmap <<-\EOF &&
1221+
C O Mitter <committer@example.com> Orig <orig@example.com>
1222+
EOF
1223+
commit_sha=$(git rev-parse HEAD) &&
1224+
git cat-file commit HEAD >commit_no_mailmap.out &&
1225+
size_no_mailmap=$(wc -c <commit_no_mailmap.out) &&
1226+
git cat-file --use-mailmap commit HEAD >commit_mailmap.out &&
1227+
size_mailmap=$(wc -c <commit_mailmap.out) &&
1228+
printf "mailmap true\ninfo HEAD\nmailmap false\ninfo HEAD\n" | \
1229+
git cat-file --batch-command >actual &&
1230+
echo $commit_sha commit $size_mailmap >expect &&
1231+
echo $commit_sha commit $size_no_mailmap >>expect &&
1232+
test_cmp expect actual
1233+
'
1234+
1235+
test_expect_success 'git cat-file --batch-command mailmap rejects invalid boolean' '
1236+
echo "mailmap maybe" >in &&
1237+
test_must_fail git cat-file --batch-command <in 2>err &&
1238+
test_grep "mailmap: invalid boolean .*maybe" err
1239+
'
1240+
11361241
test_expect_success 'git cat-file --mailmap works with different author and committer' '
11371242
test_when_finished "rm .mailmap" &&
11381243
cat >.mailmap <<-\EOF &&

0 commit comments

Comments
 (0)