Skip to content

Commit 258115d

Browse files
authored
Merge pull request libgit2#6016 from libgit2/ethomson/commit_create_cb
Introduce `create_commit_cb`, deprecate `signing_cb`
2 parents 16a2e66 + ef03e15 commit 258115d

File tree

5 files changed

+402
-59
lines changed

5 files changed

+402
-59
lines changed

include/git2/commit.h

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -503,25 +503,41 @@ GIT_EXTERN(int) git_commit_create_with_signature(
503503
GIT_EXTERN(int) git_commit_dup(git_commit **out, git_commit *source);
504504

505505
/**
506-
* Commit signing callback.
507-
*
508-
* The callback will be called with the commit content, giving a user an
509-
* opportunity to sign the commit content. The signature_field
510-
* buf may be left empty to specify the default field "gpgsig".
511-
*
512-
* Signatures can take the form of any string, and can be created on an arbitrary
513-
* header field. Signatures are most commonly used for verifying authorship of a
514-
* commit using GPG or a similar cryptographically secure signing algorithm.
515-
* See https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work for more
516-
* details.
517-
*
518-
* When the callback:
519-
* - returns GIT_PASSTHROUGH, no signature will be added to the commit.
520-
* - returns < 0, commit creation will be aborted.
521-
* - returns GIT_OK, the signature parameter is expected to be filled.
522-
*/
523-
typedef int (*git_commit_signing_cb)(
524-
git_buf *signature, git_buf *signature_field, const char *commit_content, void *payload);
506+
* Commit creation callback: used when a function is going to create
507+
* commits (for example, in `git_rebase_commit`) to allow callers to
508+
* override the commit creation behavior. For example, users may
509+
* wish to sign commits by providing this information to
510+
* `git_commit_create_buffer`, signing that buffer, then calling
511+
* `git_commit_create_with_signature`. The resultant commit id
512+
* should be set in the `out` object id parameter.
513+
*
514+
* @param out pointer that this callback will populate with the object
515+
* id of the commit that is created
516+
* @param author the author name and time of the commit
517+
* @param committer the committer name and time of the commit
518+
* @param message_encoding the encoding of the given message, or NULL
519+
* to assume UTF8
520+
* @param message the commit message
521+
* @param tree the tree to be committed
522+
* @param parent_count the number of parents for this commit
523+
* @param parents the commit parents
524+
* @param payload the payload pointer in the rebase options
525+
* @return 0 if this callback has created the commit and populated the out
526+
* parameter, GIT_PASSTHROUGH if the callback has not created a
527+
* commit and wants the calling function to create the commit as
528+
* if no callback had been specified, any other value to stop
529+
* and return a failure
530+
*/
531+
typedef int (*git_commit_create_cb)(
532+
git_oid *out,
533+
const git_signature *author,
534+
const git_signature *committer,
535+
const char *message_encoding,
536+
const char *message,
537+
const git_tree *tree,
538+
size_t parent_count,
539+
const git_commit *parents[],
540+
void *payload);
525541

526542
/** @} */
527543
GIT_END_DECL

include/git2/deprecated.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,27 @@ GIT_EXTERN(void) git_buf_free(git_buf *buffer);
205205

206206
/**@}*/
207207

208+
/** @name Deprecated Commit Definitions
209+
*/
210+
/**@{*/
211+
212+
/**
213+
* Provide a commit signature during commit creation.
214+
*
215+
* Callers should instead define a `git_commit_create_cb` that
216+
* generates a commit buffer using `git_commit_create_buffer`, sign
217+
* that buffer and call `git_commit_create_with_signature`.
218+
*
219+
* @deprecated use a `git_commit_create_cb` instead
220+
*/
221+
typedef int (*git_commit_signing_cb)(
222+
git_buf *signature,
223+
git_buf *signature_field,
224+
const char *commit_content,
225+
void *payload);
226+
227+
/**@}*/
228+
208229
/** @name Deprecated Config Functions and Constants
209230
*/
210231
/**@{*/

include/git2/rebase.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,38 @@ typedef struct {
7474
*/
7575
git_checkout_options checkout_options;
7676

77+
/**
78+
* Optional callback that allows users to override commit
79+
* creation in `git_rebase_commit`. If specified, users can
80+
* create their own commit and provide the commit ID, which
81+
* may be useful for signing commits or otherwise customizing
82+
* the commit creation.
83+
*
84+
* If this callback returns `GIT_PASSTHROUGH`, then
85+
* `git_rebase_commit` will continue to create the commit.
86+
*/
87+
git_commit_create_cb commit_create_cb;
88+
89+
#ifdef GIT_DEPRECATE_HARD
90+
void *reserved;
91+
#else
7792
/**
7893
* If provided, this will be called with the commit content, allowing
7994
* a signature to be added to the rebase commit. Can be skipped with
8095
* GIT_PASSTHROUGH. If GIT_PASSTHROUGH is returned, a commit will be made
8196
* without a signature.
97+
*
8298
* This field is only used when performing git_rebase_commit.
99+
*
100+
* This callback is not invoked if a `git_commit_create_cb` is
101+
* specified.
102+
*
103+
* This callback is deprecated; users should provide a
104+
* creation callback as `commit_create_cb` that produces a
105+
* commit buffer, signs it, and commits it.
83106
*/
84-
git_commit_signing_cb signing_cb;
107+
int (*signing_cb)(git_buf *, git_buf *, const char *, void *);
108+
#endif
85109

86110
/**
87111
* This will be passed to each of the callbacks in this struct

src/rebase.c

Lines changed: 69 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,54 @@ int git_rebase_inmemory_index(
943943
return 0;
944944
}
945945

946+
#ifndef GIT_DEPRECATE_HARD
947+
static int create_signed(
948+
git_oid *out,
949+
git_rebase *rebase,
950+
const git_signature *author,
951+
const git_signature *committer,
952+
const char *message_encoding,
953+
const char *message,
954+
git_tree *tree,
955+
size_t parent_count,
956+
const git_commit **parents)
957+
{
958+
git_buf commit_content = GIT_BUF_INIT,
959+
commit_signature = GIT_BUF_INIT,
960+
signature_field = GIT_BUF_INIT;
961+
int error;
962+
963+
git_error_clear();
964+
965+
if ((error = git_commit_create_buffer(&commit_content,
966+
rebase->repo, author, committer, message_encoding,
967+
message, tree, parent_count, parents)) < 0)
968+
goto done;
969+
970+
error = rebase->options.signing_cb(&commit_signature,
971+
&signature_field, commit_content.ptr,
972+
rebase->options.payload);
973+
974+
if (error) {
975+
if (error != GIT_PASSTHROUGH)
976+
git_error_set_after_callback_function(error, "signing_cb");
977+
978+
goto done;
979+
}
980+
981+
error = git_commit_create_with_signature(out, rebase->repo,
982+
commit_content.ptr,
983+
commit_signature.size > 0 ? commit_signature.ptr : NULL,
984+
signature_field.size > 0 ? signature_field.ptr : NULL);
985+
986+
done:
987+
git_buf_dispose(&commit_signature);
988+
git_buf_dispose(&signature_field);
989+
git_buf_dispose(&commit_content);
990+
return error;
991+
}
992+
#endif
993+
946994
static int rebase_commit__create(
947995
git_commit **out,
948996
git_rebase *rebase,
@@ -957,10 +1005,6 @@ static int rebase_commit__create(
9571005
git_commit *current_commit = NULL, *commit = NULL;
9581006
git_tree *parent_tree = NULL, *tree = NULL;
9591007
git_oid tree_id, commit_id;
960-
git_buf commit_content = GIT_BUF_INIT, commit_signature = GIT_BUF_INIT,
961-
signature_field = GIT_BUF_INIT;
962-
const char *signature_field_string = NULL,
963-
*commit_signature_string = NULL;
9641008
int error;
9651009

9661010
operation = git_array_get(rebase->operations, rebase->current);
@@ -991,37 +1035,32 @@ static int rebase_commit__create(
9911035
message = git_commit_message(current_commit);
9921036
}
9931037

994-
if ((error = git_commit_create_buffer(&commit_content, rebase->repo, author, committer,
995-
message_encoding, message, tree, 1, (const git_commit **)&parent_commit)) < 0)
996-
goto done;
1038+
git_error_clear();
1039+
error = GIT_PASSTHROUGH;
9971040

998-
if (rebase->options.signing_cb) {
999-
git_error_clear();
1000-
error = git_error_set_after_callback_function(rebase->options.signing_cb(
1001-
&commit_signature, &signature_field, git_buf_cstr(&commit_content),
1002-
rebase->options.payload), "commit signing_cb failed");
1003-
if (error == GIT_PASSTHROUGH) {
1004-
git_buf_dispose(&commit_signature);
1005-
git_buf_dispose(&signature_field);
1006-
git_error_clear();
1007-
error = GIT_OK;
1008-
} else if (error < 0)
1009-
goto done;
1010-
}
1041+
if (rebase->options.commit_create_cb) {
1042+
error = rebase->options.commit_create_cb(&commit_id,
1043+
author, committer, message_encoding, message,
1044+
tree, 1, (const git_commit **)&parent_commit,
1045+
rebase->options.payload);
10111046

1012-
if (git_buf_is_allocated(&commit_signature)) {
1013-
GIT_ASSERT(git_buf_contains_nul(&commit_signature));
1014-
commit_signature_string = git_buf_cstr(&commit_signature);
1047+
git_error_set_after_callback_function(error,
1048+
"commit_create_cb");
10151049
}
1016-
1017-
if (git_buf_is_allocated(&signature_field)) {
1018-
GIT_ASSERT(git_buf_contains_nul(&signature_field));
1019-
signature_field_string = git_buf_cstr(&signature_field);
1050+
#ifndef GIT_DEPRECATE_HARD
1051+
else if (rebase->options.signing_cb) {
1052+
error = create_signed(&commit_id, rebase, author,
1053+
committer, message_encoding, message, tree,
1054+
1, (const git_commit **)&parent_commit);
10201055
}
1056+
#endif
10211057

1022-
if ((error = git_commit_create_with_signature(&commit_id, rebase->repo,
1023-
git_buf_cstr(&commit_content), commit_signature_string,
1024-
signature_field_string)))
1058+
if (error == GIT_PASSTHROUGH)
1059+
error = git_commit_create(&commit_id, rebase->repo, NULL,
1060+
author, committer, message_encoding, message,
1061+
tree, 1, (const git_commit **)&parent_commit);
1062+
1063+
if (error)
10251064
goto done;
10261065

10271066
if ((error = git_commit_lookup(&commit, rebase->repo, &commit_id)) < 0)
@@ -1033,9 +1072,6 @@ static int rebase_commit__create(
10331072
if (error < 0)
10341073
git_commit_free(commit);
10351074

1036-
git_buf_dispose(&commit_signature);
1037-
git_buf_dispose(&signature_field);
1038-
git_buf_dispose(&commit_content);
10391075
git_commit_free(current_commit);
10401076
git_tree_free(parent_tree);
10411077
git_tree_free(tree);

0 commit comments

Comments
 (0)