Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 02d61a3

Browse files
committed
commit: add function to attach a signature to a commit
In combination with the function which creates a commit into a buffer, this allows us to more easily create signed commits.
1 parent 2ba9a0d commit 02d61a3

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed

include/git2/commit.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,27 @@ GIT_EXTERN(int) git_commit_create_buffer(
440440
size_t parent_count,
441441
const git_commit *parents[]);
442442

443+
/**
444+
* Create a commit object from the given buffer and signature
445+
*
446+
* Given the unsigned commit object's contents, its signature and the
447+
* header field in which to store the signature, attach the signature
448+
* to the commit and write it into the given repository.
449+
*
450+
* @param out the resulting commit id
451+
* @param commit_content the content of the unsigned commit object
452+
* @param signature the signature to add to the commit
453+
* @param signature_field which header field should contain this
454+
* signature. Leave `NULL` for the default of "gpgsig"
455+
* @return 0 or an error code
456+
*/
457+
GIT_EXTERN(int) git_commit_create_with_signature(
458+
git_oid *out,
459+
git_repository *repo,
460+
const char *commit_content,
461+
const char *signature,
462+
const char *signature_field);
463+
443464
/** @} */
444465
GIT_END_DECL
445466
#endif

src/commit.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,3 +820,67 @@ int git_commit_create_buffer(git_buf *out,
820820
git_array_clear(parents_arr);
821821
return error;
822822
}
823+
824+
/**
825+
* Append to 'out' properly marking continuations when there's a newline in 'content'
826+
*/
827+
static void format_header_field(git_buf *out, const char *field, const char *content)
828+
{
829+
const char *lf;
830+
831+
assert(out && field && content);
832+
833+
git_buf_puts(out, field);
834+
git_buf_putc(out, ' ');
835+
836+
while ((lf = strchr(content, '\n')) != NULL) {
837+
git_buf_put(out, content, lf - content);
838+
git_buf_puts(out, "\n ");
839+
content = lf + 1;
840+
}
841+
842+
git_buf_puts(out, content);
843+
git_buf_putc(out, '\n');
844+
}
845+
846+
int git_commit_create_with_signature(
847+
git_oid *out,
848+
git_repository *repo,
849+
const char *commit_content,
850+
const char *signature,
851+
const char *signature_field)
852+
{
853+
git_odb *odb;
854+
int error = 0;
855+
const char *field;
856+
const char *header_end;
857+
git_buf commit = GIT_BUF_INIT;
858+
859+
/* We start by identifying the end of the commit header */
860+
header_end = strstr(commit_content, "\n\n");
861+
if (!header_end) {
862+
giterr_set(GITERR_INVALID, "malformed commit contents");
863+
return -1;
864+
}
865+
866+
field = signature_field ? signature_field : "gpgsig";
867+
868+
/* The header ends after the first LF */
869+
header_end++;
870+
git_buf_put(&commit, commit_content, header_end - commit_content);
871+
format_header_field(&commit, field, signature);
872+
git_buf_puts(&commit, header_end);
873+
874+
if (git_buf_oom(&commit))
875+
return -1;
876+
877+
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0)
878+
goto cleanup;
879+
880+
if ((error = git_odb_write(out, odb, commit.ptr, commit.size, GIT_OBJ_COMMIT)) < 0)
881+
goto cleanup;
882+
883+
cleanup:
884+
git_buf_free(&commit);
885+
return error;
886+
}

