Skip to content

Commit 18ff9ba

Browse files
committed
mailmap: API and style cleanup
1 parent 57cfeab commit 18ff9ba

File tree

6 files changed

+122
-70
lines changed

6 files changed

+122
-70
lines changed

include/git2/mailmap.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,9 @@ GIT_EXTERN(void) git_mailmap_free(git_mailmap *mailmap);
8585
* @param mailmap the mailmap to perform the lookup in. (may be NULL)
8686
* @param name the name to resolve.
8787
* @param email the email to resolve.
88+
* @return 0 on success, otherwise an error code.
8889
*/
89-
GIT_EXTERN(void) git_mailmap_resolve(
90+
GIT_EXTERN(int) git_mailmap_resolve(
9091
const char **name_out, const char **email_out,
9192
const git_mailmap *mailmap, const char *name, const char *email);
9293

src/mailmap.c

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ struct git_mailmap {
2121
git_vector entries;
2222
};
2323

24+
static void mailmap_entry_free(git_mailmap_entry *entry)
25+
{
26+
if (!entry)
27+
return;
28+
29+
git__free(entry->real_name);
30+
git__free(entry->real_email);
31+
git__free(entry->replace_name);
32+
git__free(entry->replace_email);
33+
git__free(entry);
34+
}
35+
2436
/* Check if we're at the end of line, w/ comments */
2537
static bool is_eol(git_parse_ctx *ctx)
2638
{
@@ -43,7 +55,8 @@ static int advance_until(
4355
return 0;
4456
}
4557

46-
/* Parse a single entry from a mailmap file.
58+
/*
59+
* Parse a single entry from a mailmap file.
4760
*
4861
* The output git_bufs will be non-owning, and should be copied before being
4962
* persisted.
@@ -61,16 +74,21 @@ static int parse_mailmap_entry(
6174
git_buf_clear(replace_name);
6275
git_buf_clear(replace_email);
6376

64-
/* Parse the real name */
6577
git_parse_advance_ws(ctx);
78+
if (is_eol(ctx))
79+
return -1; /* blank line */
80+
81+
/* Parse the real name */
6682
if (advance_until(&start, &len, ctx, '<') < 0)
6783
return -1;
6884

6985
git_buf_attach_notowned(real_name, start, len);
7086
git_buf_rtrim(real_name);
7187

72-
/* If this is the last email in the line, this is the email to replace,
73-
* otherwise, it's the real email. */
88+
/*
89+
* If this is the last email in the line, this is the email to replace,
90+
* otherwise, it's the real email.
91+
*/
7492
if (advance_until(&start, &len, ctx, '>') < 0)
7593
return -1;
7694

@@ -131,38 +149,27 @@ int git_mailmap_from_buffer(git_mailmap **out, git_buf *buf)
131149
if (error < 0) {
132150
error = 0; /* Skip lines which don't contain a valid entry */
133151
git_parse_advance_line(&ctx);
134-
continue;
152+
continue; /* TODO: warn */
135153
}
136154

137-
GITERR_CHECK_ALLOC_ADD5(
138-
&entry_size, sizeof(git_mailmap_entry) + 4 /* 4x'\0' */,
139-
real_name.size, real_email.size,
140-
replace_name.size, replace_email.size);
141-
entry = git__calloc(1, entry_size);
155+
entry = git__calloc(1, sizeof(git_mailmap_entry));
142156
GITERR_CHECK_ALLOC(entry);
143-
144157
entry->version = GIT_MAILMAP_ENTRY_VERSION;
145158

146-
/* Copy strings into the buffer following entry */
147-
entry_data = (char *)(entry + 1);
148159
if (real_name.size > 0) {
149-
memcpy(entry_data, real_name.ptr, real_name.size);
150-
entry->real_name = entry_data;
151-
entry_data += real_name.size + 1; /* advance past null from calloc */
160+
entry->real_name = git__substrdup(real_name.ptr, real_name.size);
161+
GITERR_CHECK_ALLOC(entry->real_name);
152162
}
153163
if (real_email.size > 0) {
154-
memcpy(entry_data, real_email.ptr, real_email.size);
155-
entry->real_email = entry_data;
156-
entry_data += real_email.size + 1;
164+
entry->real_email = git__substrdup(real_email.ptr, real_email.size);
165+
GITERR_CHECK_ALLOC(entry->real_email);
157166
}
158167
if (replace_name.size > 0) {
159-
memcpy(entry_data, replace_name.ptr, replace_name.size);
160-
entry->replace_name = entry_data;
161-
entry_data += replace_name.size + 1;
168+
entry->replace_name = git__substrdup(replace_name.ptr, replace_name.size);
169+
GITERR_CHECK_ALLOC(entry->replace_name);
162170
}
163-
/* replace_email is always non-null */
164-
memcpy(entry_data, replace_email.ptr, replace_email.size);
165-
entry->replace_email = entry_data;
171+
entry->replace_email = git__substrdup(replace_email.ptr, replace_email.size);
172+
GITERR_CHECK_ALLOC(entry->replace_email);
166173

167174
error = git_vector_insert(&mm->entries, entry);
168175
if (error < 0)
@@ -175,7 +182,7 @@ int git_mailmap_from_buffer(git_mailmap **out, git_buf *buf)
175182
mm = NULL;
176183

177184
cleanup:
178-
git__free(entry);
185+
mailmap_entry_free(entry);
179186
git_mailmap_free(mm);
180187

181188
/* We never allocate data in these buffers, but better safe than sorry */
@@ -191,11 +198,15 @@ void git_mailmap_free(git_mailmap *mailmap)
191198
if (!mailmap)
192199
return;
193200

194-
git_vector_free_deep(&mailmap->entries);
201+
git_vector_foreach(&mailmap->entries, i, entry) {
202+
mailmap_entry_free(entry);
203+
}
204+
git_vector_free(&mailmap->entries);
205+
195206
git__free(mailmap);
196207
}
197208

198-
void git_mailmap_resolve(
209+
int git_mailmap_resolve(
199210
const char **name_out, const char **email_out,
200211
const git_mailmap *mailmap,
201212
const char *name, const char *email)
@@ -207,7 +218,7 @@ void git_mailmap_resolve(
207218
*email_out = email;
208219

209220
if (!mailmap)
210-
return;
221+
return 0;
211222

212223
entry = git_mailmap_entry_lookup(mailmap, name, email);
213224
if (entry) {
@@ -216,6 +227,7 @@ void git_mailmap_resolve(
216227
if (entry->real_email)
217228
*email_out = entry->real_email;
218229
}
230+
return 0;
219231
}
220232

221233
const git_mailmap_entry *git_mailmap_entry_lookup(
@@ -229,10 +241,12 @@ const git_mailmap_entry *git_mailmap_entry_lookup(
229241
return NULL;
230242

231243
git_vector_foreach(&mailmap->entries, i, entry) {
232-
if (!git__strcmp(email, entry->replace_email) &&
233-
(!entry->replace_name || !git__strcmp(name, entry->replace_name))) {
234-
return entry;
235-
}
244+
if (git__strcmp(email, entry->replace_email))
245+
continue;
246+
if (entry->replace_name && git__strcmp(name, entry->replace_name))
247+
continue;
248+
249+
return entry;
236250
}
237251

238252
return NULL;

src/signature.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,14 @@ int git_signature_with_mailmap(
111111
git_signature *signature = NULL;
112112
const char *name = NULL;
113113
const char *email = NULL;
114+
int error;
114115

115116
if (source == NULL)
116117
return 0;
117118

118-
git_mailmap_resolve(&name, &email, mailmap, source->name, source->email);
119+
error = git_mailmap_resolve(&name, &email, mailmap, source->name, source->email);
120+
if (error < 0)
121+
return error;
119122

120123
signature = git__calloc(1, sizeof(git_signature));
121124
GITERR_CHECK_ALLOC(signature);

tests/clar_libgit2.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,7 @@ static git_repository *_cl_repo = NULL;
171171

172172
git_repository *cl_git_sandbox_init(const char *sandbox)
173173
{
174-
/* Get the name of the sandbox folder which will be created
175-
*/
174+
/* Get the name of the sandbox folder which will be created */
176175
const char *basename = cl_fixture_basename(sandbox);
177176

178177
/* Copy the whole sandbox folder from our fixtures to our test sandbox

tests/mailmap/basic.c

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,59 @@ const char TEST_MAILMAP[] =
1313
"<email@foo.com> <otheremail@foo.com>\n"
1414
"<email@foo.com> Other Name <yetanotheremail@foo.com>\n";
1515

16+
struct {
17+
const char *real_name;
18+
const char *real_email;
19+
const char *replace_name;
20+
const char *replace_email;
21+
} expected[] = {
22+
{ "Foo bar", "foo@bar.com", NULL, "foo@baz.com" },
23+
{ "Foo bar", "foo@bar.com", NULL, "foo@bal.com" },
24+
{ NULL, "email@foo.com", NULL, "otheremail@foo.com" },
25+
{ NULL, "email@foo.com", "Other Name", "yetanotheremail@foo.com" }
26+
};
27+
1628
void test_mailmap_basic__initialize(void)
1729
{
1830
git_buf buf = GIT_BUF_INIT;
19-
git_buf_attach_notowned(&buf, TEST_MAILMAP, sizeof(TEST_MAILMAP) - 1);
31+
git_buf_attach_notowned(&buf, TEST_MAILMAP, strlen(TEST_MAILMAP));
2032

2133
cl_git_pass(git_mailmap_from_buffer(&mailmap, &buf));
2234
}
2335

2436
void test_mailmap_basic__cleanup(void)
2537
{
26-
if (mailmap) {
27-
git_mailmap_free(mailmap);
28-
mailmap = NULL;
29-
}
38+
git_mailmap_free(mailmap);
39+
mailmap = NULL;
3040
}
3141

3242
void test_mailmap_basic__entry(void)
3343
{
3444
const git_mailmap_entry *entry;
3545

36-
cl_assert(git_mailmap_entry_count(mailmap) == 4);
46+
cl_assert_equal_sz(ARRAY_SIZE(expected), git_mailmap_entry_count(mailmap));
3747

38-
entry = git_mailmap_entry_byindex(mailmap, 0);
39-
cl_assert(entry);
40-
cl_assert(!entry->replace_name);
41-
cl_assert(!git__strcmp(entry->replace_email, "foo@baz.com"));
48+
for (size_t i = 0; i < ARRAY_SIZE(expected); ++i) {
49+
entry = git_mailmap_entry_byindex(mailmap, i);
50+
cl_assert(entry);
51+
cl_assert_equal_s(entry->real_name, expected[i].real_name);
52+
cl_assert_equal_s(entry->real_email, expected[i].real_email);
53+
cl_assert_equal_s(entry->replace_name, expected[i].replace_name);
54+
cl_assert_equal_s(entry->replace_email, expected[i].replace_email);
55+
}
56+
}
4257

43-
entry = git_mailmap_entry_byindex(mailmap, 10000);
58+
void test_mailmap_basic__entry_large_index(void)
59+
{
60+
const git_mailmap_entry *entry =
61+
git_mailmap_entry_byindex(mailmap, 10000);
4462
cl_assert(!entry);
4563
}
4664

4765
void test_mailmap_basic__lookup_not_found(void)
4866
{
4967
const git_mailmap_entry *entry = git_mailmap_entry_lookup(
50-
mailmap,
51-
"Whoever",
52-
"doesnotexist@fo.com");
68+
mailmap, "Whoever", "doesnotexist@fo.com");
5369
cl_assert(!entry);
5470
}
5571

@@ -58,31 +74,32 @@ void test_mailmap_basic__lookup(void)
5874
const git_mailmap_entry *entry = git_mailmap_entry_lookup(
5975
mailmap, "Typoed the name once", "foo@baz.com");
6076
cl_assert(entry);
61-
cl_assert(!git__strcmp(entry->real_name, "Foo bar"));
77+
cl_assert_equal_s(entry->real_name, "Foo bar");
6278
}
6379

6480
void test_mailmap_basic__empty_email_query(void)
6581
{
6682
const char *name;
6783
const char *email;
68-
git_mailmap_resolve(
69-
&name, &email, mailmap, "Author name", "otheremail@foo.com");
70-
cl_assert(!git__strcmp(name, "Author name"));
71-
cl_assert(!git__strcmp(email, "email@foo.com"));
84+
cl_git_pass(git_mailmap_resolve(
85+
&name, &email, mailmap, "Author name", "otheremail@foo.com"));
86+
cl_assert_equal_s(name, "Author name");
87+
cl_assert_equal_s(email, "email@foo.com");
7288
}
7389

7490
void test_mailmap_basic__name_matching(void)
7591
{
7692
const char *name;
7793
const char *email;
78-
git_mailmap_resolve(
79-
&name, &email, mailmap, "Other Name", "yetanotheremail@foo.com");
80-
cl_assert(!git__strcmp(name, "Other Name"));
81-
cl_assert(!git__strcmp(email, "email@foo.com"));
94+
cl_git_pass(git_mailmap_resolve(
95+
&name, &email, mailmap, "Other Name", "yetanotheremail@foo.com"));
96+
97+
cl_assert_equal_s(name, "Other Name");
98+
cl_assert_equal_s(email, "email@foo.com");
8299

83-
git_mailmap_resolve(
100+
cl_git_pass(git_mailmap_resolve(
84101
&name, &email, mailmap,
85-
"Other Name That Doesn't Match", "yetanotheremail@foo.com");
86-
cl_assert(!git__strcmp(name, "Other Name That Doesn't Match"));
87-
cl_assert(!git__strcmp(email, "yetanotheremail@foo.com"));
102+
"Other Name That Doesn't Match", "yetanotheremail@foo.com"));
103+
cl_assert_equal_s(name, "Other Name That Doesn't Match");
104+
cl_assert_equal_s(email, "yetanotheremail@foo.com");
88105
}

tests/mailmap/parsing.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,9 @@ static void check_mailmap_resolve(
4444

4545
/* Check that the resolver behaves correctly */
4646
for (idx = 0; idx < resolved_size; ++idx) {
47-
git_mailmap_resolve(
48-
&resolved_name,
49-
&resolved_email,
50-
mailmap,
51-
resolved[idx].replace_name,
52-
resolved[idx].replace_email);
47+
cl_git_pass(git_mailmap_resolve(
48+
&resolved_name, &resolved_email, mailmap,
49+
resolved[idx].replace_name, resolved[idx].replace_email));
5350
cl_assert_equal_s(resolved_name, resolved[idx].real_name);
5451
cl_assert_equal_s(resolved_email, resolved[idx].real_email);
5552
}
@@ -70,6 +67,27 @@ void test_mailmap_parsing__string(void)
7067
g_mailmap, resolved_untracked, ARRAY_SIZE(resolved_untracked));
7168
}
7269

70+
void test_mailmap_parsing__windows_string(void)
71+
{
72+
git_buf unixbuf = GIT_BUF_INIT;
73+
git_buf winbuf = GIT_BUF_INIT;
74+
75+
/* Parse with windows-style line endings */
76+
git_buf_attach_notowned(&unixbuf, string_mailmap, strlen(string_mailmap));
77+
git_buf_text_lf_to_crlf(&winbuf, &unixbuf);
78+
79+
cl_git_pass(git_mailmap_from_buffer(&g_mailmap, &winbuf));
80+
git_buf_free(winbuf);
81+
82+
/* We should have parsed all of the entries */
83+
check_mailmap_entries(g_mailmap, entries, ARRAY_SIZE(entries));
84+
85+
/* Check that resolving the entries works */
86+
check_mailmap_resolve(g_mailmap, resolved, ARRAY_SIZE(resolved));
87+
check_mailmap_resolve(
88+
g_mailmap, resolved_untracked, ARRAY_SIZE(resolved_untracked));
89+
}
90+
7391
void test_mailmap_parsing__fromrepo(void)
7492
{
7593
g_repo = cl_git_sandbox_init("mailmap");

0 commit comments

Comments
 (0)