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
This commit is contained in:
Junio C Hamano
2012-01-06 12:44:07 -08:00
16 changed files with 488 additions and 34 deletions

118
commit.c
View File

@ -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;