fast-export, fast-import: add support for signed-commits

fast-export has a --signed-tags= option that controls how to handle tag
signatures.  However, there is no equivalent for commit signatures; it
just silently strips the signature out of the commit (analogously to
--signed-tags=strip).

While signatures are generally problematic for fast-export/fast-import
(because hashes are likely to change), if they're going to support tag
signatures, there's no reason to not also support commit signatures.

So, implement a --signed-commits= option that mirrors the --signed-tags=
option.

On the fast-export side, try to be as much like signed-tags as possible,
in both implementation and in user-interface.  This will change the
default behavior to '--signed-commits=abort' from what is now
'--signed-commits=strip'.  In order to provide an escape hatch for users
of third-party tools that call fast-export and do not yet know of the
--signed-commits= option, add an environment variable
'FAST_EXPORT_SIGNED_COMMITS_NOABORT=1' that changes the default to
'--signed-commits=warn-strip'.

Signed-off-by: Luke Shumaker <lukeshu@datawire.io>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Luke Shumaker
2025-03-10 16:57:46 +01:00
committed by Junio C Hamano
parent dda9bff3c5
commit d9cb0e6ff8
5 changed files with 253 additions and 20 deletions

View File

@@ -2719,10 +2719,13 @@ static struct hash_list *parse_merge(unsigned int *count)
static void parse_new_commit(const char *arg)
{
static struct strbuf sig = STRBUF_INIT;
static struct strbuf msg = STRBUF_INIT;
struct string_list siglines = STRING_LIST_INIT_NODUP;
struct branch *b;
char *author = NULL;
char *committer = NULL;
char *sig_alg = NULL;
char *encoding = NULL;
struct hash_list *merge_list = NULL;
unsigned int merge_count;
@@ -2746,6 +2749,13 @@ static void parse_new_commit(const char *arg)
}
if (!committer)
die("Expected committer but didn't get one");
if (skip_prefix(command_buf.buf, "gpgsig ", &v)) {
sig_alg = xstrdup(v);
read_next_command();
parse_data(&sig, 0, NULL);
read_next_command();
} else
strbuf_setlen(&sig, 0);
if (skip_prefix(command_buf.buf, "encoding ", &v)) {
encoding = xstrdup(v);
read_next_command();
@@ -2819,10 +2829,23 @@ static void parse_new_commit(const char *arg)
strbuf_addf(&new_data,
"encoding %s\n",
encoding);
if (sig_alg) {
if (!strcmp(sig_alg, "sha1"))
strbuf_addstr(&new_data, "gpgsig ");
else if (!strcmp(sig_alg, "sha256"))
strbuf_addstr(&new_data, "gpgsig-sha256 ");
else
die("Expected gpgsig algorithm sha1 or sha256, got %s", sig_alg);
string_list_split_in_place(&siglines, sig.buf, "\n", -1);
strbuf_add_separated_string_list(&new_data, "\n ", &siglines);
strbuf_addch(&new_data, '\n');
}
strbuf_addch(&new_data, '\n');
strbuf_addbuf(&new_data, &msg);
string_list_clear(&siglines, 1);
free(author);
free(committer);
free(sig_alg);
free(encoding);
if (!store_object(OBJ_COMMIT, &new_data, NULL, &b->oid, next_mark))