aboutsummaryrefslogtreecommitdiffstats
path: root/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'builtin')
-rw-r--r--builtin/fast-export.c62
-rw-r--r--builtin/fast-import.c113
2 files changed, 139 insertions, 36 deletions
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 6a3a17a8cd..f4169dc5f3 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -29,6 +29,7 @@
#include "quote.h"
#include "remote.h"
#include "blob.h"
+#include "gpg-interface.h"
static const char *const fast_export_usage[] = {
N_("git fast-export [<rev-list-opts>]"),
@@ -652,6 +653,38 @@ static const char *find_commit_multiline_header(const char *msg,
return strbuf_detach(&val, NULL);
}
+static void print_signature(const char *signature, const char *object_hash)
+{
+ if (!signature)
+ return;
+
+ printf("gpgsig %s %s\ndata %u\n%s\n",
+ object_hash,
+ get_signature_format(signature),
+ (unsigned)strlen(signature),
+ signature);
+}
+
+static const char *append_signatures_for_header(struct string_list *signatures,
+ const char *pos,
+ const char *header,
+ const char *object_hash)
+{
+ const char *signature;
+ const char *start = pos;
+ const char *end = pos;
+
+ while ((signature = find_commit_multiline_header(start + 1,
+ header,
+ &end))) {
+ string_list_append(signatures, signature)->util = (void *)object_hash;
+ free((char *)signature);
+ start = end;
+ }
+
+ return end;
+}
+
static void handle_commit(struct commit *commit, struct rev_info *rev,
struct string_list *paths_of_changed_objects)
{
@@ -660,7 +693,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
const char *author, *author_end, *committer, *committer_end;
const char *encoding = NULL;
size_t encoding_len;
- const char *signature_alg = NULL, *signature = NULL;
+ struct string_list signatures = STRING_LIST_INIT_DUP;
const char *message;
char *reencoded = NULL;
struct commit_list *p;
@@ -700,10 +733,11 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
}
if (*commit_buffer_cursor == '\n') {
- if ((signature = find_commit_multiline_header(commit_buffer_cursor + 1, "gpgsig", &commit_buffer_cursor)))
- signature_alg = "sha1";
- else if ((signature = find_commit_multiline_header(commit_buffer_cursor + 1, "gpgsig-sha256", &commit_buffer_cursor)))
- signature_alg = "sha256";
+ const char *after_sha1 = append_signatures_for_header(&signatures, commit_buffer_cursor,
+ "gpgsig", "sha1");
+ const char *after_sha256 = append_signatures_for_header(&signatures, commit_buffer_cursor,
+ "gpgsig-sha256", "sha256");
+ commit_buffer_cursor = (after_sha1 > after_sha256) ? after_sha1 : after_sha256;
}
message = strstr(commit_buffer_cursor, "\n\n");
@@ -769,30 +803,30 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
printf("%.*s\n%.*s\n",
(int)(author_end - author), author,
(int)(committer_end - committer), committer);
- if (signature) {
+ if (signatures.nr) {
switch (signed_commit_mode) {
case SIGN_ABORT:
die("encountered signed commit %s; use "
"--signed-commits=<mode> to handle it",
oid_to_hex(&commit->object.oid));
case SIGN_WARN_VERBATIM:
- warning("exporting signed commit %s",
- oid_to_hex(&commit->object.oid));
+ warning("exporting %"PRIuMAX" signature(s) for commit %s",
+ (uintmax_t)signatures.nr, oid_to_hex(&commit->object.oid));
/* fallthru */
case SIGN_VERBATIM:
- printf("gpgsig %s\ndata %u\n%s",
- signature_alg,
- (unsigned)strlen(signature),
- signature);
+ for (size_t i = 0; i < signatures.nr; i++) {
+ struct string_list_item *item = &signatures.items[i];
+ print_signature(item->string, item->util);
+ }
break;
case SIGN_WARN_STRIP:
- warning("stripping signature from commit %s",
+ warning("stripping signature(s) from commit %s",
oid_to_hex(&commit->object.oid));
/* fallthru */
case SIGN_STRIP:
break;
}
- free((char *)signature);
+ string_list_clear(&signatures, 0);
}
if (!reencoded && encoding)
printf("encoding %.*s\n", (int)encoding_len, encoding);
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index b1389c5921..6e7d0c3449 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -29,6 +29,7 @@
#include "commit-reach.h"
#include "khash.h"
#include "date.h"
+#include "gpg-interface.h"
#define PACK_ID_BITS 16
#define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
@@ -2716,15 +2717,82 @@ static struct hash_list *parse_merge(unsigned int *count)
return list;
}
+struct signature_data {
+ char *hash_algo; /* "sha1" or "sha256" */
+ char *sig_format; /* "openpgp", "x509", "ssh", or "unknown" */
+ struct strbuf data; /* The actual signature data */
+};
+
+static void parse_one_signature(struct signature_data *sig, const char *v)
+{
+ char *args = xstrdup(v); /* Will be freed when sig->hash_algo is freed */
+ char *space = strchr(args, ' ');
+
+ if (!space)
+ die("Expected gpgsig format: 'gpgsig <hash-algo> <signature-format>', "
+ "got 'gpgsig %s'", args);
+ *space = '\0';
+
+ sig->hash_algo = args;
+ sig->sig_format = space + 1;
+
+ /* Validate hash algorithm */
+ if (strcmp(sig->hash_algo, "sha1") &&
+ strcmp(sig->hash_algo, "sha256"))
+ die("Unknown git hash algorithm in gpgsig: '%s'", sig->hash_algo);
+
+ /* Validate signature format */
+ if (!valid_signature_format(sig->sig_format))
+ die("Invalid signature format in gpgsig: '%s'", sig->sig_format);
+ if (!strcmp(sig->sig_format, "unknown"))
+ warning("'unknown' signature format in gpgsig");
+
+ /* Read signature data */
+ read_next_command();
+ parse_data(&sig->data, 0, NULL);
+}
+
+static void add_gpgsig_to_commit(struct strbuf *commit_data,
+ const char *header,
+ struct signature_data *sig)
+{
+ struct string_list siglines = STRING_LIST_INIT_NODUP;
+
+ if (!sig->hash_algo)
+ return;
+
+ strbuf_addstr(commit_data, header);
+ string_list_split_in_place(&siglines, sig->data.buf, "\n", -1);
+ strbuf_add_separated_string_list(commit_data, "\n ", &siglines);
+ strbuf_addch(commit_data, '\n');
+ string_list_clear(&siglines, 1);
+ strbuf_release(&sig->data);
+ free(sig->hash_algo);
+}
+
+static void store_signature(struct signature_data *stored_sig,
+ struct signature_data *new_sig,
+ const char *hash_type)
+{
+ if (stored_sig->hash_algo) {
+ warning("multiple %s signatures found, "
+ "ignoring additional signature",
+ hash_type);
+ strbuf_release(&new_sig->data);
+ free(new_sig->hash_algo);
+ } else {
+ *stored_sig = *new_sig;
+ }
+}
+
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 signature_data sig_sha1 = { NULL, NULL, STRBUF_INIT };
+ struct signature_data sig_sha256 = { NULL, NULL, STRBUF_INIT };
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;
@@ -2748,13 +2816,23 @@ 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);
+
+ /* Process signatures (up to 2: one "sha1" and one "sha256") */
+ while (skip_prefix(command_buf.buf, "gpgsig ", &v)) {
+ struct signature_data sig = { NULL, NULL, STRBUF_INIT };
+
+ parse_one_signature(&sig, v);
+
+ if (!strcmp(sig.hash_algo, "sha1"))
+ store_signature(&sig_sha1, &sig, "SHA-1");
+ else if (!strcmp(sig.hash_algo, "sha256"))
+ store_signature(&sig_sha256, &sig, "SHA-256");
+ else
+ BUG("parse_one_signature() returned unknown hash algo");
+
read_next_command();
- } else
- strbuf_setlen(&sig, 0);
+ }
+
if (skip_prefix(command_buf.buf, "encoding ", &v)) {
encoding = xstrdup(v);
read_next_command();
@@ -2828,23 +2906,14 @@ 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');
- }
+
+ add_gpgsig_to_commit(&new_data, "gpgsig ", &sig_sha1);
+ add_gpgsig_to_commit(&new_data, "gpgsig-sha256 ", &sig_sha256);
+
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))