source src/mailmap.c
Line | Flow | Count | Block(s) | Source |
---|---|---|---|---|
1 | - | /* | ||
2 | - | * Copyright (C) the libgit2 contributors. All rights reserved. | ||
3 | - | * | ||
4 | - | * This file is part of libgit2, distributed under the GNU GPL v2 with | ||
5 | - | * a Linking Exception. For full terms see the included COPYING file. | ||
6 | - | */ | ||
7 | - | |||
8 | - | #include "mailmap.h" | ||
9 | - | |||
10 | - | #include "common.h" | ||
11 | - | #include "path.h" | ||
12 | - | #include "repository.h" | ||
13 | - | #include "signature.h" | ||
14 | - | #include "git2/config.h" | ||
15 | - | #include "git2/revparse.h" | ||
16 | - | #include "blob.h" | ||
17 | - | #include "parse.h" | ||
18 | - | |||
19 | - | #define MM_FILE ".mailmap" | ||
20 | - | #define MM_FILE_CONFIG "mailmap.file" | ||
21 | - | #define MM_BLOB_CONFIG "mailmap.blob" | ||
22 | - | #define MM_BLOB_DEFAULT "HEAD:" MM_FILE | ||
23 | - | |||
24 | 81 | 2 | static void mailmap_entry_free(git_mailmap_entry *entry) | |
25 | - | { | ||
26 | 81 | 2 | if (!entry) | |
27 | 81 | 3,9 | return; | |
28 | - | |||
29 | 81 | 4 | git__free(entry->real_name); | |
30 | 81 | 5 | git__free(entry->real_email); | |
31 | 81 | 6 | git__free(entry->replace_name); | |
32 | 81 | 7 | git__free(entry->replace_email); | |
33 | 81 | 8 | git__free(entry); | |
34 | - | } | ||
35 | - | |||
36 | - | /* | ||
37 | - | * First we sort by replace_email, then replace_name (if present). | ||
38 | - | * Entries with names are greater than entries without. | ||
39 | - | */ | ||
40 | 500 | 2 | static int mailmap_entry_cmp(const void *a_raw, const void *b_raw) | |
41 | - | { | ||
42 | 500 | 2 | const git_mailmap_entry *a = (const git_mailmap_entry *)a_raw; | |
43 | 500 | 2 | const git_mailmap_entry *b = (const git_mailmap_entry *)b_raw; | |
44 | - | int cmp; | ||
45 | - | |||
46 | 500 | 2-6 | assert(a && b && a->replace_email && b->replace_email); | |
47 | - | |||
48 | 500 | 7 | cmp = git__strcmp(a->replace_email, b->replace_email); | |
49 | 500 | 7 | if (cmp) | |
50 | 299 | 8 | return cmp; | |
51 | - | |||
52 | - | /* NULL replace_names are less than not-NULL ones */ | ||
53 | 201 | 9,10 | if (a->replace_name == NULL || b->replace_name == NULL) | |
54 | 180 | 11 | return (int)(a->replace_name != NULL) - (int)(b->replace_name != NULL); | |
55 | - | |||
56 | 21 | 12 | return git__strcmp(a->replace_name, b->replace_name); | |
57 | - | } | ||
58 | - | |||
59 | - | /* Replace the old entry with the new on duplicate. */ | ||
60 | 2 | 2 | static int mailmap_entry_replace(void **old_raw, void *new_raw) | |
61 | - | { | ||
62 | 2 | 2 | mailmap_entry_free((git_mailmap_entry *)*old_raw); | |
63 | 2 | 3 | *old_raw = new_raw; | |
64 | 2 | 3 | return GIT_EEXISTS; | |
65 | - | } | ||
66 | - | |||
67 | - | /* Check if we're at the end of line, w/ comments */ | ||
68 | 334 | 2 | static bool is_eol(git_parse_ctx *ctx) | |
69 | - | { | ||
70 | - | char c; | ||
71 | 334 | 2 | return git_parse_peek(&c, ctx, GIT_PARSE_PEEK_SKIP_WHITESPACE) < 0 || c == '#'; | |
72 | - | } | ||
73 | - | |||
74 | 291 | 2 | static int advance_until( | |
75 | - | const char **start, size_t *len, git_parse_ctx *ctx, char needle) | ||
76 | - | { | ||
77 | 291 | 2 | *start = ctx->line; | |
78 | 3423 | 2,4-6 | while (ctx->line_len > 0 && *ctx->line != '#' && *ctx->line != needle) | |
79 | 3132 | 3 | git_parse_advance_chars(ctx, 1); | |
80 | - | |||
81 | 291 | 7,8 | if (ctx->line_len == 0 || *ctx->line == '#') | |
82 | 5 | 9 | return -1; /* end of line */ | |
83 | - | |||
84 | 286 | 10 | *len = ctx->line - *start; | |
85 | 286 | 10 | git_parse_advance_chars(ctx, 1); /* advance past needle */ | |
86 | 286 | 11 | return 0; | |
87 | - | } | ||
88 | - | |||
89 | - | /* | ||
90 | - | * Parse a single entry from a mailmap file. | ||
91 | - | * | ||
92 | - | * The output git_bufs will be non-owning, and should be copied before being | ||
93 | - | * persisted. | ||
94 | - | */ | ||
95 | 172 | 2 | static int parse_mailmap_entry( | |
96 | - | git_buf *real_name, git_buf *real_email, | ||
97 | - | git_buf *replace_name, git_buf *replace_email, | ||
98 | - | git_parse_ctx *ctx) | ||
99 | - | { | ||
100 | - | const char *start; | ||
101 | - | size_t len; | ||
102 | - | |||
103 | 172 | 2 | git_buf_clear(real_name); | |
104 | 172 | 3 | git_buf_clear(real_email); | |
105 | 172 | 4 | git_buf_clear(replace_name); | |
106 | 172 | 5 | git_buf_clear(replace_email); | |
107 | - | |||
108 | 172 | 6 | git_parse_advance_ws(ctx); | |
109 | 172 | 7,8 | if (is_eol(ctx)) | |
110 | 86 | 9 | return -1; /* blank line */ | |
111 | - | |||
112 | - | /* Parse the real name */ | ||
113 | 86 | 10,11 | if (advance_until(&start, &len, ctx, '<') < 0) | |
114 | 5 | 12 | return -1; | |
115 | - | |||
116 | 81 | 13 | git_buf_attach_notowned(real_name, start, len); | |
117 | 81 | 14 | git_buf_rtrim(real_name); | |
118 | - | |||
119 | - | /* | ||
120 | - | * If this is the last email in the line, this is the email to replace, | ||
121 | - | * otherwise, it's the real email. | ||
122 | - | */ | ||
123 | 81 | 15,16 | if (advance_until(&start, &len, ctx, '>') < 0) | |
124 | ##### | 17 | return -1; | |
125 | - | |||
126 | - | /* If we aren't at the end of the line, parse a second name and email */ | ||
127 | 81 | 18,19 | if (!is_eol(ctx)) { | |
128 | 62 | 20 | git_buf_attach_notowned(real_email, start, len); | |
129 | - | |||
130 | 62 | 21 | git_parse_advance_ws(ctx); | |
131 | 62 | 22,23 | if (advance_until(&start, &len, ctx, '<') < 0) | |
132 | ##### | 24 | return -1; | |
133 | 62 | 25 | git_buf_attach_notowned(replace_name, start, len); | |
134 | 62 | 26 | git_buf_rtrim(replace_name); | |
135 | - | |||
136 | 62 | 27,28 | if (advance_until(&start, &len, ctx, '>') < 0) | |
137 | ##### | 29 | return -1; | |
138 | - | } | ||
139 | - | |||
140 | 81 | 30 | git_buf_attach_notowned(replace_email, start, len); | |
141 | - | |||
142 | 81 | 31,32 | if (!is_eol(ctx)) | |
143 | ##### | 33 | return -1; | |
144 | - | |||
145 | 81 | 34 | return 0; | |
146 | - | } | ||
147 | - | |||
148 | 13 | 2 | int git_mailmap_new(git_mailmap **out) | |
149 | - | { | ||
150 | - | int error; | ||
151 | 13 | 2 | git_mailmap *mm = git__calloc(1, sizeof(git_mailmap)); | |
152 | 13 | 3,4 | GIT_ERROR_CHECK_ALLOC(mm); | |
153 | - | |||
154 | 13 | 5 | error = git_vector_init(&mm->entries, 0, mailmap_entry_cmp); | |
155 | 13 | 6 | if (error < 0) { | |
156 | ##### | 7 | git__free(mm); | |
157 | ##### | 8 | return error; | |
158 | - | } | ||
159 | 13 | 9 | *out = mm; | |
160 | 13 | 9 | return 0; | |
161 | - | } | ||
162 | - | |||
163 | 43 | 2 | void git_mailmap_free(git_mailmap *mm) | |
164 | - | { | ||
165 | - | size_t idx; | ||
166 | - | git_mailmap_entry *entry; | ||
167 | 43 | 2 | if (!mm) | |
168 | 43 | 3,11 | return; | |
169 | - | |||
170 | 92 | 4,6-8 | git_vector_foreach(&mm->entries, idx, entry) | |
171 | 79 | 5 | mailmap_entry_free(entry); | |
172 | - | |||
173 | 13 | 9 | git_vector_free(&mm->entries); | |
174 | 13 | 10 | git__free(mm); | |
175 | - | } | ||
176 | - | |||
177 | 81 | 2 | static int mailmap_add_entry_unterminated( | |
178 | - | git_mailmap *mm, | ||
179 | - | const char *real_name, size_t real_name_size, | ||
180 | - | const char *real_email, size_t real_email_size, | ||
181 | - | const char *replace_name, size_t replace_name_size, | ||
182 | - | const char *replace_email, size_t replace_email_size) | ||
183 | - | { | ||
184 | - | int error; | ||
185 | 81 | 2 | git_mailmap_entry *entry = git__calloc(1, sizeof(git_mailmap_entry)); | |
186 | 81 | 3,4 | GIT_ERROR_CHECK_ALLOC(entry); | |
187 | - | |||
188 | 81 | 5-8 | assert(mm && replace_email && *replace_email); | |
189 | - | |||
190 | 81 | 9 | if (real_name_size > 0) { | |
191 | 57 | 10 | entry->real_name = git__substrdup(real_name, real_name_size); | |
192 | 57 | 11,12 | GIT_ERROR_CHECK_ALLOC(entry->real_name); | |
193 | - | } | ||
194 | 81 | 13 | if (real_email_size > 0) { | |
195 | 62 | 14 | entry->real_email = git__substrdup(real_email, real_email_size); | |
196 | 62 | 15,16 | GIT_ERROR_CHECK_ALLOC(entry->real_email); | |
197 | - | } | ||
198 | 81 | 17 | if (replace_name_size > 0) { | |
199 | 26 | 18 | entry->replace_name = git__substrdup(replace_name, replace_name_size); | |
200 | 26 | 19,20 | GIT_ERROR_CHECK_ALLOC(entry->replace_name); | |
201 | - | } | ||
202 | 81 | 21 | entry->replace_email = git__substrdup(replace_email, replace_email_size); | |
203 | 81 | 22,23 | GIT_ERROR_CHECK_ALLOC(entry->replace_email); | |
204 | - | |||
205 | 81 | 24 | error = git_vector_insert_sorted(&mm->entries, entry, mailmap_entry_replace); | |
206 | 81 | 25 | if (error == GIT_EEXISTS) | |
207 | 2 | 26 | error = GIT_OK; | |
208 | 79 | 27 | else if (error < 0) | |
209 | ##### | 28 | mailmap_entry_free(entry); | |
210 | - | |||
211 | 81 | 29 | return error; | |
212 | - | } | ||
213 | - | |||
214 | ##### | 2 | int git_mailmap_add_entry( | |
215 | - | git_mailmap *mm, const char *real_name, const char *real_email, | ||
216 | - | const char *replace_name, const char *replace_email) | ||
217 | - | { | ||
218 | ##### | 2 | return mailmap_add_entry_unterminated( | |
219 | - | mm, | ||
220 | - | real_name, real_name ? strlen(real_name) : 0, | ||
221 | - | real_email, real_email ? strlen(real_email) : 0, | ||
222 | - | replace_name, replace_name ? strlen(replace_name) : 0, | ||
223 | - | replace_email, strlen(replace_email)); | ||
224 | - | } | ||
225 | - | |||
226 | 15 | 2 | static int mailmap_add_buffer(git_mailmap *mm, const char *buf, size_t len) | |
227 | - | { | ||
228 | 15 | 2 | int error = 0; | |
229 | - | git_parse_ctx ctx; | ||
230 | - | |||
231 | - | /* Scratch buffers containing the real parsed names & emails */ | ||
232 | 15 | 2 | git_buf real_name = GIT_BUF_INIT; | |
233 | 15 | 2 | git_buf real_email = GIT_BUF_INIT; | |
234 | 15 | 2 | git_buf replace_name = GIT_BUF_INIT; | |
235 | 15 | 2 | git_buf replace_email = GIT_BUF_INIT; | |
236 | - | |||
237 | - | /* Buffers may not contain '\0's. */ | ||
238 | 15 | 2 | if (memchr(buf, '\0', len) != NULL) | |
239 | ##### | 3 | return -1; | |
240 | - | |||
241 | 15 | 4 | git_parse_ctx_init(&ctx, buf, len); | |
242 | - | |||
243 | - | /* Run the parser */ | ||
244 | 187 | 5,14 | while (ctx.remain_len > 0) { | |
245 | 172 | 6 | error = parse_mailmap_entry( | |
246 | - | &real_name, &real_email, &replace_name, &replace_email, &ctx); | ||
247 | 172 | 7 | if (error < 0) { | |
248 | 91 | 8 | error = 0; /* Skip lines which don't contain a valid entry */ | |
249 | 91 | 8 | git_parse_advance_line(&ctx); | |
250 | 91 | 9 | continue; /* TODO: warn */ | |
251 | - | } | ||
252 | - | |||
253 | - | /* NOTE: Can't use add_entry(...) as our buffers aren't terminated */ | ||
254 | 81 | 10,10,10,10,10 | error = mailmap_add_entry_unterminated( | |
255 | 81 | 10,10 | mm, real_name.ptr, real_name.size, real_email.ptr, real_email.size, | |
256 | 81 | 10,10 | replace_name.ptr, replace_name.size, replace_email.ptr, replace_email.size); | |
257 | 81 | 11 | if (error < 0) | |
258 | ##### | 12 | goto cleanup; | |
259 | - | |||
260 | 81 | 13 | error = 0; | |
261 | - | } | ||
262 | - | |||
263 | - | cleanup: | ||
264 | 15 | 15 | git_buf_dispose(&real_name); | |
265 | 15 | 16 | git_buf_dispose(&real_email); | |
266 | 15 | 17 | git_buf_dispose(&replace_name); | |
267 | 15 | 18 | git_buf_dispose(&replace_email); | |
268 | 15 | 19 | return error; | |
269 | - | } | ||
270 | - | |||
271 | 7 | 2 | int git_mailmap_from_buffer(git_mailmap **out, const char *data, size_t len) | |
272 | - | { | ||
273 | 7 | 2 | int error = git_mailmap_new(out); | |
274 | 7 | 3 | if (error < 0) | |
275 | ##### | 4 | return error; | |
276 | - | |||
277 | 7 | 5 | error = mailmap_add_buffer(*out, data, len); | |
278 | 7 | 6 | if (error < 0) { | |
279 | ##### | 7 | git_mailmap_free(*out); | |
280 | ##### | 8 | *out = NULL; | |
281 | - | } | ||
282 | 7 | 9 | return error; | |
283 | - | } | ||
284 | - | |||
285 | 3 | 2 | static int mailmap_add_blob( | |
286 | - | git_mailmap *mm, git_repository *repo, const char *rev) | ||
287 | - | { | ||
288 | 3 | 2 | git_object *object = NULL; | |
289 | 3 | 2 | git_blob *blob = NULL; | |
290 | 3 | 2 | git_buf content = GIT_BUF_INIT; | |
291 | - | int error; | ||
292 | - | |||
293 | 3 | 2-4 | assert(mm && repo); | |
294 | - | |||
295 | 3 | 5 | error = git_revparse_single(&object, repo, rev); | |
296 | 3 | 6 | if (error < 0) | |
297 | ##### | 7 | goto cleanup; | |
298 | - | |||
299 | 3 | 8 | error = git_object_peel((git_object **)&blob, object, GIT_OBJECT_BLOB); | |
300 | 3 | 9 | if (error < 0) | |
301 | ##### | 10 | goto cleanup; | |
302 | - | |||
303 | 3 | 11 | error = git_blob__getbuf(&content, blob); | |
304 | 3 | 12 | if (error < 0) | |
305 | ##### | 13 | goto cleanup; | |
306 | - | |||
307 | 3 | 14 | error = mailmap_add_buffer(mm, content.ptr, content.size); | |
308 | 3 | 15 | if (error < 0) | |
309 | ##### | 16 | goto cleanup; | |
310 | - | |||
311 | - | cleanup: | ||
312 | 3 | 17 | git_buf_dispose(&content); | |
313 | 3 | 18 | git_blob_free(blob); | |
314 | 3 | 19 | git_object_free(object); | |
315 | 3 | 20 | return error; | |
316 | - | } | ||
317 | - | |||
318 | 5 | 2 | static int mailmap_add_file_ondisk( | |
319 | - | git_mailmap *mm, const char *path, git_repository *repo) | ||
320 | - | { | ||
321 | 5 | 2-4 | const char *base = repo ? git_repository_workdir(repo) : NULL; | |
322 | 5 | 5 | git_buf fullpath = GIT_BUF_INIT; | |
323 | 5 | 5 | git_buf content = GIT_BUF_INIT; | |
324 | - | int error; | ||
325 | - | |||
326 | 5 | 5 | error = git_path_join_unrooted(&fullpath, path, base, NULL); | |
327 | 5 | 6 | if (error < 0) | |
328 | ##### | 7 | goto cleanup; | |
329 | - | |||
330 | 5 | 8 | error = git_futils_readbuffer(&content, fullpath.ptr); | |
331 | 5 | 9 | if (error < 0) | |
332 | ##### | 10 | goto cleanup; | |
333 | - | |||
334 | 5 | 11 | error = mailmap_add_buffer(mm, content.ptr, content.size); | |
335 | 5 | 12 | if (error < 0) | |
336 | ##### | 13 | goto cleanup; | |
337 | - | |||
338 | - | cleanup: | ||
339 | 5 | 14 | git_buf_dispose(&fullpath); | |
340 | 5 | 15 | git_buf_dispose(&content); | |
341 | 5 | 16 | return error; | |
342 | - | } | ||
343 | - | |||
344 | - | /* NOTE: Only expose with an error return, currently never errors */ | ||
345 | 6 | 2 | static void mailmap_add_from_repository(git_mailmap *mm, git_repository *repo) | |
346 | - | { | ||
347 | 6 | 2 | git_config *config = NULL; | |
348 | 6 | 2 | git_buf rev_buf = GIT_BUF_INIT; | |
349 | 6 | 2 | git_buf path_buf = GIT_BUF_INIT; | |
350 | 6 | 2 | const char *rev = NULL; | |
351 | 6 | 2 | const char *path = NULL; | |
352 | - | |||
353 | 6 | 2-4 | assert(mm && repo); | |
354 | - | |||
355 | - | /* If we're in a bare repo, default blob to 'HEAD:.mailmap' */ | ||
356 | 6 | 5 | if (repo->is_bare) | |
357 | 2 | 6 | rev = MM_BLOB_DEFAULT; | |
358 | - | |||
359 | - | /* Try to load 'mailmap.file' and 'mailmap.blob' cfgs from the repo */ | ||
360 | 6 | 7,8 | if (git_repository_config(&config, repo) == 0) { | |
361 | 6 | 9,10 | if (git_config_get_string_buf(&rev_buf, config, MM_BLOB_CONFIG) == 0) | |
362 | 2 | 11 | rev = rev_buf.ptr; | |
363 | 6 | 12,13 | if (git_config_get_path(&path_buf, config, MM_FILE_CONFIG) == 0) | |
364 | 1 | 14 | path = path_buf.ptr; | |
365 | - | } | ||
366 | - | |||
367 | - | /* | ||
368 | - | * Load mailmap files in order, overriding previous entries with new ones. | ||
369 | - | * 1. The '.mailmap' file in the repository's workdir root, | ||
370 | - | * 2. The blob described by the 'mailmap.blob' config (default HEAD:.mailmap), | ||
371 | - | * 3. The file described by the 'mailmap.file' config. | ||
372 | - | * | ||
373 | - | * We ignore errors from these loads, as these files may not exist, or may | ||
374 | - | * contain invalid information, and we don't want to report that error. | ||
375 | - | * | ||
376 | - | * XXX: Warn? | ||
377 | - | */ | ||
378 | 6 | 15 | if (!repo->is_bare) | |
379 | 4 | 16 | mailmap_add_file_ondisk(mm, MM_FILE, repo); | |
380 | 6 | 17 | if (rev != NULL) | |
381 | 3 | 18 | mailmap_add_blob(mm, repo, rev); | |
382 | 6 | 19 | if (path != NULL) | |
383 | 1 | 20 | mailmap_add_file_ondisk(mm, path, repo); | |
384 | - | |||
385 | 6 | 21 | git_buf_dispose(&rev_buf); | |
386 | 6 | 22 | git_buf_dispose(&path_buf); | |
387 | 6 | 23 | git_config_free(config); | |
388 | 6 | 24 | } | |
389 | - | |||
390 | 6 | 2 | int git_mailmap_from_repository(git_mailmap **out, git_repository *repo) | |
391 | - | { | ||
392 | 6 | 2 | int error = git_mailmap_new(out); | |
393 | 6 | 3 | if (error < 0) | |
394 | ##### | 4 | return error; | |
395 | 6 | 5 | mailmap_add_from_repository(*out, repo); | |
396 | 6 | 6 | return 0; | |
397 | - | } | ||
398 | - | |||
399 | 290 | 2 | const git_mailmap_entry *git_mailmap_entry_lookup( | |
400 | - | const git_mailmap *mm, const char *name, const char *email) | ||
401 | - | { | ||
402 | - | int error; | ||
403 | 290 | 2 | ssize_t fallback = -1; | |
404 | - | size_t idx; | ||
405 | - | git_mailmap_entry *entry; | ||
406 | - | |||
407 | - | /* The lookup needle we want to use only sets the replace_email. */ | ||
408 | 290 | 2 | git_mailmap_entry needle = { NULL }; | |
409 | 290 | 2 | needle.replace_email = (char *)email; | |
410 | - | |||
411 | 290 | 2,3 | assert(email); | |
412 | - | |||
413 | 290 | 4 | if (!mm) | |
414 | 163 | 5 | return NULL; | |
415 | - | |||
416 | - | /* | ||
417 | - | * We want to find the place to start looking. so we do a binary search for | ||
418 | - | * the "fallback" nameless entry. If we find it, we advance past it and record | ||
419 | - | * the index. | ||
420 | - | */ | ||
421 | 127 | 6 | error = git_vector_bsearch(&idx, (git_vector *)&mm->entries, &needle); | |
422 | 127 | 7 | if (error >= 0) | |
423 | 66 | 8 | fallback = idx++; | |
424 | 61 | 9 | else if (error != GIT_ENOTFOUND) | |
425 | ##### | 10 | return NULL; | |
426 | - | |||
427 | - | /* do a linear search for an exact match */ | ||
428 | 182 | 11,20-22 | for (; idx < git_vector_length(&mm->entries); ++idx) { | |
429 | 171 | 12 | entry = git_vector_get(&mm->entries, idx); | |
430 | - | |||
431 | 171 | 13 | if (git__strcmp(entry->replace_email, email)) | |
432 | 81 | 14 | break; /* it's a different email, so we're done looking */ | |
433 | - | |||
434 | 90 | 15,16 | assert(entry->replace_name); /* should be specific */ | |
435 | 90 | 17,18 | if (!name || !git__strcmp(entry->replace_name, name)) | |
436 | 35 | 19 | return entry; | |
437 | - | } | ||
438 | - | |||
439 | 92 | 23 | if (fallback < 0) | |
440 | 26 | 24 | return NULL; /* no fallback */ | |
441 | 66 | 25 | return git_vector_get(&mm->entries, fallback); | |
442 | - | } | ||
443 | - | |||
444 | 253 | 2 | int git_mailmap_resolve( | |
445 | - | const char **real_name, const char **real_email, | ||
446 | - | const git_mailmap *mailmap, | ||
447 | - | const char *name, const char *email) | ||
448 | - | { | ||
449 | 253 | 2 | const git_mailmap_entry *entry = NULL; | |
450 | 253 | 2-4 | assert(name && email); | |
451 | - | |||
452 | 253 | 5 | *real_name = name; | |
453 | 253 | 5 | *real_email = email; | |
454 | - | |||
455 | 253 | 5,6 | if ((entry = git_mailmap_entry_lookup(mailmap, name, email))) { | |
456 | 65 | 7 | if (entry->real_name) | |
457 | 42 | 8 | *real_name = entry->real_name; | |
458 | 65 | 9 | if (entry->real_email) | |
459 | 51 | 10 | *real_email = entry->real_email; | |
460 | - | } | ||
461 | 253 | 11 | return 0; | |
462 | - | } | ||
463 | - | |||
464 | 173 | 2 | int git_mailmap_resolve_signature( | |
465 | - | git_signature **out, const git_mailmap *mailmap, const git_signature *sig) | ||
466 | - | { | ||
467 | 173 | 2 | const char *name = NULL; | |
468 | 173 | 2 | const char *email = NULL; | |
469 | - | int error; | ||
470 | - | |||
471 | 173 | 2 | if (!sig) | |
472 | ##### | 3 | return 0; | |
473 | - | |||
474 | 173 | 4 | error = git_mailmap_resolve(&name, &email, mailmap, sig->name, sig->email); | |
475 | 173 | 5 | if (error < 0) | |
476 | ##### | 6 | return error; | |
477 | - | |||
478 | 173 | 7 | error = git_signature_new(out, name, email, sig->when.time, sig->when.offset); | |
479 | 173 | 8 | if (error < 0) | |
480 | ##### | 9 | return error; | |
481 | - | |||
482 | - | /* Copy over the sign, as git_signature_new doesn't let you pass it. */ | ||
483 | 173 | 10 | (*out)->when.sign = sig->when.sign; | |
484 | 173 | 10 | return 0; | |
485 | - | } |