summaryrefslogtreecommitdiff
path: root/commit.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2012-01-06 20:44:07 (GMT)
committerJunio C Hamano <gitster@pobox.com>2012-01-06 20:44:07 (GMT)
commit5de89d3abfca98b0dfd0280d28576940c913d60d (patch)
treece339497e72abc84f4a1bbc9b270b07ab46dbc0c /commit.c
parent4a3a1edd0be1c5254ae4fc66e06297d87ef7d530 (diff)
parentd041ffa55a69cb6cdc3b160dc181c7e59b3bd4bb (diff)
downloadgit-5de89d3abfca98b0dfd0280d28576940c913d60d.zip
git-5de89d3abfca98b0dfd0280d28576940c913d60d.tar.gz
git-5de89d3abfca98b0dfd0280d28576940c913d60d.tar.bz2
Merge branch 'jc/show-sig'
* jc/show-sig: log --show-signature: reword the common two-head merge case log-tree: show mergetag in log --show-signature output log-tree.c: small refactor in show_signature() commit --amend -S: strip existing gpgsig headers verify_signed_buffer: fix stale comment gpg-interface: allow use of a custom GPG binary pretty: %G[?GS] placeholders test "commit -S" and "log --show-signature" log: --show-signature commit: teach --gpg-sign option Conflicts: builtin/commit-tree.c builtin/commit.c builtin/merge.c notes-cache.c pretty.c
Diffstat (limited to 'commit.c')
-rw-r--r--commit.c118
1 files changed, 111 insertions, 7 deletions
diff --git a/commit.c b/commit.c
index 44bc96d..35af498 100644
--- a/commit.c
+++ b/commit.c
@@ -6,6 +6,7 @@
#include "diff.h"
#include "revision.h"
#include "notes.h"
+#include "gpg-interface.h"
int save_commit_buffer = 1;
@@ -840,6 +841,86 @@ struct commit_list *reduce_heads(struct commit_list *heads)
return result;
}
+static const char gpg_sig_header[] = "gpgsig";
+static const int gpg_sig_header_len = sizeof(gpg_sig_header) - 1;
+
+static int do_sign_commit(struct strbuf *buf, const char *keyid)
+{
+ struct strbuf sig = STRBUF_INIT;
+ int inspos, copypos;
+
+ /* find the end of the header */
+ inspos = strstr(buf->buf, "\n\n") - buf->buf + 1;
+
+ if (!keyid || !*keyid)
+ keyid = get_signing_key();
+ if (sign_buffer(buf, &sig, keyid)) {
+ strbuf_release(&sig);
+ return -1;
+ }
+
+ for (copypos = 0; sig.buf[copypos]; ) {
+ const char *bol = sig.buf + copypos;
+ const char *eol = strchrnul(bol, '\n');
+ int len = (eol - bol) + !!*eol;
+
+ if (!copypos) {
+ strbuf_insert(buf, inspos, gpg_sig_header, gpg_sig_header_len);
+ inspos += gpg_sig_header_len;
+ }
+ strbuf_insert(buf, inspos++, " ", 1);
+ strbuf_insert(buf, inspos, bol, len);
+ inspos += len;
+ copypos += len;
+ }
+ strbuf_release(&sig);
+ 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;
@@ -900,14 +981,15 @@ static void add_extra_header(struct strbuf *buffer,
strbuf_addch(buffer, '\n');
}
-struct commit_extra_header *read_commit_extra_headers(struct commit *commit)
+struct commit_extra_header *read_commit_extra_headers(struct commit *commit,
+ const char **exclude)
{
struct commit_extra_header *extra = NULL;
unsigned long size;
enum object_type type;
char *buffer = read_sha1_file(commit->object.sha1, &type, &size);
if (buffer && type == OBJ_COMMIT)
- extra = read_commit_extra_header_lines(buffer, size);
+ extra = read_commit_extra_header_lines(buffer, size, exclude);
free(buffer);
return extra;
}
@@ -921,7 +1003,23 @@ static inline int standard_header_field(const char *field, size_t len)
(len == 8 && !memcmp(field, "encoding ", 9)));
}
-struct commit_extra_header *read_commit_extra_header_lines(const char *buffer, size_t size)
+static int excluded_header_field(const char *field, size_t len, const char **exclude)
+{
+ if (!exclude)
+ return 0;
+
+ while (*exclude) {
+ size_t xlen = strlen(*exclude);
+ if (len == xlen &&
+ !memcmp(field, *exclude, xlen) && field[xlen] == ' ')
+ return 1;
+ exclude++;
+ }
+ return 0;
+}
+
+struct commit_extra_header *read_commit_extra_header_lines(const char *buffer, size_t size,
+ const char **exclude)
{
struct commit_extra_header *extra = NULL, **tail = &extra, *it = NULL;
const char *line, *next, *eof, *eob;
@@ -947,7 +1045,8 @@ struct commit_extra_header *read_commit_extra_header_lines(const char *buffer, s
if (next <= eof)
eof = next;
- if (standard_header_field(line, eof - line))
+ if (standard_header_field(line, eof - line) ||
+ excluded_header_field(line, eof - line, exclude))
continue;
it = xcalloc(1, sizeof(*it));
@@ -975,13 +1074,14 @@ void free_commit_extra_headers(struct commit_extra_header *extra)
int commit_tree(const struct strbuf *msg, unsigned char *tree,
struct commit_list *parents, unsigned char *ret,
- const char *author)
+ const char *author, const char *sign_commit)
{
struct commit_extra_header *extra = NULL, **tail = &extra;
int result;
append_merge_tag_headers(parents, &tail);
- result = commit_tree_extended(msg, tree, parents, ret, author, extra);
+ result = commit_tree_extended(msg, tree, parents, ret,
+ author, sign_commit, extra);
free_commit_extra_headers(extra);
return result;
}
@@ -993,7 +1093,8 @@ static const char commit_utf8_warn[] =
int commit_tree_extended(const struct strbuf *msg, unsigned char *tree,
struct commit_list *parents, unsigned char *ret,
- const char *author, struct commit_extra_header *extra)
+ const char *author, const char *sign_commit,
+ struct commit_extra_header *extra)
{
int result;
int encoding_is_utf8;
@@ -1046,6 +1147,9 @@ int commit_tree_extended(const struct strbuf *msg, unsigned char *tree,
if (encoding_is_utf8 && !is_utf8(buffer.buf))
fprintf(stderr, commit_utf8_warn);
+ if (sign_commit && do_sign_commit(&buffer, sign_commit))
+ return -1;
+
result = write_sha1_file(buffer.buf, buffer.len, commit_type, ret);
strbuf_release(&buffer);
return result;