log: --show-signature
[gitweb.git] / commit.c
index f00076e91f859d3efcc7cd9f80022c5ef5550f0f..27c7226abbfd95251bc2831a8a6447a8e35f264b 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -877,6 +877,50 @@ static int do_sign_commit(struct strbuf *buf, const char *keyid)
        return 0;
 }
 
+int parse_signed_commit(const unsigned char *sha1,
+                       struct strbuf *payload, struct strbuf *signature)
+{
+       unsigned long size;
+       enum object_type type;
+       char *buffer = read_sha1_file(sha1, &type, &size);
+       int in_signature, saw_signature = -1;
+       char *line, *tail;
+
+       if (!buffer || type != OBJ_COMMIT)
+               goto cleanup;
+
+       line = buffer;
+       tail = buffer + size;
+       in_signature = 0;
+       saw_signature = 0;
+       while (line < tail) {
+               const char *sig = NULL;
+               char *next = memchr(line, '\n', tail - line);
+
+               next = next ? next + 1 : tail;
+               if (in_signature && line[0] == ' ')
+                       sig = line + 1;
+               else if (!prefixcmp(line, gpg_sig_header) &&
+                        line[gpg_sig_header_len] == ' ')
+                       sig = line + gpg_sig_header_len + 1;
+               if (sig) {
+                       strbuf_add(signature, sig, next - sig);
+                       saw_signature = 1;
+                       in_signature = 1;
+               } else {
+                       if (*line == '\n')
+                               /* dump the whole remainder of the buffer */
+                               next = tail;
+                       strbuf_add(payload, line, next - line);
+                       in_signature = 0;
+               }
+               line = next;
+       }
+ cleanup:
+       free(buffer);
+       return saw_signature;
+}
+
 static void handle_signed_tag(struct commit *parent, struct commit_extra_header ***tail)
 {
        struct merge_remote_desc *desc;