summaryrefslogtreecommitdiff
path: root/src/commit.c
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2016-03-10 10:53:20 +0100
committerCarlos Martín Nieto <cmn@dwim.me>2016-03-15 12:55:03 +0100
commit02d61a3b66a6e5f5bc0154d780daaf5f7b71ccd9 (patch)
tree1dadcb0464c89bf1863a83c826931f93c655e5da /src/commit.c
parent2ba9a0ddacd315dafb54990ff2bfa204e6924016 (diff)
downloadlibgit2-cmn/commit-with-signature.tar.gz
commit: add function to attach a signature to a commitcmn/commit-with-signature
In combination with the function which creates a commit into a buffer, this allows us to more easily create signed commits.
Diffstat (limited to 'src/commit.c')
-rw-r--r--src/commit.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/commit.c b/src/commit.c
index 9d675ac97..f6b2d6517 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -820,3 +820,67 @@ int git_commit_create_buffer(git_buf *out,
git_array_clear(parents_arr);
return error;
}
+
+/**
+ * Append to 'out' properly marking continuations when there's a newline in 'content'
+ */
+static void format_header_field(git_buf *out, const char *field, const char *content)
+{
+ const char *lf;
+
+ assert(out && field && content);
+
+ git_buf_puts(out, field);
+ git_buf_putc(out, ' ');
+
+ while ((lf = strchr(content, '\n')) != NULL) {
+ git_buf_put(out, content, lf - content);
+ git_buf_puts(out, "\n ");
+ content = lf + 1;
+ }
+
+ git_buf_puts(out, content);
+ git_buf_putc(out, '\n');
+}
+
+int git_commit_create_with_signature(
+ git_oid *out,
+ git_repository *repo,
+ const char *commit_content,
+ const char *signature,
+ const char *signature_field)
+{
+ git_odb *odb;
+ int error = 0;
+ const char *field;
+ const char *header_end;
+ git_buf commit = GIT_BUF_INIT;
+
+ /* We start by identifying the end of the commit header */
+ header_end = strstr(commit_content, "\n\n");
+ if (!header_end) {
+ giterr_set(GITERR_INVALID, "malformed commit contents");
+ return -1;
+ }
+
+ field = signature_field ? signature_field : "gpgsig";
+
+ /* The header ends after the first LF */
+ header_end++;
+ git_buf_put(&commit, commit_content, header_end - commit_content);
+ format_header_field(&commit, field, signature);
+ git_buf_puts(&commit, header_end);
+
+ if (git_buf_oom(&commit))
+ return -1;
+
+ if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
+ goto cleanup;
+
+ if ((error = git_odb_write(out, odb, commit.ptr, commit.size, GIT_OBJ_COMMIT)) < 0)
+ goto cleanup;
+
+cleanup:
+ git_buf_free(&commit);
+ return error;
+}