@@ -1101,7 +1101,7 @@ static const char *gpg_sig_headers[] = {
"gpgsig-sha256",
};
-static int add_commit_signature(struct strbuf *buf, struct strbuf *sig, const struct git_hash_algo *algo)
+int add_header_signature(struct strbuf *buf, struct strbuf *sig, const struct git_hash_algo *algo)
{
int inspos, copypos;
const char *eoh;
@@ -1732,9 +1732,9 @@ int commit_tree_extended(const char *msg, size_t msg_len,
for (i = 0; i < ARRAY_SIZE(bufs); i++) {
if (!bufs[i].algo)
continue;
- add_commit_signature(&buffer, bufs[i].sig, bufs[i].algo);
+ add_header_signature(&buffer, bufs[i].sig, bufs[i].algo);
if (r->compat_hash_algo)
- add_commit_signature(&compat_buffer, bufs[i].sig, bufs[i].algo);
+ add_header_signature(&compat_buffer, bufs[i].sig, bufs[i].algo);
}
}
@@ -370,5 +370,6 @@ int parse_buffer_signed_by_header(const char *buffer,
struct strbuf *payload,
struct strbuf *signature,
const struct git_hash_algo *algop);
+int add_header_signature(struct strbuf *buf, struct strbuf *sig, const struct git_hash_algo *algo);
#endif /* COMMIT_H */
@@ -7,6 +7,8 @@
#include "hash.h"
#include "object.h"
#include "loose.h"
+#include "commit.h"
+#include "gpg-interface.h"
#include "object-file-convert.h"
int repo_oid_to_algop(struct repository *repo, const struct object_id *src,
@@ -125,6 +127,52 @@ static int convert_commit_object(struct strbuf *out,
return 0;
}
+static int convert_tag_object(struct strbuf *out,
+ const struct git_hash_algo *from,
+ const struct git_hash_algo *to,
+ const char *buffer, size_t size)
+{
+ struct strbuf payload = STRBUF_INIT, temp = STRBUF_INIT, oursig = STRBUF_INIT, othersig = STRBUF_INIT;
+ size_t payload_size;
+ struct object_id oid, mapped_oid;
+ const char *p;
+
+ /* Add some slop for longer signature header in the new algorithm. */
+ strbuf_grow(out, size + 7);
+
+ /* Is there a signature for our algorithm? */
+ payload_size = parse_signed_buffer(buffer, size);
+ strbuf_add(&payload, buffer, payload_size);
+ if (payload_size != size) {
+ /* Yes, there is. */
+ strbuf_add(&oursig, buffer + payload_size, size - payload_size);
+ }
+ /* Now, is there a signature for the other algorithm? */
+ if (parse_buffer_signed_by_header(payload.buf, payload.len, &temp, &othersig, to)) {
+ /* Yes, there is. */
+ strbuf_swap(&payload, &temp);
+ strbuf_release(&temp);
+ }
+
+ /*
+ * Our payload is now in payload and we may have up to two signatrures
+ * in oursig and othersig.
+ */
+ if (strncmp(payload.buf, "object ", 7) || payload.buf[from->hexsz + 7] != '\n')
+ return error("bogus tag object");
+ if (parse_oid_hex_algop(payload.buf + 7, &oid, &p, from) < 0)
+ return error("bad tag object ID");
+ if (repo_oid_to_algop(the_repository, &oid, to, &mapped_oid))
+ return error("unable to map tree %s in tag object",
+ oid_to_hex(&oid));
+ strbuf_addf(out, "object %s\n", oid_to_hex(&mapped_oid));
+ strbuf_add(out, p, payload.len - (p - payload.buf));
+ strbuf_addbuf(out, &othersig);
+ if (oursig.len)
+ add_header_signature(out, &oursig, from);
+ return 0;
+}
+
int convert_object_file(struct strbuf *outbuf,
const struct git_hash_algo *from,
const struct git_hash_algo *to,
@@ -146,6 +194,8 @@ int convert_object_file(struct strbuf *outbuf,
ret = convert_commit_object(outbuf, from, to, buf, len);
break;
case OBJ_TAG:
+ ret = convert_tag_object(outbuf, from, to, buf, len);
+ break;
default:
/* Not implemented yet, so fail. */
ret = -1;