mirror of
https://github.com/git/git.git
synced 2026-01-16 21:59:45 +00:00
Merge branch 'jc/signed-commit' into next
* jc/signed-commit: 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:
92
commit.c
92
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;
|
||||
@@ -975,13 +1056,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 +1075,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 +1129,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;
|
||||
|
||||
Reference in New Issue
Block a user