diff mbox series

[v2,4/4] cat-file: add mailmap support

Message ID 20220707161554.6900-5-siddharthasthana31@gmail.com (mailing list archive)
State Superseded
Headers show
Series Add support for mailmap in cat-file | expand

Commit Message

Siddharth Asthana July 7, 2022, 4:15 p.m. UTC
git-cat-file is used by tools like GitLab to get commit tag contents
that are then displayed to users. This content which has author,
committer or tagger information, could benefit from passing through the
mailmap mechanism before being sent or displayed.

This patch adds --[no-]use-mailmap command line option to the git
cat-file command. It also adds --[no-]mailmap option as an alias to
--[no-]use-mailmap.

Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored-by: John Cai <johncai86@gmail.com>
Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Siddharth Asthana <siddharthasthana31@gmail.com>
---
 Documentation/git-cat-file.txt |  6 ++++
 builtin/cat-file.c             | 31 ++++++++++++++++++-
 t/t4203-mailmap.sh             | 54 ++++++++++++++++++++++++++++++++++
 3 files changed, 90 insertions(+), 1 deletion(-)

Comments

Junio C Hamano July 7, 2022, 9:55 p.m. UTC | #1
Siddharth Asthana <siddharthasthana31@gmail.com> writes:

> +char *replace_idents_using_mailmap(char *object_buf, size_t *size)

Does this function need to be extern?  If nobody other than callers
in cat-file would call it, perhaps it should be file-scope static.

> +{
> +	struct strbuf sb = STRBUF_INIT;
> +	strbuf_attach(&sb, object_buf, *size, *size + 1);
> +	const char *headers[] = { "author ", "committer ", "tagger ", NULL };

This is decl-after-statement.

> +	apply_mailmap_to_header(&sb, headers, &mailmap);
> +	*size = sb.len;
> +	return strbuf_detach(&sb, NULL);
> +}
Johannes Schindelin July 8, 2022, 11:53 a.m. UTC | #2
Hi Siddarth,

On Thu, 7 Jul 2022, Siddharth Asthana wrote:

> diff --git a/builtin/cat-file.c b/builtin/cat-file.c
> index 50cf38999d..6dc750a367 100644
> --- a/builtin/cat-file.c
> +++ b/builtin/cat-file.c
> @@ -36,6 +37,19 @@ struct batch_options {
>
>  static const char *force_path;
>
> +static struct string_list mailmap = STRING_LIST_INIT_NODUP;
> +static int use_mailmap;
> +
> +char *replace_idents_using_mailmap(char *object_buf, size_t *size)

Here, we declare the `size` parameter as a pointer to a `size_t`.

> +{
> +	struct strbuf sb = STRBUF_INIT;
> +	strbuf_attach(&sb, object_buf, *size, *size + 1);
> +	const char *headers[] = { "author ", "committer ", "tagger ", NULL };
> +	apply_mailmap_to_header(&sb, headers, &mailmap);
> +	*size = sb.len;
> +	return strbuf_detach(&sb, NULL);
> +}
> +
>  static int filter_object(const char *path, unsigned mode,
>  			 const struct object_id *oid,
>  			 char **buf, unsigned long *size)
> @@ -152,6 +166,9 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
>  		if (!buf)
>  			die("Cannot read object %s", obj_name);
>
> +		if (use_mailmap)
> +			buf = replace_idents_using_mailmap(buf, &size);

But here, we are once more bitten by Git's usage of last century's data
types: the `size` variable is of type `unsigned long`.

Now, you are probably developing this patch on 64-bit Linux or macOS,
where it just so happens that `size_t` is idempotent to `unsigned long`.

But that is not the case on 32-bit Linux nor on Windows, and therefore the
build fails with this patch. I need this to get the build to pass:

-- snipsnap --
From 237c783705b30ed4bcce81aeb860dc7e152fc8bf Mon Sep 17 00:00:00 2001
From: Johannes Schindelin <johannes.schindelin@gmx.de>
Date: Fri, 8 Jul 2022 13:47:52 +0200
Subject: [PATCH] fixup??? cat-file: add mailmap support

This is needed whenever `unsigned long` is different from `size_t`, e.g.
on 32-bit Linux and on Windows.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/cat-file.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index ac852087a74..baa6aca53ce 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -185,8 +185,13 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 		if (!buf)
 			die("Cannot read object %s", obj_name);

-		if (use_mailmap)
-			buf = replace_idents_using_mailmap(buf, &size);
+		if (use_mailmap) {
+			size_t s;
+
+			buf = replace_idents_using_mailmap(buf, &s);
+
+			size = cast_size_t_to_ulong(s);
+		}

 		/* otherwise just spit out the data */
 		break;
@@ -222,8 +227,13 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 		buf = read_object_with_reference(the_repository, &oid,
 						 exp_type_id, &size, NULL);

-		if (use_mailmap)
-			buf = replace_idents_using_mailmap(buf, &size);
+		if (use_mailmap) {
+			size_t s;
+
+			buf = replace_idents_using_mailmap(buf, &s);
+
+			size = cast_size_t_to_ulong(s);
+		}
 		break;
 	}
 	default:
