public inbox for git@vger.kernel.org 
 help / color / mirror / Atom feed
From: Christian Couder <christian.couder@gmail•com>
To: git@vger•kernel.org
Cc: Junio C Hamano <gitster@pobox•com>,
	Patrick Steinhardt <ps@pks•im>, Elijah Newren <newren@gmail•com>,
	Jeff King <peff@peff•net>,
	"brian m . carlson" <sandals@crustytoothpaste•net>,
	Johannes Schindelin <Johannes.Schindelin@gmx•de>,
	Todd Zullinger <tmz@pobox•com>,
	Collin Funk <collin.funk1@gmail•com>,
	Christian Couder <christian.couder@gmail•com>,
	Christian Couder <chriscool@tuxfamily•org>
Subject: [PATCH v3 5/5] fast-import: add '--signed-tags=<mode>' option
Date: Mon, 13 Oct 2025 10:48:57 +0200	[thread overview]
Message-ID: <20251013084857.1646783-6-christian.couder@gmail.com> (raw)
In-Reply-To: <20251013084857.1646783-1-christian.couder@gmail.com>

Recently, eaaddf5791 (fast-import: add '--signed-commits=<mode>'
option, 2025-09-17) added support for controlling how signed commits
are handled by `git fast-import`, but there is no option yet to
decide about signed tags.

To remediate that, let's add a '--signed-tags=<mode>' option to
`git fast-import` too.

With this, both `git fast-export` and `git fast-import` have both
a '--signed-tags=<mode>' and a '--signed-commits=<mode>' supporting
the same <mode>s.

Signed-off-by: Christian Couder <chriscool@tuxfamily•org>
---
 Documentation/git-fast-import.adoc |  5 ++
 builtin/fast-import.c              | 43 ++++++++++++++++
 t/meson.build                      |  1 +
 t/t9306-fast-import-signed-tags.sh | 80 ++++++++++++++++++++++++++++++
 4 files changed, 129 insertions(+)
 create mode 100755 t/t9306-fast-import-signed-tags.sh

diff --git a/Documentation/git-fast-import.adoc b/Documentation/git-fast-import.adoc
index 85ed7a7270..b74179a6c8 100644
--- a/Documentation/git-fast-import.adoc
+++ b/Documentation/git-fast-import.adoc
@@ -66,6 +66,11 @@ fast-import stream! This option is enabled automatically for
 remote-helpers that use the `import` capability, as they are
 already trusted to run their own code.
 
+--signed-tags=(verbatim|warn-verbatim|warn-strip|strip|abort)::
+	Specify how to handle signed tags.  Behaves in the same way
+	as the same option in linkgit:git-fast-export[1], except that
+	default is 'verbatim' (instead of 'abort').
+
 --signed-commits=(verbatim|warn-verbatim|warn-strip|strip|abort)::
 	Specify how to handle signed commits.  Behaves in the same way
 	as the same option in linkgit:git-fast-export[1], except that
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index 2010e78475..60d6faa465 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -188,6 +188,7 @@ static int global_argc;
 static const char **global_argv;
 static const char *global_prefix;
 
+static enum sign_mode signed_tag_mode = SIGN_VERBATIM;
 static enum sign_mode signed_commit_mode = SIGN_VERBATIM;
 
 /* Memory pools */
@@ -2961,6 +2962,43 @@ static void parse_new_commit(const char *arg)
 	b->last_commit = object_count_by_type[OBJ_COMMIT];
 }
 
