mirror of
https://github.com/libgit2/libgit2.git
synced 2026-06-21 22:16:24 +00:00
commit: introduce a signing callback
Callers can now introduce a commit signing callback instead of needing to call a specialized commit buffer creation function.
This commit is contained in:
@@ -294,7 +294,8 @@ GIT_EXTERN(int) git_commit_nth_gen_ancestor(
|
||||
* @return 0 on succeess, GIT_ENOTFOUND if the field does not exist,
|
||||
* or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_commit_header_field(git_buf *out, const git_commit *commit, const char *field);
|
||||
GIT_EXTERN(int) git_commit_header_field(
|
||||
git_buf *out, const git_commit *commit, const char *field);
|
||||
|
||||
/**
|
||||
* Extract the signature from a commit
|
||||
@@ -369,6 +370,42 @@ typedef struct {
|
||||
const char *value;
|
||||
} git_commit_header;
|
||||
|
||||
/** An accessor object for setting commit signature data. */
|
||||
typedef struct git_commitbuilder git_commitbuilder;
|
||||
|
||||
/**
|
||||
* Add a header on a commit being created.
|
||||
*
|
||||
* @param builder in-progress commitbuilder object
|
||||
* @param field the header field to add
|
||||
* @param value the header value to add
|
||||
* @return 0 on success or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_commitbuilder_add_header(
|
||||
git_commitbuilder *builder,
|
||||
const char *field,
|
||||
const char *value);
|
||||
|
||||
/**
|
||||
* Commit signing callback: used when a function is going to write
|
||||
* a commit (for example, in `git_commit_create_ext`) to allow callers
|
||||
* to sign the commit.
|
||||
*
|
||||
* @param builder commit builder object to populate with the signature
|
||||
* @param repo the repository being committed in
|
||||
* @param commit_content the raw contents of the commit (to be signed)
|
||||
* @param payload the caller-specified callback payload
|
||||
* @return 0 if this callback has created a signature and populated the
|
||||
* field and signature buffers, `GIT_PASSTHROUGH` if the callback
|
||||
* does not want to sign the commit, any other value to stop and
|
||||
* return a failure
|
||||
*/
|
||||
typedef int GIT_CALLBACK(git_commit_signature_cb)(
|
||||
git_commitbuilder *builder,
|
||||
git_repository *repo,
|
||||
const char *commit_content,
|
||||
void *payload);
|
||||
|
||||
typedef struct {
|
||||
unsigned int version;
|
||||
|
||||
@@ -392,6 +429,12 @@ typedef struct {
|
||||
*/
|
||||
const git_commit_header *extra_headers;
|
||||
size_t extra_headers_len; /**< Number of extra headers */
|
||||
|
||||
/** Signing callback; leave NULL for no commit signing. */
|
||||
git_commit_signature_cb sign;
|
||||
|
||||
/** Callback payload (optional) */
|
||||
void *payload;
|
||||
} git_commit_create_ext_options;
|
||||
|
||||
/** Current version for the `git_commit_create_ext_options` structure */
|
||||
|
||||
@@ -161,6 +161,10 @@ on_error:
|
||||
return error;
|
||||
}
|
||||
|
||||
struct git_commitbuilder {
|
||||
git_str *contents;
|
||||
};
|
||||
|
||||
static int git_commit__create_internal(
|
||||
git_oid *id,
|
||||
git_repository *repo,
|
||||
@@ -173,12 +177,12 @@ static int git_commit__create_internal(
|
||||
const git_commit_create_ext_options *opts,
|
||||
bool validate)
|
||||
{
|
||||
int error;
|
||||
git_odb *odb;
|
||||
git_reference *ref = NULL;
|
||||
git_str buf = GIT_STR_INIT;
|
||||
const git_oid *current_id = NULL;
|
||||
git_array_oid_t parents = GIT_ARRAY_INIT;
|
||||
int error = 0;
|
||||
|
||||
if (opts && opts->update_ref) {
|
||||
error = git_reference_lookup_resolved(&ref,
|
||||
@@ -187,27 +191,31 @@ static int git_commit__create_internal(
|
||||
if (error < 0 && error != GIT_ENOTFOUND)
|
||||
return error;
|
||||
}
|
||||
|
||||
git_error_clear();
|
||||
|
||||
if (ref)
|
||||
current_id = git_reference_target(ref);
|
||||
|
||||
if ((error = validate_tree_and_parents(&parents, repo, tree, parent_cb, parent_payload, current_id, validate)) < 0)
|
||||
if ((error = validate_tree_and_parents(&parents, repo, tree,
|
||||
parent_cb, parent_payload, current_id, validate)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
error = git_commit__create_buffer_internal(&buf,
|
||||
author, committer, message, tree, &parents, opts);
|
||||
|
||||
if (error < 0)
|
||||
if ((error = git_commit__create_buffer_internal(&buf,
|
||||
author, committer, message, tree, &parents, opts)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (git_repository_odb__weakptr(&odb, repo) < 0)
|
||||
goto cleanup;
|
||||
if (opts && opts->sign) {
|
||||
git_commitbuilder builder = { &buf };
|
||||
|
||||
if (git_odb__freshen(odb, tree) < 0)
|
||||
goto cleanup;
|
||||
if ((error = opts->sign(&builder, repo, buf.ptr,
|
||||
opts->payload)) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (git_odb_write(id, odb, buf.ptr, buf.size, GIT_OBJECT_COMMIT) < 0)
|
||||
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 ||
|
||||
(error = git_odb__freshen(odb, tree)) < 0 ||
|
||||
(error = git_odb_write(id, odb, buf.ptr, buf.size, GIT_OBJECT_COMMIT)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
|
||||
@@ -367,6 +375,57 @@ int git_commit_create_ext(
|
||||
commit_parent_from_array, &data, opts, false);
|
||||
}
|
||||
|
||||
static int append_header(
|
||||
git_str *out,
|
||||
const char *raw_content,
|
||||
const char *name,
|
||||
const char *value)
|
||||
{
|
||||
const char *header_end;
|
||||
|
||||
/* Identifying the end of the commit header area */
|
||||
header_end = strstr(raw_content, "\n\n");
|
||||
|
||||
if (!header_end) {
|
||||
git_error_set(GIT_ERROR_INVALID, "malformed commit contents");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The header ends after the first LF */
|
||||
header_end++;
|
||||
|
||||
git_str_put(out, raw_content, header_end - raw_content);
|
||||
|
||||
if (format_header_field(out, name, value) < 0)
|
||||
return -1;
|
||||
|
||||
git_str_puts(out, header_end);
|
||||
|
||||
if (git_str_oom(out))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_commitbuilder_add_header(
|
||||
git_commitbuilder *builder,
|
||||
const char *field,
|
||||
const char *value)
|
||||
{
|
||||
git_str signed_data = GIT_BUF_INIT;
|
||||
int error;
|
||||
|
||||
if ((error = append_header(&signed_data, builder->contents->ptr,
|
||||
field, value)) < 0)
|
||||
goto done;
|
||||
|
||||
git_str_swap(builder->contents, &signed_data);
|
||||
|
||||
done:
|
||||
git_str_dispose(&signed_data);
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_commit_create(
|
||||
git_oid *id,
|
||||
git_repository *repo,
|
||||
@@ -1079,20 +1138,29 @@ int git_commit_create_with_signature(
|
||||
const char *signature_field)
|
||||
{
|
||||
git_odb *odb;
|
||||
int error = 0;
|
||||
const char *field;
|
||||
const char *header_end;
|
||||
git_str commit = GIT_STR_INIT;
|
||||
git_str signed_content = GIT_STR_INIT;
|
||||
git_commit *parsed;
|
||||
git_array_oid_t parents = GIT_ARRAY_INIT;
|
||||
git_commit__parse_options parse_opts = {0};
|
||||
size_t commit_content_len;
|
||||
int error = 0;
|
||||
|
||||
GIT_ASSERT_ARG(out);
|
||||
GIT_ASSERT_ARG(repo);
|
||||
GIT_ASSERT_ARG(commit_content);
|
||||
|
||||
if (!signature_field)
|
||||
signature_field = "gpgsig";
|
||||
|
||||
commit_content_len = strlen(commit_content);;
|
||||
|
||||
parse_opts.oid_type = repo->oid_type;
|
||||
|
||||
/* The first step is to verify that all the tree and parents exist */
|
||||
parsed = git__calloc(1, sizeof(git_commit));
|
||||
GIT_ERROR_CHECK_ALLOC(parsed);
|
||||
if (commit_parse(parsed, commit_content, strlen(commit_content), &parse_opts) < 0) {
|
||||
|
||||
if (commit_parse(parsed, commit_content, commit_content_len, &parse_opts) < 0) {
|
||||
error = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -1102,39 +1170,25 @@ int git_commit_create_with_signature(
|
||||
|
||||
git_array_clear(parents);
|
||||
|
||||
/* Then we start appending by identifying the end of the commit header */
|
||||
header_end = strstr(commit_content, "\n\n");
|
||||
if (!header_end) {
|
||||
git_error_set(GIT_ERROR_INVALID, "malformed commit contents");
|
||||
error = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* The header ends after the first LF */
|
||||
header_end++;
|
||||
git_str_put(&commit, commit_content, header_end - commit_content);
|
||||
|
||||
if (signature != NULL) {
|
||||
field = signature_field ? signature_field : "gpgsig";
|
||||
|
||||
if ((error = format_header_field(&commit, field, signature)) < 0)
|
||||
if (signature) {
|
||||
if ((error = append_header(&signed_content,
|
||||
commit_content, signature_field, signature)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
commit_content = signed_content.ptr;
|
||||
commit_content_len = signed_content.size;
|
||||
}
|
||||
|
||||
git_str_puts(&commit, header_end);
|
||||
|
||||
if (git_str_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_OBJECT_COMMIT)) < 0)
|
||||
if ((error = git_odb_write(out, odb, commit_content,
|
||||
commit_content_len, GIT_OBJECT_COMMIT)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
cleanup:
|
||||
git_commit__free(parsed);
|
||||
git_str_dispose(&commit);
|
||||
git_str_dispose(&signed_content);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@@ -299,130 +299,6 @@ void test_commit_write__can_validate_objects(void)
|
||||
cl_git_fail(create_commit_from_ids(&commit_id, &tree_id, &parent_id));
|
||||
}
|
||||
|
||||
void test_commit_write__attach_signature_checks_objects(void)
|
||||
{
|
||||
const char *sig = "magic word: pretty please";
|
||||
const char *badtree = "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 does not work\n";
|
||||
|
||||
const char *badparent = "tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\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 does not work\n";
|
||||
|
||||
git_oid id;
|
||||
|
||||
cl_git_fail_with(-1, git_commit_create_with_signature(&id, g_repo, badtree, sig, "magicsig"));
|
||||
cl_git_fail_with(-1, git_commit_create_with_signature(&id, g_repo, badparent, sig, "magicsig"));
|
||||
|
||||
}
|
||||
|
||||
void test_commit_write__attach_singleline_signature(void)
|
||||
{
|
||||
const char *sig = "magic word: pretty please";
|
||||
|
||||
const char *data = "tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n\
|
||||
parent 8496071c1b46c854b31185ea97743be6a8774479\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 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n\
|
||||
parent 8496071c1b46c854b31185ea97743be6a8774479\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 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n\
|
||||
parent 8496071c1b46c854b31185ea97743be6a8774479\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 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n\
|
||||
parent 8496071c1b46c854b31185ea97743be6a8774479\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);
|
||||
}
|
||||
|
||||
void test_commit_write__can_add_extra_headers(void)
|
||||
{
|
||||
git_odb *odb;
|
||||
@@ -479,3 +355,169 @@ This is a fun new commit.";
|
||||
git_signature_free(author);
|
||||
git_odb_free(odb);
|
||||
}
|
||||
|
||||
static const char *unsigned_data =
|
||||
"tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n\
|
||||
parent 8496071c1b46c854b31185ea97743be6a8774479\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";
|
||||
|
||||
static 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-----";
|
||||
|
||||
static const char *signed_data =
|
||||
"tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n\
|
||||
parent 8496071c1b46c854b31185ea97743be6a8774479\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";
|
||||
|
||||
void test_commit_write__attach_signature_checks_objects(void)
|
||||
{
|
||||
const char *sig = "magic word: pretty please";
|
||||
const char *badtree = "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 does not work\n";
|
||||
|
||||
const char *badparent = "tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\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 does not work\n";
|
||||
|
||||
git_oid id;
|
||||
|
||||
cl_git_fail_with(-1, git_commit_create_with_signature(&id, g_repo, badtree, sig, "magicsig"));
|
||||
cl_git_fail_with(-1, git_commit_create_with_signature(&id, g_repo, badparent, sig, "magicsig"));
|
||||
|
||||
}
|
||||
|
||||
void test_commit_write__attach_singleline_signature(void)
|
||||
{
|
||||
const char *sig = "magic word: pretty please";
|
||||
|
||||
const char *complete = "tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904\n\
|
||||
parent 8496071c1b46c854b31185ea97743be6a8774479\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, unsigned_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)
|
||||
{
|
||||
git_oid one, two;
|
||||
git_odb *odb;
|
||||
git_odb_object *obj;
|
||||
|
||||
cl_git_pass(git_commit_create_with_signature(&one, g_repo, unsigned_data, gpgsig, "gpgsig"));
|
||||
cl_git_pass(git_commit_create_with_signature(&two, g_repo, unsigned_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(signed_data, git_odb_object_data(obj));
|
||||
|
||||
git_odb_object_free(obj);
|
||||
git_odb_free(odb);
|
||||
}
|
||||
|
||||
static int sign_cb(
|
||||
git_commitbuilder *builder, git_repository *repo,
|
||||
const char *commit_buffer, void *payload)
|
||||
{
|
||||
GIT_UNUSED(repo);
|
||||
GIT_UNUSED(commit_buffer);
|
||||
GIT_UNUSED(payload);
|
||||
|
||||
return git_commitbuilder_add_header(builder,
|
||||
"gpgsig", gpgsig);
|
||||
}
|
||||
|
||||
void test_commit_write__signature_callback(void)
|
||||
{
|
||||
git_oid result_id, tree_id, parent_id;
|
||||
git_odb *odb;
|
||||
git_odb_object *obj;
|
||||
git_signature *committer;
|
||||
git_tree *tree;
|
||||
git_commit *parent;
|
||||
git_commit_create_ext_options opts = GIT_COMMIT_CREATE_EXT_OPTIONS_INIT;
|
||||
|
||||
cl_git_pass(git_oid_from_string(&tree_id, "4b825dc642cb6eb9a060e54bf8d69288fbee4904", GIT_OID_SHA1));
|
||||
cl_git_pass(git_oid_from_string(&parent_id, "8496071c1b46c854b31185ea97743be6a8774479", GIT_OID_SHA1));
|
||||
|
||||
cl_git_pass(git_tree_lookup(&tree, g_repo, &tree_id));
|
||||
cl_git_pass(git_commit_lookup(&parent, g_repo, &parent_id));
|
||||
cl_git_pass(git_signature_new(&committer, "Ben Burkert", "ben@benburkert.com", 1358451456, -480));
|
||||
|
||||
opts.sign = sign_cb;
|
||||
|
||||
cl_git_pass(git_commit_create_ext(&result_id, g_repo, committer,
|
||||
committer, "a simple commit which works\n", tree,
|
||||
1, &parent, &opts));
|
||||
|
||||
cl_git_pass(git_repository_odb(&odb, g_repo));
|
||||
cl_git_pass(git_odb_read(&obj, odb, &result_id));
|
||||
cl_assert_equal_s(signed_data, git_odb_object_data(obj));
|
||||
|
||||
git_tree_free(tree);
|
||||
git_commit_free(parent);
|
||||
git_signature_free(committer);
|
||||
git_odb_object_free(obj);
|
||||
git_odb_free(odb);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user