@@ -392,8 +402,13 @@ static void print_object_or_die(struct batch_options *opt, struct expand_data *d

 		contents = read_object_file(oid, &type, &size);

-		if (use_mailmap)
-			contents = replace_idents_using_mailmap(contents, &size);
+		if (use_mailmap) {
+			size_t s;
+
+			contents = replace_idents_using_mailmap(contents, &s);
+
+			size = cast_size_t_to_ulong(s);
+		}

 		if (!contents)
 			die("object %s disappeared", oid_to_hex(oid));
--
2.37.0.windows.1
diff mbox series

Patch

diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
index 24a811f0ef..1880e9bba1 100644
--- a/Documentation/git-cat-file.txt
+++ b/Documentation/git-cat-file.txt
@@ -63,6 +63,12 @@  OPTIONS
 	or to ask for a "blob" with `<object>` being a tag object that
 	points at it.
 
+--[no-]mailmap::
+--[no-]use-mailmap::
+       Use mailmap file to map author, committer and tagger names
+       and email addresses to canonical real names and email addresses.
+       See linkgit:git-shortlog[1].
+
 --textconv::
 	Show the content as transformed by a textconv filter. In this case,
 	`<object>` has to be of the form `<tree-ish>:<path>`, or `:<path>` in
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 50cf38999d..6dc750a367 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -16,6 +16,7 @@ 
 #include "packfile.h"
 #include "object-store.h"
 #include "promisor-remote.h"
+#include "mailmap.h"
 
 enum batch_mode {
 	BATCH_MODE_CONTENTS,
@@ -36,6 +37,19 @@  struct batch_options {
 
 static const char *force_path;
 
+static struct string_list mailmap = STRING_LIST_INIT_NODUP;
+static int use_mailmap;
+
+char *replace_idents_using_mailmap(char *object_buf, size_t *size)
+{
+	struct strbuf sb = STRBUF_INIT;
+	strbuf_attach(&sb, object_buf, *size, *size + 1);
+	const char *headers[] = { "author ", "committer ", "tagger ", NULL };
+	apply_mailmap_to_header(&sb, headers, &mailmap);
+	*size = sb.len;
+	return strbuf_detach(&sb, NULL);
+}
+
 static int filter_object(const char *path, unsigned mode,
 			 const struct object_id *oid,
 			 char **buf, unsigned long *size)
@@ -152,6 +166,9 @@  static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 		if (!buf)
 			die("Cannot read object %s", obj_name);
 
+		if (use_mailmap)
+			buf = replace_idents_using_mailmap(buf, &size);
+
 		/* otherwise just spit out the data */
 		break;
 
@@ -183,6 +200,9 @@  static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
 		}
 		buf = read_object_with_reference(the_repository, &oid,
 						 exp_type_id, &size, NULL);
+
+		if (use_mailmap)
+			buf = replace_idents_using_mailmap(buf, &size);
 		break;
 	}
 	default:
@@ -348,11 +368,15 @@  static void print_object_or_die(struct batch_options *opt, struct expand_data *d
 		void *contents;
 
 		contents = read_object_file(oid, &type, &size);
+
+		if (use_mailmap)
+			contents = replace_idents_using_mailmap(contents, &size);
+
 		if (!contents)
 			die("object %s disappeared", oid_to_hex(oid));
 		if (type != data->type)
 			die("object %s changed type!?", oid_to_hex(oid));
-		if (data->info.sizep && size != data->size)
+		if (data->info.sizep && size != data->size && !use_mailmap)
 			die("object %s changed size!?", oid_to_hex(oid));
 
 		batch_write(opt, contents, size);
@@ -843,6 +867,8 @@  int cmd_cat_file(int argc, const char **argv, const char *prefix)
 		OPT_CMDMODE('s', NULL, &opt, N_("show object size"), 's'),
 		OPT_BOOL(0, "allow-unknown-type", &unknown_type,
 			  N_("allow -s and -t to work with broken/corrupt objects")),
+		OPT_BOOL(0, "use-mailmap", &use_mailmap, N_("use mail map file")),
+		OPT_ALIAS(0, "mailmap", "use-mailmap"),
 		/* Batch mode */
 		OPT_GROUP(N_("Batch objects requested on stdin (or --batch-all-objects)")),
 		OPT_CALLBACK_F(0, "batch", &batch, N_("format"),
@@ -885,6 +911,9 @@  int cmd_cat_file(int argc, const char **argv, const char *prefix)
 	opt_cw = (opt == 'c' || opt == 'w');
 	opt_epts = (opt == 'e' || opt == 'p' || opt == 't' || opt == 's');
 
+	if (use_mailmap)
+		read_mailmap(&mailmap);
+
 	/* --batch-all-objects? */
 	if (opt == 'b')
 		batch.all_objects = 1;
diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh
index 0b2d21ec55..c60a90615c 100755
--- a/t/t4203-mailmap.sh
+++ b/t/t4203-mailmap.sh
@@ -963,4 +963,58 @@  test_expect_success SYMLINKS 'symlinks not respected in-tree' '
 	test_cmp expect actual
 '
 
+test_expect_success '--no-use-mailmap disables mailmap in cat-file' '
+	test_when_finished "rm .mailmap" &&
+	cat >.mailmap <<-EOF &&
+	A U Thor <author@example.com> Orig <orig@example.com>
+	EOF
+	cat >expect <<-EOF &&
+	author Orig <orig@example.com>
+	EOF
+	git cat-file --no-use-mailmap commit HEAD >log &&
+	sed -n "/^author /s/\([^>]*>\).*/\1/p" log >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--use-mailmap enables mailmap in cat-file' '
+	test_when_finished "rm .mailmap" &&
+	cat >.mailmap <<-EOF &&
+	A U Thor <author@example.com> Orig <orig@example.com>
+	EOF
+	cat >expect <<-EOF &&
+	author A U Thor <author@example.com>
+	EOF
+	git cat-file --use-mailmap commit HEAD >log &&
+	sed -n "/^author /s/\([^>]*>\).*/\1/p" log >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--no-mailmap disables mailmap in cat-file for annotated tag objects' '
+	test_when_finished "rm .mailmap" &&
+	cat >.mailmap <<-EOF &&
+	Orig <orig@example.com> C O Mitter <committer@example.com>
+	EOF
+	cat >expect <<-EOF &&
+	tagger C O Mitter <committer@example.com>
+	EOF
+	git tag -a -m "annotated tag" v1 &&
+	git cat-file --no-mailmap -p v1 >log &&
+	sed -n "/^tagger /s/\([^>]*>\).*/\1/p" log >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--mailmap enables mailmap in cat-file for annotated tag objects' '
+	test_when_finished "rm .mailmap" &&
+	cat >.mailmap <<-EOF &&
+	Orig <orig@example.com> C O Mitter <committer@example.com>
+	EOF
+	cat >expect <<-EOF &&
+	tagger Orig <orig@example.com>
+	EOF
+	git tag -a -m "annotated tag" v2 &&
+	git cat-file --mailmap -p v2 >log &&
+	sed -n "/^tagger /s/\([^>]*>\).*/\1/p" log >actual &&
+	test_cmp expect actual
+'
+
 test_done