Skip to content

Commit 578cc02

Browse files
committed
Single callback for commit signing in rebase w/ git_buf
Reduces the number of callbacks for signing a commit during a rebase operation to just one callback. That callback has 2 out git_buf parameters for signature and signature field. We use git_buf here, because we cannot make any assumptions about the heap allocator a user of the library might be using.
1 parent 900f991 commit 578cc02

File tree

3 files changed

+49
-74
lines changed

3 files changed

+49
-74
lines changed

include/git2/rebase.h

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,31 +27,16 @@ GIT_BEGIN_DECL
2727
* Rebase commit signature callback.
2828
*
2929
* The callback will be called with the commit content, giving a user an
30-
* opportunity to sign the commit content in a rebase.
31-
* The signature parameter will be owned by LibGit2 after this callback returns.
30+
* opportunity to sign the commit content in a rebase. The signature_field
31+
* buf may be left empty to specify the default field.
3232
*
3333
* When the callback:
3434
* - returns GIT_PASSTHROUGH, no signature will be added to the commit.
3535
* - returns < 0, git_rebase_commit will be aborted.
3636
* - returns GIT_OK, the signature parameter is expected to be filled.
3737
*/
3838
typedef int (*git_rebase_commit_signature_cb)(
39-
char **signature, const char *commit_content, void *payload);
40-
41-
/**
42-
* Rebase commit signature field callback.
43-
*
44-
* The callback will be called if a signature_cb was called and successful.
45-
* This callback will provide the field that a user is signing in a git_rebase_commit.
46-
* The signature_field parameter will be owned by LibGit2 after this callback returns.
47-
*
48-
* When the callback:
49-
* - returns GIT_PASSTHROUGH, signature_field is expected to remain null.
50-
* - returns < 0, git_rebase_commit will be aborted.
51-
* - returns GIT_OK, the signature_field parameter is expected to be filled.
52-
*/
53-
typedef int (*git_rebase_commit_signature_field_cb)(
54-
char **signature_field, void *payload);
39+
git_buf *signature, git_buf *signature_field, const char *commit_content, void *payload);
5540

5641
/**
5742
* Rebase options
@@ -112,13 +97,6 @@ typedef struct {
11297
*/
11398
git_rebase_commit_signature_cb signature_cb;
11499

115-
/**
116-
* If provided and the signature_cb is provided, this will be called asking
117-
* for the field to write the signature to. Can be skipped with GIT_PASSTHROUGH.
118-
* This field is only used when performing git_rebase_commit.
119-
*/
120-
git_rebase_commit_signature_field_cb signature_field_cb;
121-
122100
/**
123101
* This will be passed to each of the callbacks in this struct
124102
* as the last parameter.
@@ -170,7 +148,7 @@ typedef enum {
170148
#define GIT_REBASE_OPTIONS_VERSION 1
171149
#define GIT_REBASE_OPTIONS_INIT \
172150
{ GIT_REBASE_OPTIONS_VERSION, 0, 0, NULL, GIT_MERGE_OPTIONS_INIT, \
173-
GIT_CHECKOUT_OPTIONS_INIT, 0, 0, NULL }
151+
GIT_CHECKOUT_OPTIONS_INIT, 0, NULL }
174152

175153
/** Indicates that a rebase operation is not (yet) in progress. */
176154
#define GIT_REBASE_NO_OPERATION SIZE_MAX

src/rebase.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -945,8 +945,9 @@ static int rebase_commit__create(
945945
git_commit *current_commit = NULL, *commit = NULL;
946946
git_tree *parent_tree = NULL, *tree = NULL;
947947
git_oid tree_id, commit_id;
948-
git_buf commit_content = GIT_BUF_INIT;
949-
char *signature = NULL, *signature_field = NULL;
948+
git_buf commit_content = GIT_BUF_INIT, commit_signature = GIT_BUF_INIT,
949+
signature_field = GIT_BUF_INIT;
950+
const char *signature_field_as_string = NULL;
950951
int error;
951952

952953
operation = git_array_get(rebase->operations, rebase->current);
@@ -985,21 +986,22 @@ static int rebase_commit__create(
985986
message_encoding, message, tree, 1, (const git_commit **)&parent_commit)) < 0)
986987
goto done;
987988

988-
if ((error = rebase->options.signature_cb(&signature, git_buf_cstr(&commit_content),
989-
rebase->options.payload)) < 0 && error != GIT_PASSTHROUGH)
989+
if ((error = rebase->options.signature_cb(&commit_signature, &signature_field,
990+
git_buf_cstr(&commit_content), rebase->options.payload)) < 0 &&
991+
error != GIT_PASSTHROUGH)
990992
goto done;
991993

992994
if (error != GIT_PASSTHROUGH) {
993-
if (rebase->options.signature_field_cb &&
994-
(error = rebase->options.signature_field_cb(&signature_field, rebase->options.payload)) < 0) {
995-
if (error == GIT_PASSTHROUGH)
996-
assert(signature_field == NULL);
997-
else
998-
goto done;
995+
if (git_buf_is_allocated(&signature_field)) {
996+
assert(git_buf_contains_nul(&signature_field));
997+
signature_field_as_string = git_buf_cstr(&signature_field);
999998
}
1000999

1000+
assert(git_buf_is_allocated(&commit_signature));
1001+
assert(git_buf_contains_nul(&commit_signature));
10011002
if ((error = git_commit_create_with_signature(&commit_id, rebase->repo,
1002-
git_buf_cstr(&commit_content), signature, signature_field)) < 0)
1003+
git_buf_cstr(&commit_content), git_buf_cstr(&commit_signature),
1004+
signature_field_as_string)))
10031005
goto done;
10041006
}
10051007
}
@@ -1019,10 +1021,8 @@ static int rebase_commit__create(
10191021
if (error < 0)
10201022
git_commit_free(commit);
10211023

1022-
if (signature)
1023-
free(signature);
1024-
if (signature_field)
1025-
free(signature_field);
1024+
git_buf_dispose(&commit_signature);
1025+
git_buf_dispose(&signature_field);
10261026
git_buf_dispose(&commit_content);
10271027
git_commit_free(current_commit);
10281028
git_tree_free(parent_tree);

tests/rebase/sign.c

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,14 @@ committer Rebaser <rebaser@rebaser.rb> 1405694510 +0000\n\
2525
\n\
2626
Modification 3 to gravy\n";
2727

28-
int signature_cb_passthrough(char **signature, const char *commit_content, void *payload)
28+
int signature_cb_passthrough(
29+
git_buf *signature,
30+
git_buf *signature_field,
31+
const char *commit_content,
32+
void *payload)
2933
{
30-
cl_assert_equal_p(NULL, *signature);
34+
cl_assert_equal_b(false, git_buf_is_allocated(signature));
35+
cl_assert_equal_b(false, git_buf_is_allocated(signature_field));
3136
cl_assert_equal_s(expected_commit_content, commit_content);
3237
cl_assert_equal_p(NULL, payload);
3338
return GIT_PASSTHROUGH;
@@ -79,7 +84,11 @@ committer Rebaser <rebaser@rebaser.rb> 1405694510 +0000\n";
7984
git_rebase_free(rebase);
8085
}
8186

82-
int signature_cb_gpg(char **signature, const char *commit_content, void *payload)
87+
int signature_cb_gpg(
88+
git_buf *signature,
89+
git_buf *signature_field,
90+
const char *commit_content,
91+
void *payload)
8392
{
8493
const char *gpg_signature = "-----BEGIN PGP SIGNATURE-----\n\
8594
\n\
@@ -98,22 +107,17 @@ cttVRsdOoego+fiy08eFE+aJIeYiINRGhqOBTsuqG4jIdpdKxPE=\n\
98107
=KbsY\n\
99108
-----END PGP SIGNATURE-----";
100109

110+
cl_assert_equal_b(false, git_buf_is_allocated(signature));
111+
cl_assert_equal_b(false, git_buf_is_allocated(signature_field));
101112
cl_assert_equal_s(expected_commit_content, commit_content);
102113
cl_assert_equal_p(NULL, payload);
103114

104-
*signature = strdup(gpg_signature);
115+
cl_git_pass(git_buf_set(signature, gpg_signature, strlen(gpg_signature) + 1));
105116
return GIT_OK;
106117
}
107118

108-
int signature_field_cb_passthrough(char **signature_field, void *payload)
109-
{
110-
cl_assert_equal_p(NULL, *signature_field);
111-
cl_assert_equal_p(NULL, payload);
112-
return GIT_PASSTHROUGH;
113-
}
114-
115119
/* git checkout gravy ; git rebase --merge veal */
116-
void test_gpg_signature(bool use_passthrough)
120+
void test_rebase_sign__gpg_with_no_field(void)
117121
{
118122
git_rebase *rebase;
119123
git_reference *branch_ref, *upstream_ref;
@@ -145,8 +149,6 @@ gpgsig -----BEGIN PGP SIGNATURE-----\n\
145149
-----END PGP SIGNATURE-----\n";
146150

147151
rebase_opts.signature_cb = signature_cb_gpg;
148-
if (use_passthrough)
149-
rebase_opts.signature_field_cb = signature_field_cb_passthrough;
150152

151153
cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy"));
152154
cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal"));
@@ -176,30 +178,26 @@ gpgsig -----BEGIN PGP SIGNATURE-----\n\
176178
git_rebase_free(rebase);
177179
}
178180

179-
/* git checkout gravy ; git rebase --merge veal */
180-
void test_rebase_sign__gpg_with_no_field_cb(void)
181-
{
182-
test_gpg_signature(false);
183-
}
184181

185-
/* git checkout gravy ; git rebase --merge veal */
186-
void test_rebase_sign__gpg_with_passthrough_field_cb(void)
182+
int signature_cb_magic_field(
183+
git_buf *signature,
184+
git_buf *signature_field,
185+
const char *commit_content,
186+
void *payload)
187187
{
188-
test_gpg_signature(true);
189-
}
188+
const char *signature_content = "magic word: pretty please";
189+
const char * signature_field_content = "magicsig";
190190

191-
int signature_cb_magic_field(char **signature, const char *commit_content, void *payload)
192-
{
191+
cl_assert_equal_b(false, git_buf_is_allocated(signature));
192+
cl_assert_equal_b(false, git_buf_is_allocated(signature_field));
193193
cl_assert_equal_s(expected_commit_content, commit_content);
194194
cl_assert_equal_p(NULL, payload);
195-
*signature = strdup("magic word: pretty please");
196-
return GIT_OK;
197-
}
198195

199-
int signature_field_cb_magic_field(char **signature_field, void *payload)
200-
{
201-
cl_assert_equal_p(NULL, payload);
202-
*signature_field = strdup("magicsig");
196+
cl_git_pass(git_buf_set(signature, signature_content,
197+
strlen(signature_content) + 1));
198+
cl_git_pass(git_buf_set(signature_field, signature_field_content,
199+
strlen(signature_field_content) + 1));
200+
203201
return GIT_OK;
204202
}
205203

@@ -221,7 +219,6 @@ committer Rebaser <rebaser@rebaser.rb> 1405694510 +0000\n\
221219
magicsig magic word: pretty please\n";
222220

223221
rebase_opts.signature_cb = signature_cb_magic_field;
224-
rebase_opts.signature_field_cb = signature_field_cb_magic_field;
225222

226223
cl_git_pass(git_reference_lookup(&branch_ref, repo, "refs/heads/gravy"));
227224
cl_git_pass(git_reference_lookup(&upstream_ref, repo, "refs/heads/veal"));

0 commit comments

Comments
 (0)