Commit ba349322 by Edward Thomson

Merge pull request #3673 from libgit2/cmn/commit-with-signature

commit: add function to attach a signature to a commit
parents a151eb54 02d61a3b
......@@ -440,6 +440,27 @@ GIT_EXTERN(int) git_commit_create_buffer(
size_t parent_count,
const git_commit *parents[]);
/**
* Create a commit object from the given buffer and signature
*
* Given the unsigned commit object's contents, its signature and the
* header field in which to store the signature, attach the signature
* to the commit and write it into the given repository.
*
* @param out the resulting commit id
* @param commit_content the content of the unsigned commit object
* @param signature the signature to add to the commit
* @param signature_field which header field should contain this
* signature. Leave `NULL` for the default of "gpgsig"
* @return 0 or an error code
*/
GIT_EXTERN(int) git_commit_create_with_signature(
git_oid *out,
git_repository *repo,
const char *commit_content,
const char *signature,
const char *signature_field);
/** @} */
GIT_END_DECL
#endif
......@@ -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;
}
......@@ -298,3 +298,103 @@ void test_commit_write__can_validate_objects(void)
git_oid_fromstr(&parent_id, tree_id_str);
cl_git_fail(create_commit_from_ids(&commit_id, &tree_id, &parent_id));
}
void test_commit_write__attach_singleline_signature(void)
{
const char *sig = "magic word: pretty please";
const char *data = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\
parent 34734e478d6cf50c27c9d69026d93974d052c454\n\
author Ben Burkert <ben@benburkert.com> 1358451456 -0800\n\
committer Ben Burkert <ben@benburkert.com> 1358451456 -0800\n\
\n\
a simple commit which works\n";
const char *complete = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\
parent 34734e478d6cf50c27c9d69026d93974d052c454\n\
author Ben Burkert <ben@benburkert.com> 1358451456 -0800\n\
committer Ben Burkert <ben@benburkert.com> 1358451456 -0800\n\
magicsig magic word: pretty please\n\
\n\
a simple commit which works\n";
git_oid id;
git_odb *odb;
git_odb_object *obj;
cl_git_pass(git_commit_create_with_signature(&id, g_repo, data, sig, "magicsig"));
cl_git_pass(git_repository_odb(&odb, g_repo));
cl_git_pass(git_odb_read(&obj, odb, &id));
cl_assert_equal_s(complete, git_odb_object_data(obj));
git_odb_object_free(obj);
git_odb_free(odb);
}
void test_commit_write__attach_multiline_signature(void)
{
const char *gpgsig = "-----BEGIN PGP SIGNATURE-----\n\
Version: GnuPG v1.4.12 (Darwin)\n\
\n\
iQIcBAABAgAGBQJQ+FMIAAoJEH+LfPdZDSs1e3EQAJMjhqjWF+WkGLHju7pTw2al\n\
o6IoMAhv0Z/LHlWhzBd9e7JeCnanRt12bAU7yvYp9+Z+z+dbwqLwDoFp8LVuigl8\n\
JGLcnwiUW3rSvhjdCp9irdb4+bhKUnKUzSdsR2CK4/hC0N2i/HOvMYX+BRsvqweq\n\
AsAkA6dAWh+gAfedrBUkCTGhlNYoetjdakWqlGL1TiKAefEZrtA1TpPkGn92vbLq\n\
SphFRUY9hVn1ZBWrT3hEpvAIcZag3rTOiRVT1X1flj8B2vGCEr3RrcwOIZikpdaW\n\
who/X3xh/DGbI2RbuxmmJpxxP/8dsVchRJJzBwG+yhwU/iN3MlV2c5D69tls/Dok\n\
6VbyU4lm/ae0y3yR83D9dUlkycOnmmlBAHKIZ9qUts9X7mWJf0+yy2QxJVpjaTGG\n\
cmnQKKPeNIhGJk2ENnnnzjEve7L7YJQF6itbx5VCOcsGh3Ocb3YR7DMdWjt7f8pu\n\
c6j+q1rP7EpE2afUN/geSlp5i3x8aXZPDj67jImbVCE/Q1X9voCtyzGJH7MXR0N9\n\
ZpRF8yzveRfMH8bwAJjSOGAFF5XkcR/RNY95o+J+QcgBLdX48h+ZdNmUf6jqlu3J\n\
7KmTXXQcOVpN6dD3CmRFsbjq+x6RHwa8u1iGn+oIkX908r97ckfB/kHKH7ZdXIJc\n\
cpxtDQQMGYFpXK/71stq\n\
=ozeK\n\
-----END PGP SIGNATURE-----";
const char *data = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\
parent 34734e478d6cf50c27c9d69026d93974d052c454\n\
author Ben Burkert <ben@benburkert.com> 1358451456 -0800\n\
committer Ben Burkert <ben@benburkert.com> 1358451456 -0800\n\
\n\
a simple commit which works\n";
const char *complete = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\
parent 34734e478d6cf50c27c9d69026d93974d052c454\n\
author Ben Burkert <ben@benburkert.com> 1358451456 -0800\n\
committer Ben Burkert <ben@benburkert.com> 1358451456 -0800\n\
gpgsig -----BEGIN PGP SIGNATURE-----\n\
Version: GnuPG v1.4.12 (Darwin)\n\
\n\
iQIcBAABAgAGBQJQ+FMIAAoJEH+LfPdZDSs1e3EQAJMjhqjWF+WkGLHju7pTw2al\n\
o6IoMAhv0Z/LHlWhzBd9e7JeCnanRt12bAU7yvYp9+Z+z+dbwqLwDoFp8LVuigl8\n\
JGLcnwiUW3rSvhjdCp9irdb4+bhKUnKUzSdsR2CK4/hC0N2i/HOvMYX+BRsvqweq\n\
AsAkA6dAWh+gAfedrBUkCTGhlNYoetjdakWqlGL1TiKAefEZrtA1TpPkGn92vbLq\n\
SphFRUY9hVn1ZBWrT3hEpvAIcZag3rTOiRVT1X1flj8B2vGCEr3RrcwOIZikpdaW\n\
who/X3xh/DGbI2RbuxmmJpxxP/8dsVchRJJzBwG+yhwU/iN3MlV2c5D69tls/Dok\n\
6VbyU4lm/ae0y3yR83D9dUlkycOnmmlBAHKIZ9qUts9X7mWJf0+yy2QxJVpjaTGG\n\
cmnQKKPeNIhGJk2ENnnnzjEve7L7YJQF6itbx5VCOcsGh3Ocb3YR7DMdWjt7f8pu\n\
c6j+q1rP7EpE2afUN/geSlp5i3x8aXZPDj67jImbVCE/Q1X9voCtyzGJH7MXR0N9\n\
ZpRF8yzveRfMH8bwAJjSOGAFF5XkcR/RNY95o+J+QcgBLdX48h+ZdNmUf6jqlu3J\n\
7KmTXXQcOVpN6dD3CmRFsbjq+x6RHwa8u1iGn+oIkX908r97ckfB/kHKH7ZdXIJc\n\
cpxtDQQMGYFpXK/71stq\n\
=ozeK\n\
-----END PGP SIGNATURE-----\n\
\n\
a simple commit which works\n";
git_oid one, two;
git_odb *odb;
git_odb_object *obj;
cl_git_pass(git_commit_create_with_signature(&one, g_repo, data, gpgsig, "gpgsig"));
cl_git_pass(git_commit_create_with_signature(&two, g_repo, data, gpgsig, NULL));
cl_assert(!git_oid_cmp(&one, &two));
cl_git_pass(git_repository_odb(&odb, g_repo));
cl_git_pass(git_odb_read(&obj, odb, &one));
cl_assert_equal_s(complete, git_odb_object_data(obj));
git_odb_object_free(obj);
git_odb_free(odb);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment