Skip to content

Commit 56303e1

Browse files
committed
mailmap: API and style cleanup
1 parent a140c13 commit 56303e1

File tree

10 files changed

+112
-105
lines changed

10 files changed

+112
-105
lines changed

include/git2/mailmap.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,11 @@ GIT_EXTERN(int) git_mailmap_add_entry(
5858
*
5959
* @param mm mailmap to add the entries to
6060
* @param buf the buffer to read the mailmap file from
61+
* @param len the length of the input buffer [optional: 0 defaults to 'strlen']
6162
* @return 0 on success, or an error code
6263
*/
63-
GIT_EXTERN(int) git_mailmap_add_buffer(git_mailmap *mm, const git_buf *buf);
64+
GIT_EXTERN(int) git_mailmap_add_buffer(
65+
git_mailmap *mm, const char *buf, size_t len);
6466

6567
/**
6668
* Create a new mailmap instance containing a single mailmap file
@@ -72,9 +74,11 @@ GIT_EXTERN(int) git_mailmap_add_buffer(git_mailmap *mm, const git_buf *buf);
7274
*
7375
* @param out pointer to store the new mailmap
7476
* @param buf buffer to parse the mailmap from
77+
* @param len the length of the input buffer [optional: 0 defaults to 'strlen']
7578
* @return 0 on success, or an error code
7679
*/
77-
GIT_EXTERN(int) git_mailmap_from_buffer(git_mailmap **out, const git_buf *buf);
80+
GIT_EXTERN(int) git_mailmap_from_buffer(
81+
git_mailmap **out, const char *buf, size_t len);
7882

7983
/**
8084
* Create a new mailmap instance from a repository, loading mailmap files based
@@ -109,6 +113,19 @@ GIT_EXTERN(int) git_mailmap_resolve(
109113
const char **real_name, const char **real_email,
110114
const git_mailmap *mm, const char *name, const char *email);
111115

116+
/**
117+
* Resolve a signature to use real names and emails with a mailmap.
118+
*
119+
* Call `git_signature_free()` to free the data.
120+
*
121+
* @param out new signature
122+
* @param mm mailmap to resolve with
123+
* @param sig signature to resolve
124+
* @return 0 or an error code
125+
*/
126+
GIT_EXTERN(int) git_mailmap_resolve_signature(
127+
git_signature **out, const git_mailmap *mm, const git_signature *sig);
128+
112129
/** @} */
113130
GIT_END_DECL
114131
#endif

include/git2/signature.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,6 @@ GIT_EXTERN(int) git_signature_default(git_signature **out, git_repository *repo)
7575
*/
7676
GIT_EXTERN(int) git_signature_from_buffer(git_signature **out, const char *buf);
7777

78-
/**
79-
* Create a signature with names updated respecting the mailmap.
80-
*
81-
* Call `git_signature_free()` to free the data.
82-
*
83-
* @param out new signature
84-
* @param sig signature to resolve
85-
* @param mailmap mailmap to resolve with
86-
* @return 0 or an error code
87-
*/
88-
GIT_EXTERN(int) git_signature_with_mailmap(git_signature **out, const git_signature *sig, const git_mailmap *mailmap);
89-
9078
/**
9179
* Create a copy of an existing signature. All internal strings are also
9280
* duplicated.

include/git2/types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ struct git_writestream {
434434
void (*free)(git_writestream *stream);
435435
};
436436

437-
/** A parsed representation of a .mailmap file. */
437+
/** Representation of .mailmap file state. */
438438
typedef struct git_mailmap git_mailmap;
439439

440440
/** @} */

src/commit.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "git2/object.h"
1212
#include "git2/repository.h"
1313
#include "git2/signature.h"
14+
#include "git2/mailmap.h"
1415
#include "git2/sys/commit.h"
1516

1617
#include "odb.h"
@@ -893,11 +894,11 @@ int git_commit_create_with_signature(
893894
int git_commit_committer_with_mailmap(
894895
git_signature **out, const git_commit *commit, const git_mailmap *mailmap)
895896
{
896-
return git_signature_with_mailmap(out, commit->committer, mailmap);
897+
return git_mailmap_resolve_signature(out, mailmap, commit->committer);
897898
}
898899

899900
int git_commit_author_with_mailmap(
900901
git_signature **out, const git_commit *commit, const git_mailmap *mailmap)
901902
{
902-
return git_signature_with_mailmap(out, commit->author, mailmap);
903+
return git_mailmap_resolve_signature(out, mailmap, commit->author);
903904
}

src/mailmap.c

Lines changed: 79 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "common.h"
1111
#include "path.h"
1212
#include "repository.h"
13+
#include "signature.h"
1314
#include "git2/config.h"
1415
#include "git2/revparse.h"
1516
#include "blob.h"
@@ -171,29 +172,32 @@ void git_mailmap_free(git_mailmap *mm)
171172
git__free(mm);
172173
}
173174

174-
int git_mailmap_add_entry(
175-
git_mailmap *mm, const char *real_name, const char *real_email,
176-
const char *replace_name, const char *replace_email)
175+
static int mailmap_add_entry_unterminated(
176+
git_mailmap *mm,
177+
const char *real_name, size_t real_name_size,
178+
const char *real_email, size_t real_email_size,
179+
const char *replace_name, size_t replace_name_size,
180+
const char *replace_email, size_t replace_email_size)
177181
{
178182
int error;
179183
git_mailmap_entry *entry = git__calloc(1, sizeof(git_mailmap_entry));
180184
GITERR_CHECK_ALLOC(entry);
181185

182186
assert(mm && replace_email && *replace_email);
183187

184-
if (real_name && *real_name) {
185-
entry->real_name = git__strdup(real_name);
188+
if (real_name_size > 0) {
189+
entry->real_name = git__substrdup(real_name, real_name_size);
186190
GITERR_CHECK_ALLOC(entry->real_name);
187191
}
188-
if (real_email && *real_email) {
189-
entry->real_email = git__strdup(real_email);
192+
if (real_email_size > 0) {
193+
entry->real_email = git__substrdup(real_email, real_email_size);
190194
GITERR_CHECK_ALLOC(entry->real_email);
191195
}
192-
if (replace_name && *replace_name) {
193-
entry->replace_name = git__strdup(replace_name);
196+
if (replace_name_size > 0) {
197+
entry->replace_name = git__substrdup(replace_name, replace_name_size);
194198
GITERR_CHECK_ALLOC(entry->replace_name);
195199
}
196-
entry->replace_email = git__strdup(replace_email);
200+
entry->replace_email = git__substrdup(replace_email, replace_email_size);
197201
GITERR_CHECK_ALLOC(entry->replace_email);
198202

199203
error = git_vector_insert_sorted(&mm->entries, entry, mailmap_entry_replace);
@@ -203,10 +207,21 @@ int git_mailmap_add_entry(
203207
return error;
204208
}
205209

206-
int git_mailmap_add_buffer(git_mailmap *mm, const git_buf *buf)
210+
int git_mailmap_add_entry(
211+
git_mailmap *mm, const char *real_name, const char *real_email,
212+
const char *replace_name, const char *replace_email)
213+
{
214+
return mailmap_add_entry_unterminated(
215+
mm,
216+
real_name, real_name ? strlen(real_name) : 0,
217+
real_email, real_email ? strlen(real_email) : 0,
218+
replace_name, replace_name ? strlen(replace_name) : 0,
219+
replace_email, strlen(replace_email));
220+
}
221+
222+
int git_mailmap_add_buffer(git_mailmap *mm, const char *buf, size_t len)
207223
{
208224
int error;
209-
git_mailmap_entry *entry = NULL;
210225
git_parse_ctx ctx;
211226

212227
/* Scratch buffers containing the real parsed names & emails */
@@ -215,10 +230,15 @@ int git_mailmap_add_buffer(git_mailmap *mm, const git_buf *buf)
215230
git_buf replace_name = GIT_BUF_INIT;
216231
git_buf replace_email = GIT_BUF_INIT;
217232

218-
if (git_buf_contains_nul(buf))
233+
/* If `len` is passed as 0, use strlen to get the real length */
234+
if (buf && len == 0)
235+
len = strlen(buf);
236+
237+
/* Buffers may not contain '\0's. */
238+
if (memchr(buf, '\0', len) != NULL)
219239
return -1;
220240

221-
git_parse_ctx_init(&ctx, buf->ptr, buf->size);
241+
git_parse_ctx_init(&ctx, buf, len);
222242

223243
/* Run the parser */
224244
while (ctx.remain_len > 0) {
@@ -230,51 +250,31 @@ int git_mailmap_add_buffer(git_mailmap *mm, const git_buf *buf)
230250
continue; /* TODO: warn */
231251
}
232252

233-
entry = git__calloc(1, sizeof(git_mailmap_entry));
234-
GITERR_CHECK_ALLOC(entry);
235-
236-
if (real_name.size > 0) {
237-
entry->real_name = git__substrdup(real_name.ptr, real_name.size);
238-
GITERR_CHECK_ALLOC(entry->real_name);
239-
}
240-
if (real_email.size > 0) {
241-
entry->real_email = git__substrdup(real_email.ptr, real_email.size);
242-
GITERR_CHECK_ALLOC(entry->real_email);
243-
}
244-
if (replace_name.size > 0) {
245-
entry->replace_name = git__substrdup(replace_name.ptr, replace_name.size);
246-
GITERR_CHECK_ALLOC(entry->replace_name);
247-
}
248-
entry->replace_email = git__substrdup(replace_email.ptr, replace_email.size);
249-
GITERR_CHECK_ALLOC(entry->replace_email);
250-
251-
error = git_vector_insert_sorted(
252-
&mm->entries, entry, mailmap_entry_replace);
253+
/* NOTE: Can't use add_entry(...) as our buffers aren't terminated */
254+
error = mailmap_add_entry_unterminated(
255+
mm, real_name.ptr, real_name.size, real_email.ptr, real_email.size,
256+
replace_name.ptr, replace_name.size, replace_email.ptr, replace_email.size);
253257
if (error < 0 && error != GIT_EEXISTS)
254258
goto cleanup;
255259

256-
entry = NULL;
257260
error = 0;
258261
}
259262

260263
cleanup:
261-
mailmap_entry_free(entry);
262-
263-
/* We never allocate data in these buffers, but better safe than sorry */
264264
git_buf_free(&real_name);
265265
git_buf_free(&real_email);
266266
git_buf_free(&replace_name);
267267
git_buf_free(&replace_email);
268268
return error;
269269
}
270270

271-
int git_mailmap_from_buffer(git_mailmap **out, const git_buf *buffer)
271+
int git_mailmap_from_buffer(git_mailmap **out, const char *data, size_t len)
272272
{
273273
int error = git_mailmap_new(out);
274274
if (error < 0)
275275
return error;
276276

277-
error = git_mailmap_add_buffer(*out, buffer);
277+
error = git_mailmap_add_buffer(*out, data, len);
278278
if (error < 0) {
279279
git_mailmap_free(*out);
280280
*out = NULL;
@@ -283,7 +283,7 @@ int git_mailmap_from_buffer(git_mailmap **out, const git_buf *buffer)
283283
}
284284

285285
static int mailmap_add_blob(
286-
git_mailmap *mm, git_repository *repo, const char *spec)
286+
git_mailmap *mm, git_repository *repo, const char *rev)
287287
{
288288
git_object *object = NULL;
289289
git_blob *blob = NULL;
@@ -292,7 +292,7 @@ static int mailmap_add_blob(
292292

293293
assert(mm && repo);
294294

295-
error = git_revparse_single(&object, repo, spec);
295+
error = git_revparse_single(&object, repo, rev);
296296
if (error < 0)
297297
goto cleanup;
298298

@@ -304,7 +304,7 @@ static int mailmap_add_blob(
304304
if (error < 0)
305305
goto cleanup;
306306

307-
error = git_mailmap_add_buffer(mm, &content);
307+
error = git_mailmap_add_buffer(mm, content.ptr, content.size);
308308
if (error < 0)
309309
goto cleanup;
310310

@@ -331,7 +331,7 @@ static int mailmap_add_file_ondisk(
331331
if (error < 0)
332332
goto cleanup;
333333

334-
error = git_mailmap_add_buffer(mm, &content);
334+
error = git_mailmap_add_buffer(mm, content.ptr, content.size);
335335
if (error < 0)
336336
goto cleanup;
337337

@@ -345,21 +345,21 @@ static int mailmap_add_file_ondisk(
345345
static void mailmap_add_from_repository(git_mailmap *mm, git_repository *repo)
346346
{
347347
git_config *config = NULL;
348-
git_buf spec_buf = GIT_BUF_INIT;
348+
git_buf rev_buf = GIT_BUF_INIT;
349349
git_buf path_buf = GIT_BUF_INIT;
350-
const char *spec = NULL;
350+
const char *rev = NULL;
351351
const char *path = NULL;
352352

353353
assert(mm && repo);
354354

355355
/* If we're in a bare repo, default blob to 'HEAD:.mailmap' */
356356
if (repo->is_bare)
357-
spec = MM_BLOB_DEFAULT;
357+
rev = MM_BLOB_DEFAULT;
358358

359359
/* Try to load 'mailmap.file' and 'mailmap.blob' cfgs from the repo */
360360
if (git_repository_config(&config, repo) == 0) {
361-
if (git_config_get_string_buf(&spec_buf, config, MM_BLOB_CONFIG) == 0)
362-
spec = spec_buf.ptr;
361+
if (git_config_get_string_buf(&rev_buf, config, MM_BLOB_CONFIG) == 0)
362+
rev = rev_buf.ptr;
363363
if (git_config_get_path(&path_buf, config, MM_FILE_CONFIG) == 0)
364364
path = path_buf.ptr;
365365
}
@@ -377,12 +377,12 @@ static void mailmap_add_from_repository(git_mailmap *mm, git_repository *repo)
377377
*/
378378
if (!repo->is_bare)
379379
mailmap_add_file_ondisk(mm, MM_FILE, repo);
380-
if (spec != NULL)
381-
mailmap_add_blob(mm, repo, spec);
380+
if (rev != NULL)
381+
mailmap_add_blob(mm, repo, rev);
382382
if (path != NULL)
383383
mailmap_add_file_ondisk(mm, path, repo);
384384

385-
git_buf_free(&spec_buf);
385+
git_buf_free(&rev_buf);
386386
git_buf_free(&path_buf);
387387
git_config_free(config);
388388
}
@@ -403,7 +403,10 @@ const git_mailmap_entry *git_mailmap_entry_lookup(
403403
ssize_t fallback = -1;
404404
size_t idx;
405405
git_mailmap_entry *entry;
406-
git_mailmap_entry needle = { NULL, NULL, NULL, (char *)email };
406+
407+
/* The lookup needle we want to use only sets the replace_email. */
408+
git_mailmap_entry needle = { NULL };
409+
needle.replace_email = (char *)email;
407410

408411
assert(email);
409412

@@ -457,3 +460,26 @@ int git_mailmap_resolve(
457460
}
458461
return 0;
459462
}
463+
464+
int git_mailmap_resolve_signature(
465+
git_signature **out, const git_mailmap *mailmap, const git_signature *sig)
466+
{
467+
const char *name = NULL;
468+
const char *email = NULL;
469+
int error;
470+
471+
if (!sig)
472+
return 0;
473+
474+
error = git_mailmap_resolve(&name, &email, mailmap, sig->name, sig->email);
475+
if (error < 0)
476+
return error;
477+
478+
error = git_signature_new(out, name, email, sig->when.time, sig->when.offset);
479+
if (error < 0)
480+
return error;
481+
482+
/* Copy over the sign, as git_signature_new doesn't let you pass it. */
483+
(*out)->when.sign = sig->when.sign;
484+
return 0;
485+
}

0 commit comments

Comments
 (0)