tests/commit/write.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,103 @@ void test_commit_write__can_validate_objects(void)
298298
git_oid_fromstr(&parent_id, tree_id_str);
299299
cl_git_fail(create_commit_from_ids(&commit_id, &tree_id, &parent_id));
300300
}
301+
302+
void test_commit_write__attach_singleline_signature(void)
303+
{
304+
const char *sig = "magic word: pretty please";
305+
306+
const char *data = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\
307+
parent 34734e478d6cf50c27c9d69026d93974d052c454\n\
308+
author Ben Burkert <[email protected]> 1358451456 -0800\n\
309+
committer Ben Burkert <[email protected]> 1358451456 -0800\n\
310+
\n\
311+
a simple commit which works\n";
312+
313+
const char *complete = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\
314+
parent 34734e478d6cf50c27c9d69026d93974d052c454\n\
315+
author Ben Burkert <[email protected]> 1358451456 -0800\n\
316+
committer Ben Burkert <[email protected]> 1358451456 -0800\n\
317+
magicsig magic word: pretty please\n\
318+
\n\
319+
a simple commit which works\n";
320+
321+
git_oid id;
322+
git_odb *odb;
323+
git_odb_object *obj;
324+
325+
cl_git_pass(git_commit_create_with_signature(&id, g_repo, data, sig, "magicsig"));
326+
327+
cl_git_pass(git_repository_odb(&odb, g_repo));
328+
cl_git_pass(git_odb_read(&obj, odb, &id));
329+
cl_assert_equal_s(complete, git_odb_object_data(obj));
330+
331+
git_odb_object_free(obj);
332+
git_odb_free(odb);
333+
}
334+
335+
void test_commit_write__attach_multiline_signature(void)
336+
{
337+
const char *gpgsig = "-----BEGIN PGP SIGNATURE-----\n\
338+
Version: GnuPG v1.4.12 (Darwin)\n\
339+
\n\
340+
iQIcBAABAgAGBQJQ+FMIAAoJEH+LfPdZDSs1e3EQAJMjhqjWF+WkGLHju7pTw2al\n\
341+
o6IoMAhv0Z/LHlWhzBd9e7JeCnanRt12bAU7yvYp9+Z+z+dbwqLwDoFp8LVuigl8\n\
342+
JGLcnwiUW3rSvhjdCp9irdb4+bhKUnKUzSdsR2CK4/hC0N2i/HOvMYX+BRsvqweq\n\
343+
AsAkA6dAWh+gAfedrBUkCTGhlNYoetjdakWqlGL1TiKAefEZrtA1TpPkGn92vbLq\n\
344+
SphFRUY9hVn1ZBWrT3hEpvAIcZag3rTOiRVT1X1flj8B2vGCEr3RrcwOIZikpdaW\n\
345+
who/X3xh/DGbI2RbuxmmJpxxP/8dsVchRJJzBwG+yhwU/iN3MlV2c5D69tls/Dok\n\
346+
6VbyU4lm/ae0y3yR83D9dUlkycOnmmlBAHKIZ9qUts9X7mWJf0+yy2QxJVpjaTGG\n\
347+
cmnQKKPeNIhGJk2ENnnnzjEve7L7YJQF6itbx5VCOcsGh3Ocb3YR7DMdWjt7f8pu\n\
348+
c6j+q1rP7EpE2afUN/geSlp5i3x8aXZPDj67jImbVCE/Q1X9voCtyzGJH7MXR0N9\n\
349+
ZpRF8yzveRfMH8bwAJjSOGAFF5XkcR/RNY95o+J+QcgBLdX48h+ZdNmUf6jqlu3J\n\
350+
7KmTXXQcOVpN6dD3CmRFsbjq+x6RHwa8u1iGn+oIkX908r97ckfB/kHKH7ZdXIJc\n\
351+
cpxtDQQMGYFpXK/71stq\n\
352+
=ozeK\n\
353+
-----END PGP SIGNATURE-----";
354+
355+
const char *data = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\
356+
parent 34734e478d6cf50c27c9d69026d93974d052c454\n\
357+
author Ben Burkert <[email protected]> 1358451456 -0800\n\
358+
committer Ben Burkert <[email protected]> 1358451456 -0800\n\
359+
\n\
360+
a simple commit which works\n";
361+
362+
const char *complete = "tree 6b79e22d69bf46e289df0345a14ca059dfc9bdf6\n\
363+
parent 34734e478d6cf50c27c9d69026d93974d052c454\n\
364+
author Ben Burkert <[email protected]> 1358451456 -0800\n\
365+
committer Ben Burkert <[email protected]> 1358451456 -0800\n\
366+
gpgsig -----BEGIN PGP SIGNATURE-----\n\
367+
Version: GnuPG v1.4.12 (Darwin)\n\
368+
\n\
369+
iQIcBAABAgAGBQJQ+FMIAAoJEH+LfPdZDSs1e3EQAJMjhqjWF+WkGLHju7pTw2al\n\
370+
o6IoMAhv0Z/LHlWhzBd9e7JeCnanRt12bAU7yvYp9+Z+z+dbwqLwDoFp8LVuigl8\n\
371+
JGLcnwiUW3rSvhjdCp9irdb4+bhKUnKUzSdsR2CK4/hC0N2i/HOvMYX+BRsvqweq\n\
372+
AsAkA6dAWh+gAfedrBUkCTGhlNYoetjdakWqlGL1TiKAefEZrtA1TpPkGn92vbLq\n\
373+
SphFRUY9hVn1ZBWrT3hEpvAIcZag3rTOiRVT1X1flj8B2vGCEr3RrcwOIZikpdaW\n\
374+
who/X3xh/DGbI2RbuxmmJpxxP/8dsVchRJJzBwG+yhwU/iN3MlV2c5D69tls/Dok\n\
375+
6VbyU4lm/ae0y3yR83D9dUlkycOnmmlBAHKIZ9qUts9X7mWJf0+yy2QxJVpjaTGG\n\
376+
cmnQKKPeNIhGJk2ENnnnzjEve7L7YJQF6itbx5VCOcsGh3Ocb3YR7DMdWjt7f8pu\n\
377+
c6j+q1rP7EpE2afUN/geSlp5i3x8aXZPDj67jImbVCE/Q1X9voCtyzGJH7MXR0N9\n\
378+
ZpRF8yzveRfMH8bwAJjSOGAFF5XkcR/RNY95o+J+QcgBLdX48h+ZdNmUf6jqlu3J\n\
379+
7KmTXXQcOVpN6dD3CmRFsbjq+x6RHwa8u1iGn+oIkX908r97ckfB/kHKH7ZdXIJc\n\
380+
cpxtDQQMGYFpXK/71stq\n\
381+
=ozeK\n\
382+
-----END PGP SIGNATURE-----\n\
383+
\n\
384+
a simple commit which works\n";
385+
386+
git_oid one, two;
387+
git_odb *odb;
388+
git_odb_object *obj;
389+
390+
cl_git_pass(git_commit_create_with_signature(&one, g_repo, data, gpgsig, "gpgsig"));
391+
cl_git_pass(git_commit_create_with_signature(&two, g_repo, data, gpgsig, NULL));
392+
393+
cl_assert(!git_oid_cmp(&one, &two));
394+
cl_git_pass(git_repository_odb(&odb, g_repo));
395+
cl_git_pass(git_odb_read(&obj, odb, &one));
396+
cl_assert_equal_s(complete, git_odb_object_data(obj));
397+
398+
git_odb_object_free(obj);
399+
git_odb_free(odb);
400+
}

0 commit comments

Comments
 (0)