+static void handle_tag_signature(struct strbuf *msg, const char *name)
+{
+	size_t sig_offset = parse_signed_buffer(msg->buf, msg->len);
+
+	/* If there is no signature, there is nothing to do. */
+	if (sig_offset >= msg->len)
+		return;
+
+	switch (signed_tag_mode) {
+
+	/* First, modes that don't change anything */
+	case SIGN_ABORT:
+		die(_("encountered signed tag; use "
+		      "--signed-tags=<mode> to handle it"));
+	case SIGN_WARN_VERBATIM:
+		warning(_("importing a tag signature verbatim for tag '%s'"), name);
+		/* fallthru */
+	case SIGN_VERBATIM:
+		/* Nothing to do, the signature will be put into the imported tag. */
+		break;
+
+	/* Second, modes that remove the signature */
+	case SIGN_WARN_STRIP:
+		warning(_("stripping a tag signature for tag '%s'"), name);
+		/* fallthru */
+	case SIGN_STRIP:
+		/* Truncate the buffer to remove the signature */
+		strbuf_setlen(msg, sig_offset);
+		break;
+
+	/* Third, BUG */
+	default:
+		BUG("invalid signed_tag_mode value %d from tag '%s'",
+		    signed_tag_mode, name);
+	}
+}
+
 static void parse_new_tag(const char *arg)
 {
 	static struct strbuf msg = STRBUF_INIT;
@@ -3024,6 +3062,8 @@ static void parse_new_tag(const char *arg)
 	/* tag payload/message */
 	parse_data(&msg, 0, NULL);
 
+	handle_tag_signature(&msg, t->name);
+
 	/* build the tag object */
 	strbuf_reset(&new_data);
 
@@ -3544,6 +3584,9 @@ static int parse_one_option(const char *option)
 	} else if (skip_prefix(option, "signed-commits=", &option)) {
 		if (parse_sign_mode(option, &signed_commit_mode))
 			usagef(_("unknown --signed-commits mode '%s'"), option);
+	} else if (skip_prefix(option, "signed-tags=", &option)) {
+		if (parse_sign_mode(option, &signed_tag_mode))
+			usagef(_("unknown --signed-tags mode '%s'"), option);
 	} else if (!strcmp(option, "quiet")) {
 		show_stats = 0;
 		quiet = 1;
diff --git a/t/meson.build b/t/meson.build
index 11376b9e25..cb8c2b4b30 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -1036,6 +1036,7 @@ integration_tests = [
   't9303-fast-import-compression.sh',
   't9304-fast-import-marks.sh',
   't9305-fast-import-signatures.sh',
+  't9306-fast-import-signed-tags.sh',
   't9350-fast-export.sh',
   't9351-fast-export-anonymize.sh',
   't9400-git-cvsserver-server.sh',
diff --git a/t/t9306-fast-import-signed-tags.sh b/t/t9306-fast-import-signed-tags.sh
new file mode 100755
index 0000000000..363619e7d1
--- /dev/null
+++ b/t/t9306-fast-import-signed-tags.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+
+test_description='git fast-import --signed-tags=<mode>'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-gpg.sh"
+
+test_expect_success 'set up unsigned initial commit and import repo' '
+	test_commit first &&
+	git init new
+'
+
+test_expect_success 'import no signed tag with --signed-tags=abort' '
+	git fast-export --signed-tags=verbatim >output &&
+	git -C new fast-import --quiet --signed-tags=abort <output
+'
+
+test_expect_success GPG 'set up OpenPGP signed tag' '
+	git tag -s -m "OpenPGP signed tag" openpgp-signed first &&
+	OPENPGP_SIGNED=$(git rev-parse --verify refs/tags/openpgp-signed) &&
+	git fast-export --signed-tags=verbatim openpgp-signed >output
+'
+
+test_expect_success GPG 'import OpenPGP signed tag with --signed-tags=abort' '
+	test_must_fail git -C new fast-import --quiet --signed-tags=abort <output
+'
+
+test_expect_success GPG 'import OpenPGP signed tag with --signed-tags=verbatim' '
+	git -C new fast-import --quiet --signed-tags=verbatim <output >log 2>&1 &&
+	IMPORTED=$(git -C new rev-parse --verify refs/tags/openpgp-signed) &&
+	test $OPENPGP_SIGNED = $IMPORTED &&
+	test_must_be_empty log
+'
+
+test_expect_success GPGSM 'setup X.509 signed tag' '
+	test_config gpg.format x509 &&
+	test_config user.signingkey $GIT_COMMITTER_EMAIL &&
+
+	git tag -s -m "X.509 signed tag" x509-signed first &&
+	X509_SIGNED=$(git rev-parse --verify refs/tags/x509-signed) &&
+	git fast-export --signed-tags=verbatim x509-signed >output
+'
+
+test_expect_success GPGSM 'import X.509 signed tag with --signed-tags=warn-strip' '
+	git -C new fast-import --quiet --signed-tags=warn-strip <output >log 2>&1 &&
+	test_grep "stripping a tag signature for tag '\''x509-signed'\''" log &&
+	IMPORTED=$(git -C new rev-parse --verify refs/tags/x509-signed) &&
+	test $X509_SIGNED != $IMPORTED &&
+	git -C new cat-file -p x509-signed >out &&
+	test_grep ! "SIGNED MESSAGE" out
+'
+
+test_expect_success GPGSSH 'setup SSH signed tag' '
+	test_config gpg.format ssh &&
+	test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" &&
+
+	git tag -s -m "SSH signed tag" ssh-signed first &&
+	SSH_SIGNED=$(git rev-parse --verify refs/tags/ssh-signed) &&
+	git fast-export --signed-tags=verbatim ssh-signed >output
+'
+
+test_expect_success GPGSSH 'import SSH signed tag with --signed-tags=warn-verbatim' '
+	git -C new fast-import --quiet --signed-tags=warn-verbatim <output >log 2>&1 &&
+	test_grep "importing a tag signature verbatim for tag '\''ssh-signed'\''" log &&
+	IMPORTED=$(git -C new rev-parse --verify refs/tags/ssh-signed) &&
+	test $SSH_SIGNED = $IMPORTED
+'
+
+test_expect_success GPGSSH 'import SSH signed tag with --signed-tags=strip' '
+	git -C new fast-import --quiet --signed-tags=strip <output >log 2>&1 &&
+	test_must_be_empty log &&
+	IMPORTED=$(git -C new rev-parse --verify refs/tags/ssh-signed) &&
+	test $SSH_SIGNED != $IMPORTED &&
+	git -C new cat-file -p ssh-signed >out &&
+	test_grep ! "SSH SIGNATURE" out
+'
+
+test_done
-- 
2.51.0.438.g6987fc0bae


  parent reply	other threads:[~2025-10-13  8:49 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-07 12:29 [PATCH 0/5] fast-import: start controlling how tag signatures are handled Christian Couder
2025-10-07 12:29 ` [PATCH 1/5] doc: git-tag: stop focussing on GPG signed tags Christian Couder
2025-10-08  7:14   ` Patrick Steinhardt
2025-10-08  9:52     ` Christian Couder
2025-10-08 11:48       ` Patrick Steinhardt
2025-10-07 12:29 ` [PATCH 2/5] lib-gpg: allow tests with the GPGSM prereq first Christian Couder
2025-10-08  7:14   ` Patrick Steinhardt
2025-10-08  9:42     ` Christian Couder
2025-10-09  1:29       ` Collin Funk
2025-10-09  2:37         ` Todd Zullinger
2025-10-09 12:29           ` Christian Couder
2025-10-09 18:18           ` Junio C Hamano
2025-10-09 12:30         ` Christian Couder
2025-10-07 12:29 ` [PATCH 3/5] t9350: properly count annotated tags Christian Couder
2025-10-08  7:14   ` Patrick Steinhardt
2025-10-08 10:00     ` Christian Couder
2025-10-07 12:29 ` [PATCH 4/5] fast-export: handle all kinds of tag signatures Christian Couder
2025-10-08  7:14   ` Patrick Steinhardt
2025-10-08 10:02     ` Christian Couder
2025-10-09 12:33     ` Christian Couder
2025-10-07 12:29 ` [PATCH 5/5] fast-import: add '--signed-tags=<mode>' option Christian Couder
2025-10-08  7:14   ` Patrick Steinhardt
2025-10-08 10:50     ` Christian Couder
2025-10-08 11:53       ` Patrick Steinhardt
2025-10-09 12:24 ` [PATCH v2 0/5] fast-import: start controlling how tag signatures are handled Christian Couder
2025-10-09 12:24   ` [PATCH v2 1/5] doc: git-tag: stop focusing on GPG signed tags Christian Couder
2025-10-10  1:19     ` Junio C Hamano
2025-10-10  7:06       ` Christian Couder
2025-10-09 12:24   ` [PATCH v2 2/5] lib-gpg: allow tests with GPGSM or GPGSSH prereq first Christian Couder
2025-10-10  6:49     ` Patrick Steinhardt
2025-10-10 14:09       ` Todd Zullinger
2025-10-10 16:22         ` Junio C Hamano
2025-10-11  2:14           ` Todd Zullinger
2025-10-12  0:15             ` Junio C Hamano
2025-10-09 12:24   ` [PATCH v2 3/5] t9350: properly count annotated tags Christian Couder
2025-10-09 12:24   ` [PATCH v2 4/5] fast-export: handle all kinds of tag signatures Christian Couder
2025-10-09 12:24   ` [PATCH v2 5/5] fast-import: add '--signed-tags=<mode>' option Christian Couder
2025-10-09 21:35   ` [PATCH v2 0/5] fast-import: start controlling how tag signatures are handled Junio C Hamano
2025-10-13  8:48 ` [PATCH v3 " Christian Couder
2025-10-13  8:48   ` [PATCH v3 1/5] doc: git-tag: stop focusing on GPG signed tags Christian Couder
2025-10-24  2:03     ` Elijah Newren
2025-10-13  8:48   ` [PATCH v3 2/5] lib-gpg: allow tests with GPGSM or GPGSSH prereq first Christian Couder
2025-10-13  8:48   ` [PATCH v3 3/5] t9350: properly count annotated tags Christian Couder
2025-10-24  2:03     ` Elijah Newren
2025-10-13  8:48   ` [PATCH v3 4/5] fast-export: handle all kinds of tag signatures Christian Couder
2025-10-24  2:03     ` Elijah Newren
2025-10-13  8:48   ` Christian Couder [this message]
2025-10-24  2:03     ` [PATCH v3 5/5] fast-import: add '--signed-tags=<mode>' option Elijah Newren
2025-10-24  9:27       ` Christian Couder
2025-10-24 15:03       ` Junio C Hamano
2025-10-13  9:09   ` [PATCH v3 0/5] fast-import: start controlling how tag signatures are handled Christian Couder
2025-10-24  2:06     ` Elijah Newren

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251013084857.1646783-6-christian.couder@gmail.com \
    --to=christian.couder@gmail$(echo .)com \
    --cc=Johannes.Schindelin@gmx$(echo .)de \
    --cc=chriscool@tuxfamily$(echo .)org \
    --cc=collin.funk1@gmail$(echo .)com \
    --cc=git@vger$(echo .)kernel.org \
    --cc=gitster@pobox$(echo .)com \
    --cc=newren@gmail$(echo .)com \
    --cc=peff@peff$(echo .)net \
    --cc=ps@pks$(echo .)im \
    --cc=sandals@crustytoothpaste$(echo .)net \
    --cc=tmz@pobox$(echo .)com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox