From 7a169390b89ad2182f9d5a31851270f0bc37423a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 15 Mar 2018 16:34:30 +0100 Subject: mailmap: WIP mailmap support --- include/git2.h | 1 + include/git2/mailmap.h | 39 ++++++++++ src/mailmap.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 248 insertions(+) create mode 100644 include/git2/mailmap.h create mode 100644 src/mailmap.c diff --git a/include/git2.h b/include/git2.h index 5f6104ef7..e182ce924 100644 --- a/include/git2.h +++ b/include/git2.h @@ -29,6 +29,7 @@ #include "git2/ignore.h" #include "git2/index.h" #include "git2/indexer.h" +#include "git2/mailmap.h" #include "git2/merge.h" #include "git2/message.h" #include "git2/net.h" diff --git a/include/git2/mailmap.h b/include/git2/mailmap.h new file mode 100644 index 000000000..bb126d14e --- /dev/null +++ b/include/git2/mailmap.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_mailmap_h__ +#define INCLUDE_mailmap_h__ + +#include "common.h" +#include "repository.h" + +/** + * @file git2/mailmap.h + * @brief Mailmap access subroutines. + * @defgroup git_rebase Git merge routines + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +typedef struct git_mailmap git_mailmap; + +struct git_mailmap_entry { + const char* name; + const char* email; +}; + +GIT_EXTERN(int) git_mailmap_create(git_mailmap**, git_repository*); +GIT_EXTERN(void) git_mailmap_free(git_mailmap*); +GIT_EXTERN(struct git_mailmap_entry) git_mailmap_lookup( + git_mailmap* map, + const char* name, + const char* email); + +/** @} */ +GIT_END_DECL + +#endif diff --git a/src/mailmap.c b/src/mailmap.c new file mode 100644 index 000000000..26b5f8b26 --- /dev/null +++ b/src/mailmap.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "git2/mailmap.h" + +#include "blob.h" +#include "commit.h" +#include "git2/common.h" +#include "git2/repository.h" +#include "git2/revparse.h" +#include "git2/sys/commit.h" + +struct mailmap_entry { + char* to_name; + char* to_email; + char* from_name; + char* from_email; +}; + +struct git_mailmap { + git_vector lines; +}; + +// Returns -1 on failure, length of the string scanned successfully on success, +// guaranteed to be less that `length`. +ssize_t parse_name_and_email( + const char *line, + size_t length, + const char** name, + size_t* name_len, + const char** email, + size_t* email_len, + bool allow_empty_email) +{ + const char* email_start; + const char* email_end; + const char* name_start; + const char* name_end; + + email_start = memchr(line, '<', length); + if (!email_start) + return -1; + email_end = memchr(email_start, '>', length - (email_start - line)); + if (!email_end) + return -1; + assert(email_end > email_start); + + *email_len = email_end - email_start - 1; + *email = email_start + 1; + if (*email == email_end && !allow_empty_email) + return -1; + + // Now look for the name. + name_start = line; + while (name_start < email_start && isspace(*name_start)) + ++name_start; + + *name = name_start; + + name_end = email_start; + while (name_end > name_start && isspace(*(name_end - 1))) + name_end--; + + assert(name_end >= name_start); + *name_len = name_end - name_start; + + return email_end - line; +} + +static void git_mailmap_parse_line( + git_mailmap* mailmap, + const char* contents, + size_t size) +{ + struct mailmap_entry* entry; + + const char* to_name; + size_t to_name_length; + + const char* to_email; + size_t to_email_length; + + const char* from_name; + size_t from_name_length; + + const char* from_email; + size_t from_email_length; + + ssize_t ret; + + if (!size) + return; + if (contents[0] == '#') + return; + + ret = parse_name_and_email( + contents, + size, + &to_name, + &to_name_length, + &to_email, + &to_email_length, + false); + if (ret < 0) + return; + + ret = parse_name_and_email( + contents + ret + 1, + size - ret - 1, + &from_name, + &from_name_length, + &from_email, + &from_email_length, + true); + if (ret < 0) + return; + + entry = git__malloc(sizeof(struct mailmap_entry)); + + entry->to_name = git__strndup(to_name, to_name_length); + entry->to_email = git__strndup(to_email, to_email_length); + entry->from_name = git__strndup(from_name, from_name_length); + entry->from_email = git__strndup(from_email, from_email_length); + + printf("%s <%s> \"%s\" <%s>\n", + entry->to_name, + entry->to_email, + entry->from_name, + entry->from_email); + + git_vector_insert(&mailmap->lines, entry); +} + +static void git_mailmap_parse( + git_mailmap* mailmap, + const char* contents, + size_t size) +{ + size_t start = 0; + size_t i; + for (i = 0; i < size; ++i) { + if (contents[i] != '\n') + continue; + git_mailmap_parse_line(mailmap, contents + start, i - start); + start = i + 1; + } +} + +int git_mailmap_create(git_mailmap** mailmap, git_repository* repo) +{ + git_commit* head = NULL; + git_blob* mailmap_blob = NULL; + git_off_t size = 0; + const char* contents = NULL; + int ret; + + *mailmap = git__malloc(sizeof(struct git_mailmap)); + git_vector_init(&(*mailmap)->lines, 0, NULL); + + ret = git_revparse_single((git_object **)&head, repo, "HEAD"); + if (ret) + goto error; + + ret = git_object_lookup_bypath( + (git_object**) &mailmap_blob, + (const git_object*) head, + ".mailmap", + GIT_OBJ_BLOB); + if (ret) + goto error; + + contents = git_blob_rawcontent(mailmap_blob); + size = git_blob_rawsize(mailmap_blob); + + git_mailmap_parse(*mailmap, contents, size); + + return 0; + +error: + assert(ret); + + if (mailmap_blob) + git_blob_free(mailmap_blob); + if (head) + git_commit_free(head); + git_mailmap_free(*mailmap); + return ret; +} + +void git_mailmap_free(struct git_mailmap* mailmap) +{ + size_t i; + struct mailmap_entry* line; + git_vector_foreach(&mailmap->lines, i, line) { + git__free((char*)line->to_name); + git__free((char*)line->to_email); + git__free((char*)line->from_name); + git__free((char*)line->from_email); + git__free(line); + } + + git_vector_clear(&mailmap->lines); + git__free(mailmap); +} -- cgit v1.2.1 From 49620359f22c952021645b70480f1f3dc2e74440 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sat, 17 Mar 2018 02:29:41 -0400 Subject: mailmap: Clean up mailmap parser, and finish API --- include/git2/mailmap.h | 119 ++++++++++++-- src/mailmap.c | 431 +++++++++++++++++++++++++++++++------------------ 2 files changed, 377 insertions(+), 173 deletions(-) diff --git a/include/git2/mailmap.h b/include/git2/mailmap.h index bb126d14e..0f582c2a3 100644 --- a/include/git2/mailmap.h +++ b/include/git2/mailmap.h @@ -4,16 +4,16 @@ * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. */ -#ifndef INCLUDE_mailmap_h__ -#define INCLUDE_mailmap_h__ +#ifndef INCLUDE_git_mailmap_h__ +#define INCLUDE_git_mailmap_h__ #include "common.h" -#include "repository.h" +#include "tree.h" /** * @file git2/mailmap.h - * @brief Mailmap access subroutines. - * @defgroup git_rebase Git merge routines + * @brief Mailmap parsing routines + * @defgroup git_mailmap Git mailmap routines * @ingroup Git * @{ */ @@ -21,19 +21,106 @@ GIT_BEGIN_DECL typedef struct git_mailmap git_mailmap; -struct git_mailmap_entry { - const char* name; - const char* email; -}; +/** + * A single entry parsed from a mailmap. + */ +typedef struct git_mailmap_entry { + const char *real_name; /**< the real name (may be NULL) */ + const char *real_email; /**< the real email (may be NULL) */ + const char *replace_name; /**< the name to replace (may be NULL) */ + const char *replace_email; /**< the email to replace */ +} git_mailmap_entry; + +/** + * Create a mailmap object by parsing a mailmap file. + * + * The mailmap must be freed with 'git_mailmap_free'. + * + * @param out Pointer to store the mailmap + * @param data raw data buffer to parse + * @param size size of the raw data buffer + * @return 0 on success + */ +GIT_EXTERN(int) git_mailmap_parse( + git_mailmap **out, + const char *data, + size_t size); + +/** + * Create a mailmap object by parsing the ".mailmap" file in the tree root. + * + * The mailmap must be freed with 'git_mailmap_free'. + * + * @param out pointer to store the mailmap + * @param treeish root object that can be peeled to a tree + * @return 0 on success; GIT_ENOTFOUND if .mailmap does not exist. + */ +GIT_EXTERN(int) git_mailmap_from_tree( + git_mailmap **out, + const git_object *treeish); -GIT_EXTERN(int) git_mailmap_create(git_mailmap**, git_repository*); -GIT_EXTERN(void) git_mailmap_free(git_mailmap*); -GIT_EXTERN(struct git_mailmap_entry) git_mailmap_lookup( - git_mailmap* map, - const char* name, - const char* email); +/** + * Create a mailmap object by parsing the ".mailmap" file in the repository's + * HEAD's tree root. + * + * The mailmap must be freed with 'git_mailmap_free'. + * + * @param out pointer to store the mailmap + * @param repo repository to find the .mailmap in + * @return 0 on success; GIT_ENOTFOUND if .mailmap does not exist. + */ +GIT_EXTERN(int) git_mailmap_from_repo( + git_mailmap **out, + git_repository *repo); + +/** + * Free a mailmap created by 'git_mailmap_parse', 'git_mailmap_from_tree' or + * 'git_mailmap_from_repo'. + */ +GIT_EXTERN(void) git_mailmap_free(git_mailmap *mailmap); + +/** + * Resolve a name and email to the corresponding real name and email. + * + * @param name_out either 'name', or the real name to use. + * You should NOT free this value. + * @param email_out either 'email' or the real email to use, + * You should NOT free this value. + * @param mailmap the mailmap to perform the lookup in. + * @param name the name to resolve. + * @param email the email to resolve. + */ +GIT_EXTERN(void) git_mailmap_resolve( + const char **name_out, + const char **email_out, + git_mailmap *mailmap, + const char *name, + const char *email); + +/** + * Get the number of mailmap entries. + */ +GIT_EXTERN(size_t) git_mailmap_entry_count(git_mailmap *mailmap); + +/** + * Lookup a mailmap entry by index. + * + * Do not free the mailmap entry, it is owned by the mailmap. + */ +GIT_EXTERN(git_mailmap_entry *) git_mailmap_entry_byindex( + git_mailmap *mailmap, + size_t idx); + +/** + * Lookup a mailmap entry by name/email pair. + * + * Do not free the mailmap entry, it is owned by the mailmap. + */ +GIT_EXTERN(git_mailmap_entry *) git_mailmap_entry_lookup( + git_mailmap *mailmap, + const char *name, + const char *email); /** @} */ GIT_END_DECL - #endif diff --git a/src/mailmap.c b/src/mailmap.c index 26b5f8b26..9e4d57468 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -14,195 +14,312 @@ #include "git2/revparse.h" #include "git2/sys/commit.h" -struct mailmap_entry { - char* to_name; - char* to_email; - char* from_name; - char* from_email; -}; +/** + * Helper type and methods for the mailmap parser + */ +typedef struct char_range { + const char *p; + size_t len; +} char_range; + +static const char_range NULL_RANGE = {0}; + +/* Split a range at the first instance of 'c'. Returns whether 'c' was found */ +static bool range_split( + char_range range, + char c, + char_range *before, + char_range *after) +{ + const char *off; + + *before = *after = NULL_RANGE; + before->p = range.p; + off = memchr(range.p, c, range.len); + if (!off) { + before->len = range.len; + return false; + } + + before->len = off - range.p; + after->p = off + 1; + after->len = (range.p + range.len) - after->p; + return true; +} + +/* Trim whitespace from the beginning and end of the range */ +static void range_trim(char_range *range) { + while (range->len > 0 && git__isspace(range->p[0])) { + ++range->p; + --range->len; + } + while (range->len > 0 && git__isspace(range->p[range->len - 1])) + --range->len; +} + +/** + * If `buf` is not NULL, copies range into it with a '\0', and bumps buf. + * If `size` is not NULL, adds the number of bytes to be written to it. + * returns a pointer to the copied string, or NULL. + */ +static const char *range_copyz(char **buf, size_t *size, char_range src) +{ + char *s = NULL; + if (src.p == NULL) + return NULL; + + if (size) + *size += src.len + 1; + + if (buf) { + s = *buf; + memcpy(s, src.p, src.len); + s[src.len] = '\0'; + *buf += src.len + 1; + } + return s; +} struct git_mailmap { - git_vector lines; + git_vector entries; }; -// Returns -1 on failure, length of the string scanned successfully on success, -// guaranteed to be less that `length`. -ssize_t parse_name_and_email( - const char *line, - size_t length, - const char** name, - size_t* name_len, - const char** email, - size_t* email_len, - bool allow_empty_email) +/** + * Parse a single entry out of a mailmap file. + * Advances the `file` range past the parsed entry. + */ +static int git_mailmap_parse_single( + char_range *file, + bool *found, + char_range *real_name, + char_range *real_email, + char_range *replace_name, + char_range *replace_email) { - const char* email_start; - const char* email_end; - const char* name_start; - const char* name_end; + char_range line, comment, name_a, email_a, name_b, email_b; + bool two_emails = false; + + *found = false; + *real_name = NULL_RANGE; + *real_email = NULL_RANGE; + *replace_name = NULL_RANGE; + *replace_email = NULL_RANGE; + + while (file->len) { + /* Get the line, and remove any comments */ + range_split(*file, '\n', &line, file); + range_split(line, '#', &line, &comment); + + /* Skip blank lines */ + range_trim(&line); + if (line.len == 0) + continue; - email_start = memchr(line, '<', length); - if (!email_start) - return -1; - email_end = memchr(email_start, '>', length - (email_start - line)); - if (!email_end) - return -1; - assert(email_end > email_start); + /* Get the first name and email */ + if (!range_split(line, '<', &name_a, &line)) + return -1; /* garbage in line */ + if (!range_split(line, '>', &email_a, &line)) + return -1; /* unfinished <> pair */ + + /* Get an optional second name and/or email */ + two_emails = range_split(line, '<', &name_b, &line); + if (two_emails && !range_split(line, '>', &email_b, &line)) + return -1; /* unfinished <> pair */ + + if (line.len > 0) + return -1; /* junk at end of line */ + + /* Trim whitespace from around names */ + range_trim(&name_a); + range_trim(&name_b); + + *found = true; + if (name_a.len > 0) + *real_name = name_a; + + if (two_emails) { + *real_email = email_a; + *replace_email = email_b; + + if (name_b.len > 0) + *replace_name = name_b; + } else { + *replace_email = email_a; + } + break; + } - *email_len = email_end - email_start - 1; - *email = email_start + 1; - if (*email == email_end && !allow_empty_email) - return -1; + return 0; +} - // Now look for the name. - name_start = line; - while (name_start < email_start && isspace(*name_start)) - ++name_start; +int git_mailmap_parse( + git_mailmap **mailmap, + const char *data, + size_t size) +{ + char_range file = { data, size }; + git_mailmap_entry* entry = NULL; + int error = 0; - *name = name_start; + *mailmap = git__calloc(1, sizeof(git_mailmap)); + if (!*mailmap) + return -1; - name_end = email_start; - while (name_end > name_start && isspace(*(name_end - 1))) - name_end--; + /* XXX: Is it worth it to precompute the size? */ + error = git_vector_init(&(*mailmap)->entries, 0, NULL); + if (error < 0) + goto cleanup; + + while (file.len > 0) { + bool found = false; + char_range real_name, real_email, replace_name, replace_email; + size_t size = 0; + char *buf = NULL; + + error = git_mailmap_parse_single( + &file, &found, + &real_name, &real_email, + &replace_name, &replace_email); + if (error < 0) + goto cleanup; + if (!found) + break; + + /* Compute how much space we'll need to store our entry */ + size = sizeof(git_mailmap_entry); + range_copyz(NULL, &size, real_name); + range_copyz(NULL, &size, real_email); + range_copyz(NULL, &size, replace_name); + range_copyz(NULL, &size, replace_email); + + entry = git__malloc(size); + if (!entry) { + error = -1; + goto cleanup; + } + + buf = (char*)(entry + 1); + entry->real_name = range_copyz(&buf, NULL, real_name); + entry->real_email = range_copyz(&buf, NULL, real_email); + entry->replace_name = range_copyz(&buf, NULL, replace_name); + entry->replace_email = range_copyz(&buf, NULL, replace_email); + assert(buf == ((char*)entry) + size); + + error = git_vector_insert(&(*mailmap)->entries, entry); + if (error < 0) + goto cleanup; + entry = NULL; + } - assert(name_end >= name_start); - *name_len = name_end - name_start; +cleanup: + if (entry) + git__free(entry); + if (error < 0 && *mailmap) + git_mailmap_free(*mailmap); + return error; +} - return email_end - line; +void git_mailmap_free(git_mailmap *mailmap) +{ + git_vector_free_deep(&mailmap->entries); + git__free(mailmap); } -static void git_mailmap_parse_line( - git_mailmap* mailmap, - const char* contents, - size_t size) +void git_mailmap_resolve( + const char **name_out, + const char **email_out, + git_mailmap *mailmap, + const char *name, + const char *email) { - struct mailmap_entry* entry; - - const char* to_name; - size_t to_name_length; - - const char* to_email; - size_t to_email_length; - - const char* from_name; - size_t from_name_length; - - const char* from_email; - size_t from_email_length; - - ssize_t ret; - - if (!size) - return; - if (contents[0] == '#') - return; - - ret = parse_name_and_email( - contents, - size, - &to_name, - &to_name_length, - &to_email, - &to_email_length, - false); - if (ret < 0) - return; - - ret = parse_name_and_email( - contents + ret + 1, - size - ret - 1, - &from_name, - &from_name_length, - &from_email, - &from_email_length, - true); - if (ret < 0) - return; - - entry = git__malloc(sizeof(struct mailmap_entry)); - - entry->to_name = git__strndup(to_name, to_name_length); - entry->to_email = git__strndup(to_email, to_email_length); - entry->from_name = git__strndup(from_name, from_name_length); - entry->from_email = git__strndup(from_email, from_email_length); - - printf("%s <%s> \"%s\" <%s>\n", - entry->to_name, - entry->to_email, - entry->from_name, - entry->from_email); - - git_vector_insert(&mailmap->lines, entry); + git_mailmap_entry *entry = NULL; + + *name_out = name; + *email_out = email; + + entry = git_mailmap_entry_lookup(mailmap, name, email); + if (entry) { + if (entry->real_name) + *name_out = entry->real_name; + if (entry->real_email) + *email_out = entry->real_email; + } } -static void git_mailmap_parse( - git_mailmap* mailmap, - const char* contents, - size_t size) +git_mailmap_entry* git_mailmap_entry_lookup( + git_mailmap *mailmap, + const char *name, + const char *email) { - size_t start = 0; size_t i; - for (i = 0; i < size; ++i) { - if (contents[i] != '\n') - continue; - git_mailmap_parse_line(mailmap, contents + start, i - start); - start = i + 1; + git_mailmap_entry *entry; + assert(mailmap && name && email); + + git_vector_foreach(&mailmap->entries, i, entry) { + if (!git__strcmp(email, entry->replace_email) && + (!entry->replace_name || !git__strcmp(name, entry->replace_name))) { + return entry; + } } + + return NULL; } -int git_mailmap_create(git_mailmap** mailmap, git_repository* repo) +git_mailmap_entry* git_mailmap_entry_byindex(git_mailmap *mailmap, size_t idx) { - git_commit* head = NULL; - git_blob* mailmap_blob = NULL; - git_off_t size = 0; - const char* contents = NULL; - int ret; - - *mailmap = git__malloc(sizeof(struct git_mailmap)); - git_vector_init(&(*mailmap)->lines, 0, NULL); + return git_vector_get(&mailmap->entries, idx); +} - ret = git_revparse_single((git_object **)&head, repo, "HEAD"); - if (ret) - goto error; +size_t git_mailmap_entry_count(git_mailmap *mailmap) +{ + return git_vector_length(&mailmap->entries); +} - ret = git_object_lookup_bypath( - (git_object**) &mailmap_blob, - (const git_object*) head, - ".mailmap", - GIT_OBJ_BLOB); - if (ret) - goto error; +int git_mailmap_from_tree( + git_mailmap **mailmap, + const git_object *treeish) +{ + git_blob *blob = NULL; + const char *content = NULL; + git_off_t size = 0; + int error; - contents = git_blob_rawcontent(mailmap_blob); - size = git_blob_rawsize(mailmap_blob); + *mailmap = NULL; - git_mailmap_parse(*mailmap, contents, size); + error = git_object_lookup_bypath( + (git_object **) &blob, + treeish, + ".mailmap", + GIT_OBJ_BLOB); + if (error < 0) + goto cleanup; - return 0; + content = git_blob_rawcontent(blob); + size = git_blob_rawsize(blob); -error: - assert(ret); + error = git_mailmap_parse(mailmap, content, size); - if (mailmap_blob) - git_blob_free(mailmap_blob); - if (head) - git_commit_free(head); - git_mailmap_free(*mailmap); - return ret; +cleanup: + if (blob != NULL) + git_blob_free(blob); + return error; } -void git_mailmap_free(struct git_mailmap* mailmap) +int git_mailmap_from_repo(git_mailmap **mailmap, git_repository *repo) { - size_t i; - struct mailmap_entry* line; - git_vector_foreach(&mailmap->lines, i, line) { - git__free((char*)line->to_name); - git__free((char*)line->to_email); - git__free((char*)line->from_name); - git__free((char*)line->from_email); - git__free(line); - } + git_object *head = NULL; + int error; - git_vector_clear(&mailmap->lines); - git__free(mailmap); + *mailmap = NULL; + + error = git_revparse_single(&head, repo, "HEAD"); + if (error < 0) + goto cleanup; + + error = git_mailmap_from_tree(mailmap, head); + +cleanup: + if (head) + git_object_free(head); + return error; } -- cgit v1.2.1 From ae2221362f68e167b9f3fdb0132bf339c40483de Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sat, 17 Mar 2018 02:33:48 -0400 Subject: mailmap: Some more style cleanup --- src/mailmap.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/mailmap.c b/src/mailmap.c index 9e4d57468..4a073a2bf 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -246,7 +246,7 @@ void git_mailmap_resolve( } } -git_mailmap_entry* git_mailmap_entry_lookup( +git_mailmap_entry *git_mailmap_entry_lookup( git_mailmap *mailmap, const char *name, const char *email) @@ -265,9 +265,12 @@ git_mailmap_entry* git_mailmap_entry_lookup( return NULL; } -git_mailmap_entry* git_mailmap_entry_byindex(git_mailmap *mailmap, size_t idx) +git_mailmap_entry *git_mailmap_entry_byindex(git_mailmap *mailmap, size_t idx) { - return git_vector_get(&mailmap->entries, idx); + if (idx < git_vector_length(&mailmap->entries)) + return git_vector_get(&mailmap->entries, idx); + + return NULL; } size_t git_mailmap_entry_count(git_mailmap *mailmap) -- cgit v1.2.1 From ae5ee182befb1bdf11b4455e796548fc18655af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 17 Mar 2018 17:33:48 +0100 Subject: mailmap: git_vector_get already checks bounds --- src/mailmap.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/mailmap.c b/src/mailmap.c index 4a073a2bf..9c3b8343c 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -267,10 +267,7 @@ git_mailmap_entry *git_mailmap_entry_lookup( git_mailmap_entry *git_mailmap_entry_byindex(git_mailmap *mailmap, size_t idx) { - if (idx < git_vector_length(&mailmap->entries)) - return git_vector_get(&mailmap->entries, idx); - - return NULL; + return git_vector_get(&mailmap->entries, idx); } size_t git_mailmap_entry_count(git_mailmap *mailmap) -- cgit v1.2.1 From 44112db208c92685ddaea4010b266cc411a062b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 17 Mar 2018 17:34:42 +0100 Subject: mailmap: Be consistent about checking len vs. len > 0 Not that it matters much anyway but... --- src/mailmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mailmap.c b/src/mailmap.c index 9c3b8343c..12b684f6a 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -105,7 +105,7 @@ static int git_mailmap_parse_single( *replace_name = NULL_RANGE; *replace_email = NULL_RANGE; - while (file->len) { + while (file->len > 0) { /* Get the line, and remove any comments */ range_split(*file, '\n', &line, file); range_split(line, '#', &line, &comment); -- cgit v1.2.1 From 97bc898828f8a281f292cef8913e6ec2dc13eef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 17 Mar 2018 17:40:24 +0100 Subject: mailmap: Do not error out when the mailmap contains an invalid line This matches git. --- src/mailmap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mailmap.c b/src/mailmap.c index 12b684f6a..54ef72066 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -180,10 +180,10 @@ int git_mailmap_parse( &file, &found, &real_name, &real_email, &replace_name, &replace_email); - if (error < 0) - goto cleanup; - if (!found) - break; + if (error < 0 || !found) { + error = 0; + continue; + } /* Compute how much space we'll need to store our entry */ size = sizeof(git_mailmap_entry); -- cgit v1.2.1 From 59fbf9cfb0633f2968a8d397074456bfbbef0cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 17 Mar 2018 18:29:34 +0100 Subject: mailmap: Don't return a freed pointer, even if we return an error code --- src/mailmap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mailmap.c b/src/mailmap.c index 54ef72066..850b566ce 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -214,8 +214,10 @@ int git_mailmap_parse( cleanup: if (entry) git__free(entry); - if (error < 0 && *mailmap) + if (error < 0 && *mailmap) { git_mailmap_free(*mailmap); + *mailmap = NULL; + } return error; } -- cgit v1.2.1 From 7bafd175e55d5f6bf96f70973cfff92ee3ca5179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 18 Mar 2018 01:39:57 +0100 Subject: mailmap: Don't error out when there's junk at the end of the line Also matches git. --- src/mailmap.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/mailmap.c b/src/mailmap.c index 850b566ce..dfff47d3a 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -126,9 +126,6 @@ static int git_mailmap_parse_single( if (two_emails && !range_split(line, '>', &email_b, &line)) return -1; /* unfinished <> pair */ - if (line.len > 0) - return -1; /* junk at end of line */ - /* Trim whitespace from around names */ range_trim(&name_a); range_trim(&name_b); -- cgit v1.2.1 From b88cbf8c28b6965e6f57d8f044aeab437914c23d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 18 Mar 2018 01:40:47 +0100 Subject: mailmap: Add some super-basic tests --- tests/mailmap/basic.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tests/mailmap/basic.c diff --git a/tests/mailmap/basic.c b/tests/mailmap/basic.c new file mode 100644 index 000000000..b507407a5 --- /dev/null +++ b/tests/mailmap/basic.c @@ -0,0 +1,98 @@ +#include "clar.h" +#include "clar_libgit2.h" + +#include "common.h" +#include "git2/mailmap.h" + +static git_mailmap *mailmap = NULL; + +const char TEST_MAILMAP[] = + "Foo bar \n" + "Blatantly invalid line\n" + "Foo bar \n" + " \n" + " Other Name \n"; + +void test_mailmap_basic__initialize(void) +{ + cl_git_pass(git_mailmap_parse(&mailmap, TEST_MAILMAP, sizeof(TEST_MAILMAP))); +} + +void test_mailmap_basic__cleanup(void) +{ + if (mailmap) { + git_mailmap_free(mailmap); + mailmap = NULL; + } +} + +void test_mailmap_basic__entry(void) +{ + git_mailmap_entry* entry; + + cl_assert(git_mailmap_entry_count(mailmap) == 4); + + entry = git_mailmap_entry_byindex(mailmap, 0); + cl_assert(entry); + cl_assert(!entry->replace_name); + cl_assert(!git__strcmp(entry->replace_email, "foo@baz.com")); + + entry = git_mailmap_entry_byindex(mailmap, 10000); + cl_assert(!entry); +} + +void test_mailmap_basic__lookup_not_found(void) +{ + git_mailmap_entry* entry = git_mailmap_entry_lookup( + mailmap, + "Whoever", + "doesnotexist@fo.com"); + cl_assert(!entry); +} + +void test_mailmap_basic__lookup(void) +{ + git_mailmap_entry* entry = git_mailmap_entry_lookup( + mailmap, + "Typoed the name once", + "foo@baz.com"); + cl_assert(entry); + cl_assert(!git__strcmp(entry->real_name, "Foo bar")); +} + +void test_mailmap_basic__empty_email_query(void) +{ + const char* name; + const char* email; + git_mailmap_resolve( + &name, + &email, + mailmap, + "Author name", + "otheremail@foo.com"); + cl_assert(!git__strcmp(name, "Author name")); + cl_assert(!git__strcmp(email, "email@foo.com")); +} + +void test_mailmap_basic__name_matching(void) +{ + const char* name; + const char* email; + git_mailmap_resolve( + &name, + &email, + mailmap, + "Other Name", + "yetanotheremail@foo.com"); + cl_assert(!git__strcmp(name, "Other Name")); + cl_assert(!git__strcmp(email, "email@foo.com")); + + git_mailmap_resolve( + &name, + &email, + mailmap, + "Other Name That Doesn't Match", + "yetanotheremail@foo.com"); + cl_assert(!git__strcmp(name, "Other Name That Doesn't Match")); + cl_assert(!git__strcmp(email, "yetanotheremail@foo.com")); +} -- cgit v1.2.1 From 939d8d579dcf722ca56578203df7c3134ba23ac1 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sat, 17 Mar 2018 18:14:03 -0400 Subject: mailmap: Support path fixtures in cl_git_repository_init() --- tests/clar.h | 1 + tests/clar/fixtures.h | 27 +++++++++++++-------------- tests/clar_libgit2.c | 12 +++++++++--- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/tests/clar.h b/tests/clar.h index 5c674d70f..dfb88d76d 100644 --- a/tests/clar.h +++ b/tests/clar.h @@ -72,6 +72,7 @@ void cl_trace_register(cl_trace_cb *cb, void *payload); const char *cl_fixture(const char *fixture_name); void cl_fixture_sandbox(const char *fixture_name); void cl_fixture_cleanup(const char *fixture_name); +const char *cl_fixture_basename(const char *fixture_name); #endif /** diff --git a/tests/clar/fixtures.h b/tests/clar/fixtures.h index f7b8d96af..77033d365 100644 --- a/tests/clar/fixtures.h +++ b/tests/clar/fixtures.h @@ -20,19 +20,6 @@ fixture_path(const char *base, const char *fixture_name) return _path; } -static const char * -fixture_basename(const char *fixture_name) -{ - const char *p; - - for (p = fixture_name; *p; p++) { - if (p[0] == '/' && p[1] && p[1] != '/') - fixture_name = p+1; - } - - return fixture_name; -} - #ifdef CLAR_FIXTURE_PATH const char *cl_fixture(const char *fixture_name) { @@ -44,8 +31,20 @@ void cl_fixture_sandbox(const char *fixture_name) fs_copy(cl_fixture(fixture_name), _clar_path); } +const char *cl_fixture_basename(const char *fixture_name) +{ + const char *p; + + for (p = fixture_name; *p; p++) { + if (p[0] == '/' && p[1] && p[1] != '/') + fixture_name = p+1; + } + + return fixture_name; +} + void cl_fixture_cleanup(const char *fixture_name) { - fs_rm(fixture_path(_clar_path, fixture_basename(fixture_name))); + fs_rm(fixture_path(_clar_path, cl_fixture_basename(fixture_name))); } #endif diff --git a/tests/clar_libgit2.c b/tests/clar_libgit2.c index 92404b5d7..b50633a6c 100644 --- a/tests/clar_libgit2.c +++ b/tests/clar_libgit2.c @@ -171,13 +171,17 @@ static git_repository *_cl_repo = NULL; git_repository *cl_git_sandbox_init(const char *sandbox) { + /* Get the name of the sandbox folder which will be created + */ + const char *basename = cl_fixture_basename(sandbox); + /* Copy the whole sandbox folder from our fixtures to our test sandbox * area. After this it can be accessed with `./sandbox` */ cl_fixture_sandbox(sandbox); _cl_sandbox = sandbox; - cl_git_pass(p_chdir(sandbox)); + cl_git_pass(p_chdir(basename)); /* If this is not a bare repo, then rename `sandbox/.gitted` to * `sandbox/.git` which must be done since we cannot store a folder @@ -200,7 +204,7 @@ git_repository *cl_git_sandbox_init(const char *sandbox) cl_git_pass(p_chdir("..")); /* Now open the sandbox repository and make it available for tests */ - cl_git_pass(git_repository_open(&_cl_repo, sandbox)); + cl_git_pass(git_repository_open(&_cl_repo, basename)); /* Adjust configs after copying to new filesystem */ cl_git_pass(git_repository_reinit_filesystem(_cl_repo, 0)); @@ -222,7 +226,9 @@ git_repository *cl_git_sandbox_reopen(void) git_repository_free(_cl_repo); _cl_repo = NULL; - cl_git_pass(git_repository_open(&_cl_repo, _cl_sandbox)); + cl_git_pass(git_repository_open( + &_cl_repo, + cl_fixture_basename(_cl_sandbox))); } return _cl_repo; -- cgit v1.2.1 From b05fbba394b9f2befea8b50817fd64209538e384 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sat, 17 Mar 2018 18:14:31 -0400 Subject: mailmap: Make everything a bit more style conforming --- include/git2/mailmap.h | 61 ++++++++++++++-------------- src/mailmap.c | 107 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 113 insertions(+), 55 deletions(-) diff --git a/include/git2/mailmap.h b/include/git2/mailmap.h index 0f582c2a3..a80ecb970 100644 --- a/include/git2/mailmap.h +++ b/include/git2/mailmap.h @@ -8,7 +8,7 @@ #define INCLUDE_git_mailmap_h__ #include "common.h" -#include "tree.h" +#include "types.h" /** * @file git2/mailmap.h @@ -19,24 +19,27 @@ */ GIT_BEGIN_DECL -typedef struct git_mailmap git_mailmap; - /** * A single entry parsed from a mailmap. */ -typedef struct git_mailmap_entry { +struct git_mailmap_entry { + unsigned int version; + const char *real_name; /**< the real name (may be NULL) */ const char *real_email; /**< the real email (may be NULL) */ const char *replace_name; /**< the name to replace (may be NULL) */ const char *replace_email; /**< the email to replace */ -} git_mailmap_entry; +}; + +#define GIT_MAILMAP_ENTRY_VERSION 1 +#define GIT_MAILMAP_ENTRY_INIT {GIT_MAILMAP_ENTRY_VERSION} /** * Create a mailmap object by parsing a mailmap file. * * The mailmap must be freed with 'git_mailmap_free'. * - * @param out Pointer to store the mailmap + * @param out pointer to store the mailmap * @param data raw data buffer to parse * @param size size of the raw data buffer * @return 0 on success @@ -47,35 +50,26 @@ GIT_EXTERN(int) git_mailmap_parse( size_t size); /** - * Create a mailmap object by parsing the ".mailmap" file in the tree root. + * Create a mailmap object from the given repository. * - * The mailmap must be freed with 'git_mailmap_free'. + * If the repository is not bare, the repository's working directory root will + * be checked for the '.mailmap' file to be parsed. * - * @param out pointer to store the mailmap - * @param treeish root object that can be peeled to a tree - * @return 0 on success; GIT_ENOTFOUND if .mailmap does not exist. - */ -GIT_EXTERN(int) git_mailmap_from_tree( - git_mailmap **out, - const git_object *treeish); - -/** - * Create a mailmap object by parsing the ".mailmap" file in the repository's - * HEAD's tree root. + * If the repository is bare, the repository's HEAD commit's tree root will be + * searched for the '.mailmap' file to be parsed. * * The mailmap must be freed with 'git_mailmap_free'. * * @param out pointer to store the mailmap * @param repo repository to find the .mailmap in - * @return 0 on success; GIT_ENOTFOUND if .mailmap does not exist. + * @return 0 on success; GIT_ENOTFOUND if .mailmap could not be found. */ GIT_EXTERN(int) git_mailmap_from_repo( git_mailmap **out, git_repository *repo); /** - * Free a mailmap created by 'git_mailmap_parse', 'git_mailmap_from_tree' or - * 'git_mailmap_from_repo'. + * Free a mailmap created by 'git_mailmap_parse' or 'git_mailmap_from_repo'. */ GIT_EXTERN(void) git_mailmap_free(git_mailmap *mailmap); @@ -86,38 +80,45 @@ GIT_EXTERN(void) git_mailmap_free(git_mailmap *mailmap); * You should NOT free this value. * @param email_out either 'email' or the real email to use, * You should NOT free this value. - * @param mailmap the mailmap to perform the lookup in. + * @param mailmap the mailmap to perform the lookup in. (may be NULL) * @param name the name to resolve. * @param email the email to resolve. */ GIT_EXTERN(void) git_mailmap_resolve( const char **name_out, const char **email_out, - git_mailmap *mailmap, + const git_mailmap *mailmap, const char *name, const char *email); /** - * Get the number of mailmap entries. + * Get the number of mailmap entries in this mailmap. */ -GIT_EXTERN(size_t) git_mailmap_entry_count(git_mailmap *mailmap); +GIT_EXTERN(size_t) git_mailmap_entry_count(const git_mailmap *mailmap); /** * Lookup a mailmap entry by index. * * Do not free the mailmap entry, it is owned by the mailmap. + * + * @return the mailmap entry at index, or NULL if it cannot be found. */ -GIT_EXTERN(git_mailmap_entry *) git_mailmap_entry_byindex( - git_mailmap *mailmap, +GIT_EXTERN(const git_mailmap_entry *) git_mailmap_entry_byindex( + const git_mailmap *mailmap, size_t idx); /** * Lookup a mailmap entry by name/email pair. * * Do not free the mailmap entry, it is owned by the mailmap. + * + * @param mailmap the mailmap to perform the lookup in. (may be NULL) + * @param name the name to perform the lookup with. + * @param email the email to perform the lookup with. + * @return the corresponding mailmap entry, or NULL if it cannot be found. */ -GIT_EXTERN(git_mailmap_entry *) git_mailmap_entry_lookup( - git_mailmap *mailmap, +GIT_EXTERN(const git_mailmap_entry *) git_mailmap_entry_lookup( + const git_mailmap *mailmap, const char *name, const char *email); diff --git a/src/mailmap.c b/src/mailmap.c index dfff47d3a..aaf5446f2 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -135,7 +135,8 @@ static int git_mailmap_parse_single( *real_name = name_a; if (two_emails) { - *real_email = email_a; + if (email_a.len > 0) + *real_email = email_a; *replace_email = email_b; if (name_b.len > 0) @@ -158,6 +159,9 @@ int git_mailmap_parse( git_mailmap_entry* entry = NULL; int error = 0; + if (memchr(data, '\0', size) != NULL) + return -1; /* data may not contain '\0's */ + *mailmap = git__calloc(1, sizeof(git_mailmap)); if (!*mailmap) return -1; @@ -194,6 +198,7 @@ int git_mailmap_parse( error = -1; goto cleanup; } + entry->version = GIT_MAILMAP_ENTRY_VERSION; buf = (char*)(entry + 1); entry->real_name = range_copyz(&buf, NULL, real_name); @@ -209,9 +214,8 @@ int git_mailmap_parse( } cleanup: - if (entry) - git__free(entry); - if (error < 0 && *mailmap) { + git__free(entry); + if (error < 0) git_mailmap_free(*mailmap); *mailmap = NULL; } @@ -220,6 +224,9 @@ cleanup: void git_mailmap_free(git_mailmap *mailmap) { + if (!mailmap) + return; + git_vector_free_deep(&mailmap->entries); git__free(mailmap); } @@ -227,15 +234,19 @@ void git_mailmap_free(git_mailmap *mailmap) void git_mailmap_resolve( const char **name_out, const char **email_out, - git_mailmap *mailmap, + const git_mailmap *mailmap, const char *name, const char *email) { - git_mailmap_entry *entry = NULL; + const git_mailmap_entry *entry = NULL; + assert(name && email); *name_out = name; *email_out = email; + if (!mailmap) + return; + entry = git_mailmap_entry_lookup(mailmap, name, email); if (entry) { if (entry->real_name) @@ -245,14 +256,17 @@ void git_mailmap_resolve( } } -git_mailmap_entry *git_mailmap_entry_lookup( - git_mailmap *mailmap, +const git_mailmap_entry *git_mailmap_entry_lookup( + const git_mailmap *mailmap, const char *name, const char *email) { size_t i; git_mailmap_entry *entry; - assert(mailmap && name && email); + assert(name && email); + + if (!mailmap) + return NULL; git_vector_foreach(&mailmap->entries, i, entry) { if (!git__strcmp(email, entry->replace_email) && @@ -264,26 +278,42 @@ git_mailmap_entry *git_mailmap_entry_lookup( return NULL; } -git_mailmap_entry *git_mailmap_entry_byindex(git_mailmap *mailmap, size_t idx) +const git_mailmap_entry *git_mailmap_entry_byindex( + const git_mailmap *mailmap, size_t idx) { - return git_vector_get(&mailmap->entries, idx); + if (mailmap) + return git_vector_get(&mailmap->entries, idx); + return NULL; } -size_t git_mailmap_entry_count(git_mailmap *mailmap) +size_t git_mailmap_entry_count(const git_mailmap *mailmap) { - return git_vector_length(&mailmap->entries); + if (mailmap) + return git_vector_length(&mailmap->entries); + return 0; } -int git_mailmap_from_tree( +static int git_mailmap_from_bare_repo( git_mailmap **mailmap, - const git_object *treeish) + git_repository *repo) { + git_reference *head = NULL; + git_object *tree = NULL; git_blob *blob = NULL; const char *content = NULL; git_off_t size = 0; int error; - *mailmap = NULL; + assert(git_repository_is_bare(repo)); + + /* In bare repositories, fall back to reading from HEAD's tree */ + error = git_repository_head(&head, repo); + if (error < 0) + goto cleanup; + + error = git_reference_peel(&tree, head, GIT_OBJ_TREE); + if (error < 0) + goto cleanup; error = git_object_lookup_bypath( (git_object **) &blob, @@ -297,28 +327,55 @@ int git_mailmap_from_tree( size = git_blob_rawsize(blob); error = git_mailmap_parse(mailmap, content, size); + if (error < 0) + goto cleanup; cleanup: - if (blob != NULL) - git_blob_free(blob); + git_reference_free(head); + git_object_free(tree); + git_blob_free(blob); + return error; } -int git_mailmap_from_repo(git_mailmap **mailmap, git_repository *repo) +static int git_mailmap_from_workdir_repo( + git_mailmap **mailmap, + git_repository *repo) { - git_object *head = NULL; + git_buf path = GIT_BUF_INIT; + git_buf data = GIT_BUF_INIT; int error; - *mailmap = NULL; + assert(!git_repository_is_bare(repo)); - error = git_revparse_single(&head, repo, "HEAD"); + /* In non-bare repositories, .mailmap should be read from the workdir */ + error = git_buf_joinpath(&path, git_repository_workdir(repo), ".mailmap"); if (error < 0) goto cleanup; - error = git_mailmap_from_tree(mailmap, head); + error = git_futils_readbuffer(&data, git_buf_cstr(&path)); + if (error < 0) + goto cleanup; + + error = git_mailmap_parse(mailmap, data.ptr, data.size); + if (error < 0) + goto cleanup; cleanup: - if (head) - git_object_free(head); + git_buf_free(&path); + git_buf_free(&data); + return error; } + +int git_mailmap_from_repo(git_mailmap **mailmap, git_repository *repo) +{ + assert(mailmap && repo); + + *mailmap = NULL; + + if (git_repository_is_bare(repo)) + return git_mailmap_from_bare_repo(mailmap, repo); + else + return git_mailmap_from_workdir_repo(mailmap, repo); +} -- cgit v1.2.1 From e3dcaca579ba344ccdacfe4835dcc7bf52c5ba57 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sat, 17 Mar 2018 18:15:01 -0400 Subject: mailmap: Integrate mailmaps with blame and signatures --- include/git2/blame.h | 10 ++++++++++ include/git2/commit.h | 28 ++++++++++++++++++++++++++++ include/git2/signature.h | 13 +++++++++++++ include/git2/types.h | 3 +++ src/blame.c | 14 ++++++++++---- src/blame.h | 2 ++ src/commit.c | 12 ++++++++++++ src/signature.c | 39 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 117 insertions(+), 4 deletions(-) diff --git a/include/git2/blame.h b/include/git2/blame.h index 34cb69916..cc9131718 100644 --- a/include/git2/blame.h +++ b/include/git2/blame.h @@ -43,6 +43,10 @@ typedef enum { /** Restrict the search of commits to those reachable following only the * first parents. */ GIT_BLAME_FIRST_PARENT = (1<<4), + /** Use mailmap file to map author and committer names and email addresses + * to canonical real names and email addresses. The mailmap will be read + * from the working directory, or HEAD in a bare repository. */ + GIT_BLAME_USE_MAILMAP = (1<<5), } git_blame_flag_t; /** @@ -108,6 +112,9 @@ GIT_EXTERN(int) git_blame_init_options( * changed. * - `final_start_line_number` is the 1-based line number where this hunk * begins, in the final version of the file + * - `final_signature` is the author of `final_commit_id`. If + * `GIT_BLAME_USE_MAILMAP` has been specified, it will contain the canonical + * real name and email address. * - `orig_commit_id` is the OID of the commit where this hunk was found. This * will usually be the same as `final_commit_id`, except when * `GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES` has been specified. @@ -116,6 +123,9 @@ GIT_EXTERN(int) git_blame_init_options( * - `orig_start_line_number` is the 1-based line number where this hunk begins * in the file named by `orig_path` in the commit specified by * `orig_commit_id`. + * - `orig_signature` is the author of `orig_commit_id`. If + * `GIT_BLAME_USE_MAILMAP` has been specified, it will contain the canonical + * real name and email address. * - `boundary` is 1 iff the hunk has been tracked to a boundary commit (the * root, or the commit specified in git_blame_options.oldest_commit) */ diff --git a/include/git2/commit.h b/include/git2/commit.h index 692b3bdd9..50f2fc963 100644 --- a/include/git2/commit.h +++ b/include/git2/commit.h @@ -172,6 +172,34 @@ GIT_EXTERN(const git_signature *) git_commit_committer(const git_commit *commit) */ GIT_EXTERN(const git_signature *) git_commit_author(const git_commit *commit); +/** + * Get the committer of a commit, using the mailmap to map names and email + * addresses to canonical real names and email addresses. + * + * Call `git_signature_free` to free the signature. + * + * @param out a pointer to store the resolved signature. + * @param commit a previously loaded commit. + * @param mailmap the mailmap to resolve with. (may be NULL) + * @return 0 or an error code + */ +GIT_EXTERN(int) git_commit_committer_with_mailmap( + git_signature **out, const git_commit *commit, const git_mailmap *mailmap); + +/** + * Get the author of a commit, using the mailmap to map names and email + * addresses to canonical real names and email addresses. + * + * Call `git_signature_free` to free the signature. + * + * @param out a pointer to store the resolved signature. + * @param commit a previously loaded commit. + * @param mailmap the mailmap to resolve with. (may be NULL) + * @return 0 or an error code + */ +GIT_EXTERN(int) git_commit_author_with_mailmap( + git_signature **out, const git_commit *commit, const git_mailmap *mailmap); + /** * Get the full raw text of the commit header. * diff --git a/include/git2/signature.h b/include/git2/signature.h index 7a2a0238a..18fae98c2 100644 --- a/include/git2/signature.h +++ b/include/git2/signature.h @@ -75,6 +75,19 @@ GIT_EXTERN(int) git_signature_default(git_signature **out, git_repository *repo) */ GIT_EXTERN(int) git_signature_from_buffer(git_signature **out, const char *buf); +/** + * Create a signature with names updated respecting the mailmap. + * + * Call `git_signature_free()` to free the data. + * + * @param out new signature + * @param sig signature to resolve + * @param mailmap mailmap to resolve with + * @return 0 or an error code + */ +GIT_EXTERN(int) git_signature_with_mailmap( + git_signature **out, const git_signature *sig, const git_mailmap *mailmap); + /** * Create a copy of an existing signature. All internal strings are also * duplicated. diff --git a/include/git2/types.h b/include/git2/types.h index 67e5bd155..943a7e987 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -434,6 +434,9 @@ struct git_writestream { void (*free)(git_writestream *stream); }; +/** A parsed representation of a .mailmap file. */ +typedef struct git_mailmap git_mailmap; + /** @} */ GIT_END_DECL diff --git a/src/blame.c b/src/blame.c index a923bf003..967530b7e 100644 --- a/src/blame.c +++ b/src/blame.c @@ -132,6 +132,9 @@ git_blame* git_blame__alloc( return NULL; } + if (opts.flags & GIT_BLAME_USE_MAILMAP) + git_mailmap_from_repo(&gbr->mailmap, repo); + return gbr; } @@ -150,6 +153,8 @@ void git_blame_free(git_blame *blame) git_array_clear(blame->line_index); + git_mailmap_free(blame->mailmap); + git__free(blame->path); git_blob_free(blame->final_blob); git__free(blame); @@ -279,7 +284,7 @@ static int index_blob_lines(git_blame *blame) return blame->num_lines; } -static git_blame_hunk* hunk_from_entry(git_blame__entry *e) +static git_blame_hunk* hunk_from_entry(git_blame__entry *e, git_blame *blame) { git_blame_hunk *h = new_hunk( e->lno+1, e->num_lines, e->s_lno+1, e->suspect->path); @@ -289,8 +294,9 @@ static git_blame_hunk* hunk_from_entry(git_blame__entry *e) git_oid_cpy(&h->final_commit_id, git_commit_id(e->suspect->commit)); git_oid_cpy(&h->orig_commit_id, git_commit_id(e->suspect->commit)); - git_signature_dup(&h->final_signature, git_commit_author(e->suspect->commit)); - git_signature_dup(&h->orig_signature, git_commit_author(e->suspect->commit)); + git_commit_author_with_mailmap( + &h->final_signature, e->suspect->commit, blame->mailmap); + git_signature_dup(&h->orig_signature, h->final_signature); h->boundary = e->is_boundary ? 1 : 0; return h; } @@ -341,7 +347,7 @@ static int blame_internal(git_blame *blame) cleanup: for (ent = blame->ent; ent; ) { git_blame__entry *e = ent->next; - git_blame_hunk *h = hunk_from_entry(ent); + git_blame_hunk *h = hunk_from_entry(ent, blame); git_vector_insert(&blame->hunks, h); diff --git a/src/blame.h b/src/blame.h index 8fd3ee5b1..057413274 100644 --- a/src/blame.h +++ b/src/blame.h @@ -84,6 +84,8 @@ struct git_blame { int num_lines; const char *final_buf; git_off_t final_buf_size; + + git_mailmap *mailmap; }; git_blame *git_blame__alloc( diff --git a/src/commit.c b/src/commit.c index e0c090aa8..03ecea8e8 100644 --- a/src/commit.c +++ b/src/commit.c @@ -889,3 +889,15 @@ cleanup: git_buf_dispose(&commit); return error; } + +int git_commit_committer_with_mailmap( + git_signature **out, const git_commit *commit, const git_mailmap *mailmap) +{ + return git_signature_with_mailmap(out, commit->committer, mailmap); +} + +int git_commit_author_with_mailmap( + git_signature **out, const git_commit *commit, const git_mailmap *mailmap) +{ + return git_signature_with_mailmap(out, commit->author, mailmap); +} diff --git a/src/signature.c b/src/signature.c index cd6852326..a93ba1019 100644 --- a/src/signature.c +++ b/src/signature.c @@ -9,6 +9,7 @@ #include "repository.h" #include "git2/common.h" +#include "git2/mailmap.h" #include "posix.h" void git_signature_free(git_signature *sig) @@ -121,6 +122,44 @@ int git_signature_dup(git_signature **dest, const git_signature *source) return 0; } +int git_signature_with_mailmap( + git_signature **dest, + const git_signature *source, + const git_mailmap *mailmap) +{ + git_signature *signature = NULL; + const char *name = NULL; + const char *email = NULL; + + if (source == NULL) + goto on_error; + + git_mailmap_resolve(&name, &email, mailmap, source->name, source->email); + + signature = git__calloc(1, sizeof(git_signature)); + if (!signature) + goto on_error; + + signature->name = git__strdup(name); + if (!signature->name) + goto on_error; + + signature->email = git__strdup(email); + if (!signature->email) + goto on_error; + + signature->when.time = source->when.time; + signature->when.offset = source->when.offset; + signature->when.sign = source->when.sign; + + *dest = signature; + return 0; + +on_error: + git_signature_free(signature); + return -1; +} + int git_signature__pdup(git_signature **dest, const git_signature *source, git_pool *pool) { git_signature *signature; -- cgit v1.2.1 From 983b8c2df818c92afa9b15041d3480b671b59a14 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sat, 17 Mar 2018 18:15:41 -0400 Subject: mailmap: Add a bunch of tests for the new mailmap functionality --- tests/mailmap/blame.c | 70 +++++++++ tests/mailmap/mailmap_helpers.h | 52 +++++++ tests/mailmap/parsing.c | 123 +++++++++++++++ tests/resources/mailmap/.gitted/COMMIT_EDITMSG | 1 + tests/resources/mailmap/.gitted/HEAD | 1 + tests/resources/mailmap/.gitted/config | 5 + tests/resources/mailmap/.gitted/description | 1 + .../mailmap/.gitted/hooks/applypatch-msg.sample | 15 ++ .../mailmap/.gitted/hooks/commit-msg.sample | 24 +++ .../mailmap/.gitted/hooks/post-update.sample | 8 + .../mailmap/.gitted/hooks/pre-applypatch.sample | 14 ++ .../mailmap/.gitted/hooks/pre-commit.sample | 49 ++++++ .../mailmap/.gitted/hooks/pre-push.sample | 53 +++++++ .../mailmap/.gitted/hooks/pre-rebase.sample | 169 +++++++++++++++++++++ .../mailmap/.gitted/hooks/pre-receive.sample | 24 +++ .../.gitted/hooks/prepare-commit-msg.sample | 36 +++++ .../resources/mailmap/.gitted/hooks/update.sample | 128 ++++++++++++++++ tests/resources/mailmap/.gitted/index | Bin 0 -> 209 bytes tests/resources/mailmap/.gitted/info/exclude | 6 + tests/resources/mailmap/.gitted/logs/HEAD | 11 ++ .../mailmap/.gitted/logs/refs/heads/master | 11 ++ .../00/1387531bed84262f137837125d4d998a9ba65d | Bin 0 -> 70 bytes .../02/7b2816ae0d7a08ba656d0417c09b4eac18cf00 | Bin 0 -> 85 bytes .../09/20975110511365e56aec2263082d0c3d56d1fa | Bin 0 -> 113 bytes .../0c/d99501dfbec781a22ff7b84426b7bb308e709a | Bin 0 -> 53 bytes .../1e/1212e7674820c17f7b8797aee7bf38ece0e838 | 2 + .../36/370b71f5aad1dd46bec5e14145280a843c9f49 | Bin 0 -> 53 bytes .../3a/1295dbc9234c0c5947c72803618c7112a01447 | 2 + .../3f/134546ae8fbe95a39dd20ea8c12b5fb0f48afb | 3 + .../43/179dc93939196f59b25387b5e44e9e8794f84c | 2 + .../46/b5bb908c78b575cac9f9e6e42ff9ba3f769a46 | Bin 0 -> 53 bytes .../4b/4d2010ba256ef339c1d1854d20249da7478f01 | Bin 0 -> 54 bytes .../4b/825dc642cb6eb9a060e54bf8d69288fbee4904 | Bin 0 -> 15 bytes .../4d/61d588546529ad27b2d77a3d6b05460ecb4be0 | Bin 0 -> 79 bytes .../50/d69f4e64be2cff2cedde8f9b7f970257caf4dd | 1 + .../61/293f4c3d7500d227a755a7a8258e28e53449b2 | Bin 0 -> 52 bytes .../62/7f0bd2f4fb5e949b79ba450d84676fa876b1c8 | Bin 0 -> 53 bytes .../68/dfd5e5cb6138488680246d134f47ce559f4cf1 | Bin 0 -> 149 bytes .../6c/dec08ab9bfcd5a3d889f27bbed650317e3ec13 | Bin 0 -> 76 bytes .../71/00e631fb4d5deba31fdc8acc98f4fb5c1573fd | Bin 0 -> 178 bytes .../7e/cbb98d860b304f622b38ce9ab8f08d14d981a8 | Bin 0 -> 198 bytes .../7e/e7b9a4a2a1eda925f6260338c063d8211d5ad5 | 2 + .../83/714a9223f3e072b85f0d4301cd2081fff3acf2 | Bin 0 -> 52 bytes .../87/ce8d4920a30ddb9547334e7c65806518863ff1 | 2 + .../8c/f0547fcb649b44ebaf39b8104982bb0abb4e69 | Bin 0 -> 121 bytes .../94/7ff75c33ac7941a32fe9900118b6ba85ab2be9 | Bin 0 -> 49 bytes .../95/d03c49d94de67d5a05553a1bb22e78f7cdf5ca | 1 + .../96/78a4325710507f7bf598a0fde5ebbd88148614 | Bin 0 -> 132 bytes .../a1/6db1cbb8817dddcf199c12d3c81221cf8eefc4 | 1 + .../a7/054a4b356b3ecdec60cee66e50beaa5b863755 | 3 + .../a7/eb40274887baeb01a958ead80d106b5977312c | Bin 0 -> 52 bytes .../c9/e5462de8ec453e94d85f26f64b80ea76fda6d4 | Bin 0 -> 53 bytes .../d3/e5e624cc7bfb09ac1960ebb6c458021b098f87 | Bin 0 -> 97 bytes .../fe/dd34e8baffdb2acfe9a6860bf339287ca942bc | Bin 0 -> 53 bytes .../fe/ef8f2135df4835496e4d576b1f1bd23510e1c5 | 1 + tests/resources/mailmap/.gitted/refs/heads/master | 1 + tests/resources/mailmap/.mailmap | 9 ++ tests/resources/mailmap/file.txt | 10 ++ 58 files changed, 841 insertions(+) create mode 100644 tests/mailmap/blame.c create mode 100644 tests/mailmap/mailmap_helpers.h create mode 100644 tests/mailmap/parsing.c create mode 100644 tests/resources/mailmap/.gitted/COMMIT_EDITMSG create mode 100644 tests/resources/mailmap/.gitted/HEAD create mode 100644 tests/resources/mailmap/.gitted/config create mode 100644 tests/resources/mailmap/.gitted/description create mode 100755 tests/resources/mailmap/.gitted/hooks/applypatch-msg.sample create mode 100755 tests/resources/mailmap/.gitted/hooks/commit-msg.sample create mode 100755 tests/resources/mailmap/.gitted/hooks/post-update.sample create mode 100755 tests/resources/mailmap/.gitted/hooks/pre-applypatch.sample create mode 100755 tests/resources/mailmap/.gitted/hooks/pre-commit.sample create mode 100755 tests/resources/mailmap/.gitted/hooks/pre-push.sample create mode 100755 tests/resources/mailmap/.gitted/hooks/pre-rebase.sample create mode 100755 tests/resources/mailmap/.gitted/hooks/pre-receive.sample create mode 100755 tests/resources/mailmap/.gitted/hooks/prepare-commit-msg.sample create mode 100755 tests/resources/mailmap/.gitted/hooks/update.sample create mode 100644 tests/resources/mailmap/.gitted/index create mode 100644 tests/resources/mailmap/.gitted/info/exclude create mode 100644 tests/resources/mailmap/.gitted/logs/HEAD create mode 100644 tests/resources/mailmap/.gitted/logs/refs/heads/master create mode 100644 tests/resources/mailmap/.gitted/objects/00/1387531bed84262f137837125d4d998a9ba65d create mode 100644 tests/resources/mailmap/.gitted/objects/02/7b2816ae0d7a08ba656d0417c09b4eac18cf00 create mode 100644 tests/resources/mailmap/.gitted/objects/09/20975110511365e56aec2263082d0c3d56d1fa create mode 100644 tests/resources/mailmap/.gitted/objects/0c/d99501dfbec781a22ff7b84426b7bb308e709a create mode 100644 tests/resources/mailmap/.gitted/objects/1e/1212e7674820c17f7b8797aee7bf38ece0e838 create mode 100644 tests/resources/mailmap/.gitted/objects/36/370b71f5aad1dd46bec5e14145280a843c9f49 create mode 100644 tests/resources/mailmap/.gitted/objects/3a/1295dbc9234c0c5947c72803618c7112a01447 create mode 100644 tests/resources/mailmap/.gitted/objects/3f/134546ae8fbe95a39dd20ea8c12b5fb0f48afb create mode 100644 tests/resources/mailmap/.gitted/objects/43/179dc93939196f59b25387b5e44e9e8794f84c create mode 100644 tests/resources/mailmap/.gitted/objects/46/b5bb908c78b575cac9f9e6e42ff9ba3f769a46 create mode 100644 tests/resources/mailmap/.gitted/objects/4b/4d2010ba256ef339c1d1854d20249da7478f01 create mode 100644 tests/resources/mailmap/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 create mode 100644 tests/resources/mailmap/.gitted/objects/4d/61d588546529ad27b2d77a3d6b05460ecb4be0 create mode 100644 tests/resources/mailmap/.gitted/objects/50/d69f4e64be2cff2cedde8f9b7f970257caf4dd create mode 100644 tests/resources/mailmap/.gitted/objects/61/293f4c3d7500d227a755a7a8258e28e53449b2 create mode 100644 tests/resources/mailmap/.gitted/objects/62/7f0bd2f4fb5e949b79ba450d84676fa876b1c8 create mode 100644 tests/resources/mailmap/.gitted/objects/68/dfd5e5cb6138488680246d134f47ce559f4cf1 create mode 100644 tests/resources/mailmap/.gitted/objects/6c/dec08ab9bfcd5a3d889f27bbed650317e3ec13 create mode 100644 tests/resources/mailmap/.gitted/objects/71/00e631fb4d5deba31fdc8acc98f4fb5c1573fd create mode 100644 tests/resources/mailmap/.gitted/objects/7e/cbb98d860b304f622b38ce9ab8f08d14d981a8 create mode 100644 tests/resources/mailmap/.gitted/objects/7e/e7b9a4a2a1eda925f6260338c063d8211d5ad5 create mode 100644 tests/resources/mailmap/.gitted/objects/83/714a9223f3e072b85f0d4301cd2081fff3acf2 create mode 100644 tests/resources/mailmap/.gitted/objects/87/ce8d4920a30ddb9547334e7c65806518863ff1 create mode 100644 tests/resources/mailmap/.gitted/objects/8c/f0547fcb649b44ebaf39b8104982bb0abb4e69 create mode 100644 tests/resources/mailmap/.gitted/objects/94/7ff75c33ac7941a32fe9900118b6ba85ab2be9 create mode 100644 tests/resources/mailmap/.gitted/objects/95/d03c49d94de67d5a05553a1bb22e78f7cdf5ca create mode 100644 tests/resources/mailmap/.gitted/objects/96/78a4325710507f7bf598a0fde5ebbd88148614 create mode 100644 tests/resources/mailmap/.gitted/objects/a1/6db1cbb8817dddcf199c12d3c81221cf8eefc4 create mode 100644 tests/resources/mailmap/.gitted/objects/a7/054a4b356b3ecdec60cee66e50beaa5b863755 create mode 100644 tests/resources/mailmap/.gitted/objects/a7/eb40274887baeb01a958ead80d106b5977312c create mode 100644 tests/resources/mailmap/.gitted/objects/c9/e5462de8ec453e94d85f26f64b80ea76fda6d4 create mode 100644 tests/resources/mailmap/.gitted/objects/d3/e5e624cc7bfb09ac1960ebb6c458021b098f87 create mode 100644 tests/resources/mailmap/.gitted/objects/fe/dd34e8baffdb2acfe9a6860bf339287ca942bc create mode 100644 tests/resources/mailmap/.gitted/objects/fe/ef8f2135df4835496e4d576b1f1bd23510e1c5 create mode 100644 tests/resources/mailmap/.gitted/refs/heads/master create mode 100644 tests/resources/mailmap/.mailmap create mode 100644 tests/resources/mailmap/file.txt diff --git a/tests/mailmap/blame.c b/tests/mailmap/blame.c new file mode 100644 index 000000000..2dd309588 --- /dev/null +++ b/tests/mailmap/blame.c @@ -0,0 +1,70 @@ +#include "clar_libgit2.h" +#include "git2/repository.h" +#include "git2/blame.h" +#include "git2/mailmap.h" +#include "mailmap_helpers.h" + +static git_repository *g_repo; +static git_blame *g_blame; +static git_mailmap *g_mailmap; + +void test_mailmap_blame__initialize(void) +{ + g_repo = NULL; + g_blame = NULL; +} + +void test_mailmap_blame__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; + + git_blame_free(g_blame); + g_blame = NULL; +} + +void test_mailmap_blame__hunks(void) +{ + size_t idx = 0; + const git_blame_hunk *hunk = NULL; + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + g_repo = cl_git_sandbox_init("mailmap"); + + opts.flags |= GIT_BLAME_USE_MAILMAP; + + cl_check_pass(git_blame_file(&g_blame, g_repo, "file.txt", &opts)); + if (!g_blame) + return; + + for (idx = 0; idx < ARRAY_SIZE(resolved); ++idx) { + hunk = git_blame_get_hunk_byline(g_blame, idx + 1); + + cl_assert(hunk->final_signature != NULL); + cl_assert(hunk->orig_signature != NULL); + cl_assert_equal_s(hunk->final_signature->name, resolved[idx].real_name); + cl_assert_equal_s(hunk->final_signature->email, resolved[idx].real_email); + } +} + +void test_mailmap_blame__hunks_no_mailmap(void) +{ + size_t idx = 0; + const git_blame_hunk *hunk = NULL; + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + + g_repo = cl_git_sandbox_init("mailmap"); + + cl_check_pass(git_blame_file(&g_blame, g_repo, "file.txt", &opts)); + if (!g_blame) + return; + + for (idx = 0; idx < ARRAY_SIZE(resolved); ++idx) { + hunk = git_blame_get_hunk_byline(g_blame, idx + 1); + + cl_assert(hunk->final_signature != NULL); + cl_assert(hunk->orig_signature != NULL); + cl_assert_equal_s(hunk->final_signature->name, resolved[idx].replace_name); + cl_assert_equal_s(hunk->final_signature->email, resolved[idx].replace_email); + } +} diff --git a/tests/mailmap/mailmap_helpers.h b/tests/mailmap/mailmap_helpers.h new file mode 100644 index 000000000..49df55fb1 --- /dev/null +++ b/tests/mailmap/mailmap_helpers.h @@ -0,0 +1,52 @@ +#include "git2/mailmap.h" + +typedef struct mailmap_entry { + const char *real_name; + const char *real_email; + const char *replace_name; + const char *replace_email; +} mailmap_entry; + +static const char string_mailmap[] = + "# Simple Comment line\n" + " \n" + "Some Dude nick1 \n" + "Other Author nick2 \n" + "Other Author \n" + "Phil Hill # Comment at end of line\n" + " Joseph \n" + "Santa Claus \n" + "Untracked "; + +static const mailmap_entry entries[] = { + { NULL, "cto@company.xx", NULL, "cto@coompany.xx" }, + { "Some Dude", "some@dude.xx", "nick1", "bugs@company.xx" }, + { "Other Author", "other@author.xx", "nick2", "bugs@company.xx" }, + { "Other Author", "other@author.xx", NULL, "nick2@company.xx" }, + { "Phil Hill", NULL, NULL, "phil@company.xx" }, + { NULL, "joseph@company.xx", "Joseph", "bugs@company.xx" }, + { "Santa Claus", "santa.claus@northpole.xx", NULL, "me@company.xx" }, + /* This entry isn't in the bare repository */ + { "Untracked", NULL, NULL, "untracked@company.xx" } +}; + +static const mailmap_entry resolved[] = { + { "Brad", "cto@company.xx", "Brad", "cto@coompany.xx" }, + { "Brad L", "cto@company.xx", "Brad L", "cto@coompany.xx" }, + { "Some Dude", "some@dude.xx", "nick1", "bugs@company.xx" }, + { "Other Author", "other@author.xx", "nick2", "bugs@company.xx" }, + { "nick3", "bugs@company.xx", "nick3", "bugs@company.xx" }, + { "Other Author", "other@author.xx", "Some Garbage", "nick2@company.xx" }, + { "Phil Hill", "phil@company.xx", "unknown", "phil@company.xx" }, + { "Joseph", "joseph@company.xx", "Joseph", "bugs@company.xx" }, + { "Santa Claus", "santa.claus@northpole.xx", "Clause", "me@company.xx" }, + { "Charles", "charles@charles.xx", "Charles", "charles@charles.xx" } +}; + +static const mailmap_entry resolved_bare[] = { + { "xx", "untracked@company.xx", "xx", "untracked@company.xx" } +}; + +static const mailmap_entry resolved_untracked[] = { + { "Untracked", "untracked@company.xx", "xx", "untracked@company.xx" } +}; diff --git a/tests/mailmap/parsing.c b/tests/mailmap/parsing.c new file mode 100644 index 000000000..3fda25ff7 --- /dev/null +++ b/tests/mailmap/parsing.c @@ -0,0 +1,123 @@ +#include "clar_libgit2.h" +#include "repository.h" +#include "git2/sys/repository.h" +#include "mailmap_helpers.h" + +static git_repository *g_repo; +static git_mailmap *g_mailmap; + +void test_mailmap_parsing__initialize(void) +{ + g_repo = NULL; + g_mailmap = NULL; +} + +void test_mailmap_parsing__cleanup(void) +{ + cl_git_sandbox_cleanup(); + g_repo = NULL; + + git_mailmap_free(g_mailmap); + g_mailmap = NULL; +} + +static void check_mailmap_entries( + const git_mailmap *mailmap, const mailmap_entry *entries, size_t entries_size) +{ + const mailmap_entry *parsed = NULL; + size_t idx = 0; + + /* Check that the parsed entries match */ + cl_assert_equal_sz(entries_size, git_mailmap_entry_count(mailmap)); + for (idx = 0; idx < entries_size; ++idx) { + parsed = git_mailmap_entry_byindex(mailmap, idx); + cl_assert_equal_s(parsed->real_name, entries[idx].real_name); + cl_assert_equal_s(parsed->real_email, entries[idx].real_email); + cl_assert_equal_s(parsed->replace_name, entries[idx].replace_name); + cl_assert_equal_s(parsed->replace_email, entries[idx].replace_email); + } +} + +static void check_mailmap_resolve( + const git_mailmap *mailmap, const mailmap_entry *resolved, size_t resolved_size) +{ + const char *resolved_name = NULL; + const char *resolved_email = NULL; + size_t idx = 0; + + /* Check that the resolver behaves correctly */ + for (idx = 0; idx < resolved_size; ++idx) { + git_mailmap_resolve( + &resolved_name, + &resolved_email, + mailmap, + resolved[idx].replace_name, + resolved[idx].replace_email); + cl_assert_equal_s(resolved_name, resolved[idx].real_name); + cl_assert_equal_s(resolved_email, resolved[idx].real_email); + } +} + +void test_mailmap_parsing__string(void) +{ + cl_check_pass(git_mailmap_parse( + &g_mailmap, + string_mailmap, + strlen(string_mailmap))); + + /* We should have parsed all of the entries */ + check_mailmap_entries( + g_mailmap, + entries, ARRAY_SIZE(entries)); + + /* Check that resolving the entries works */ + check_mailmap_resolve( + g_mailmap, + resolved, ARRAY_SIZE(resolved)); + check_mailmap_resolve( + g_mailmap, + resolved_untracked, ARRAY_SIZE(resolved_untracked)); +} + +void test_mailmap_parsing__fromrepo(void) +{ + g_repo = cl_git_sandbox_init("mailmap"); + cl_check(!git_repository_is_bare(g_repo)); + + cl_check_pass(git_mailmap_from_repo(&g_mailmap, g_repo)); + + /* We should have parsed all of the entries */ + check_mailmap_entries( + g_mailmap, + entries, ARRAY_SIZE(entries)); + + /* Check that resolving the entries works */ + check_mailmap_resolve( + g_mailmap, + resolved, ARRAY_SIZE(resolved)); + check_mailmap_resolve( + g_mailmap, + resolved_untracked, ARRAY_SIZE(resolved_untracked)); +} + +void test_mailmap_parsing__frombare(void) +{ + g_repo = cl_git_sandbox_init("mailmap/.gitted"); + cl_check_pass(git_repository_set_bare(g_repo)); + cl_check(git_repository_is_bare(g_repo)); + + cl_check_pass(git_mailmap_from_repo(&g_mailmap, g_repo)); + + /* We should have parsed all of the entries, except for the untracked one */ + check_mailmap_entries( + g_mailmap, + entries, ARRAY_SIZE(entries) - 1); + + /* Check that resolving the entries works */ + check_mailmap_resolve( + g_mailmap, + resolved, ARRAY_SIZE(resolved)); + check_mailmap_resolve( + g_mailmap, + resolved_bare, ARRAY_SIZE(resolved_bare)); +} diff --git a/tests/resources/mailmap/.gitted/COMMIT_EDITMSG b/tests/resources/mailmap/.gitted/COMMIT_EDITMSG new file mode 100644 index 000000000..14bee00c0 --- /dev/null +++ b/tests/resources/mailmap/.gitted/COMMIT_EDITMSG @@ -0,0 +1 @@ ++.mailmap diff --git a/tests/resources/mailmap/.gitted/HEAD b/tests/resources/mailmap/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests/resources/mailmap/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/resources/mailmap/.gitted/config b/tests/resources/mailmap/.gitted/config new file mode 100644 index 000000000..515f48362 --- /dev/null +++ b/tests/resources/mailmap/.gitted/config @@ -0,0 +1,5 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true diff --git a/tests/resources/mailmap/.gitted/description b/tests/resources/mailmap/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests/resources/mailmap/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/resources/mailmap/.gitted/hooks/applypatch-msg.sample b/tests/resources/mailmap/.gitted/hooks/applypatch-msg.sample new file mode 100755 index 000000000..a5d7b84a6 --- /dev/null +++ b/tests/resources/mailmap/.gitted/hooks/applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/tests/resources/mailmap/.gitted/hooks/commit-msg.sample b/tests/resources/mailmap/.gitted/hooks/commit-msg.sample new file mode 100755 index 000000000..b58d1184a --- /dev/null +++ b/tests/resources/mailmap/.gitted/hooks/commit-msg.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines. + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + exit 1 +} diff --git a/tests/resources/mailmap/.gitted/hooks/post-update.sample b/tests/resources/mailmap/.gitted/hooks/post-update.sample new file mode 100755 index 000000000..ec17ec193 --- /dev/null +++ b/tests/resources/mailmap/.gitted/hooks/post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/tests/resources/mailmap/.gitted/hooks/pre-applypatch.sample b/tests/resources/mailmap/.gitted/hooks/pre-applypatch.sample new file mode 100755 index 000000000..4142082bc --- /dev/null +++ b/tests/resources/mailmap/.gitted/hooks/pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/tests/resources/mailmap/.gitted/hooks/pre-commit.sample b/tests/resources/mailmap/.gitted/hooks/pre-commit.sample new file mode 100755 index 000000000..68d62d544 --- /dev/null +++ b/tests/resources/mailmap/.gitted/hooks/pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/tests/resources/mailmap/.gitted/hooks/pre-push.sample b/tests/resources/mailmap/.gitted/hooks/pre-push.sample new file mode 100755 index 000000000..6187dbf43 --- /dev/null +++ b/tests/resources/mailmap/.gitted/hooks/pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +z40=0000000000000000000000000000000000000000 + +while read local_ref local_sha remote_ref remote_sha +do + if [ "$local_sha" = $z40 ] + then + # Handle delete + : + else + if [ "$remote_sha" = $z40 ] + then + # New branch, examine all commits + range="$local_sha" + else + # Update to existing branch, examine new commits + range="$remote_sha..$local_sha" + fi + + # Check for WIP commit + commit=`git rev-list -n 1 --grep '^WIP' "$range"` + if [ -n "$commit" ] + then + echo >&2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/tests/resources/mailmap/.gitted/hooks/pre-rebase.sample b/tests/resources/mailmap/.gitted/hooks/pre-rebase.sample new file mode 100755 index 000000000..33730ca64 --- /dev/null +++ b/tests/resources/mailmap/.gitted/hooks/pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up-to-date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/tests/resources/mailmap/.gitted/hooks/pre-receive.sample b/tests/resources/mailmap/.gitted/hooks/pre-receive.sample new file mode 100755 index 000000000..a1fd29ec1 --- /dev/null +++ b/tests/resources/mailmap/.gitted/hooks/pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/tests/resources/mailmap/.gitted/hooks/prepare-commit-msg.sample b/tests/resources/mailmap/.gitted/hooks/prepare-commit-msg.sample new file mode 100755 index 000000000..f093a02ec --- /dev/null +++ b/tests/resources/mailmap/.gitted/hooks/prepare-commit-msg.sample @@ -0,0 +1,36 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first comments out the +# "Conflicts:" part of a merge commit. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +case "$2,$3" in + merge,) + /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;; + +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$1" ;; + + *) ;; +esac + +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" diff --git a/tests/resources/mailmap/.gitted/hooks/update.sample b/tests/resources/mailmap/.gitted/hooks/update.sample new file mode 100755 index 000000000..80ba94135 --- /dev/null +++ b/tests/resources/mailmap/.gitted/hooks/update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --bool hooks.allowunannotated) +allowdeletebranch=$(git config --bool hooks.allowdeletebranch) +denycreatebranch=$(git config --bool hooks.denycreatebranch) +allowdeletetag=$(git config --bool hooks.allowdeletetag) +allowmodifytag=$(git config --bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero="0000000000000000000000000000000000000000" +if [ "$newrev" = "$zero" ]; then + newrev_type=delete +else + newrev_type=$(git cat-file -t $newrev) +fi + +case "$refname","$newrev_type" in + refs/tags/*,commit) + # un-annotated tag + short_refname=${refname##refs/tags/} + if [ "$allowunannotated" != "true" ]; then + echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/tests/resources/mailmap/.gitted/index b/tests/resources/mailmap/.gitted/index new file mode 100644 index 000000000..c46a1b440 Binary files /dev/null and b/tests/resources/mailmap/.gitted/index differ diff --git a/tests/resources/mailmap/.gitted/info/exclude b/tests/resources/mailmap/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests/resources/mailmap/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/resources/mailmap/.gitted/logs/HEAD b/tests/resources/mailmap/.gitted/logs/HEAD new file mode 100644 index 000000000..53945f715 --- /dev/null +++ b/tests/resources/mailmap/.gitted/logs/HEAD @@ -0,0 +1,11 @@ +0000000000000000000000000000000000000000 43179dc93939196f59b25387b5e44e9e8794f84c Nika Layzell 1521306034 -0400 commit (initial): Brad +43179dc93939196f59b25387b5e44e9e8794f84c 3a1295dbc9234c0c5947c72803618c7112a01447 Nika Layzell 1521306086 -0400 commit: Brad L. +3a1295dbc9234c0c5947c72803618c7112a01447 a7054a4b356b3ecdec60cee66e50beaa5b863755 Nika Layzell 1521306181 -0400 commit: Some Dude +a7054a4b356b3ecdec60cee66e50beaa5b863755 95d03c49d94de67d5a05553a1bb22e78f7cdf5ca Nika Layzell 1521306222 -0400 commit: Other Author +95d03c49d94de67d5a05553a1bb22e78f7cdf5ca 1e1212e7674820c17f7b8797aee7bf38ece0e838 Nika Layzell 1521306263 -0400 commit: nick3 +1e1212e7674820c17f7b8797aee7bf38ece0e838 3f134546ae8fbe95a39dd20ea8c12b5fb0f48afb Nika Layzell 1521306341 -0400 commit: Other Author +3f134546ae8fbe95a39dd20ea8c12b5fb0f48afb 50d69f4e64be2cff2cedde8f9b7f970257caf4dd Nika Layzell 1521306417 -0400 commit: Phil Hill +50d69f4e64be2cff2cedde8f9b7f970257caf4dd feef8f2135df4835496e4d576b1f1bd23510e1c5 Nika Layzell 1521306468 -0400 commit: Joseph +feef8f2135df4835496e4d576b1f1bd23510e1c5 7ecbb98d860b304f622b38ce9ab8f08d14d981a8 Nika Layzell 1521306510 -0400 commit: Santa Claus +7ecbb98d860b304f622b38ce9ab8f08d14d981a8 87ce8d4920a30ddb9547334e7c65806518863ff1 Nika Layzell 1521306549 -0400 commit: Charles +87ce8d4920a30ddb9547334e7c65806518863ff1 7100e631fb4d5deba31fdc8acc98f4fb5c1573fd Nika Layzell 1521306767 -0400 commit: +.mailmap diff --git a/tests/resources/mailmap/.gitted/logs/refs/heads/master b/tests/resources/mailmap/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..53945f715 --- /dev/null +++ b/tests/resources/mailmap/.gitted/logs/refs/heads/master @@ -0,0 +1,11 @@ +0000000000000000000000000000000000000000 43179dc93939196f59b25387b5e44e9e8794f84c Nika Layzell 1521306034 -0400 commit (initial): Brad +43179dc93939196f59b25387b5e44e9e8794f84c 3a1295dbc9234c0c5947c72803618c7112a01447 Nika Layzell 1521306086 -0400 commit: Brad L. +3a1295dbc9234c0c5947c72803618c7112a01447 a7054a4b356b3ecdec60cee66e50beaa5b863755 Nika Layzell 1521306181 -0400 commit: Some Dude +a7054a4b356b3ecdec60cee66e50beaa5b863755 95d03c49d94de67d5a05553a1bb22e78f7cdf5ca Nika Layzell 1521306222 -0400 commit: Other Author +95d03c49d94de67d5a05553a1bb22e78f7cdf5ca 1e1212e7674820c17f7b8797aee7bf38ece0e838 Nika Layzell 1521306263 -0400 commit: nick3 +1e1212e7674820c17f7b8797aee7bf38ece0e838 3f134546ae8fbe95a39dd20ea8c12b5fb0f48afb Nika Layzell 1521306341 -0400 commit: Other Author +3f134546ae8fbe95a39dd20ea8c12b5fb0f48afb 50d69f4e64be2cff2cedde8f9b7f970257caf4dd Nika Layzell 1521306417 -0400 commit: Phil Hill +50d69f4e64be2cff2cedde8f9b7f970257caf4dd feef8f2135df4835496e4d576b1f1bd23510e1c5 Nika Layzell 1521306468 -0400 commit: Joseph +feef8f2135df4835496e4d576b1f1bd23510e1c5 7ecbb98d860b304f622b38ce9ab8f08d14d981a8 Nika Layzell 1521306510 -0400 commit: Santa Claus +7ecbb98d860b304f622b38ce9ab8f08d14d981a8 87ce8d4920a30ddb9547334e7c65806518863ff1 Nika Layzell 1521306549 -0400 commit: Charles +87ce8d4920a30ddb9547334e7c65806518863ff1 7100e631fb4d5deba31fdc8acc98f4fb5c1573fd Nika Layzell 1521306767 -0400 commit: +.mailmap diff --git a/tests/resources/mailmap/.gitted/objects/00/1387531bed84262f137837125d4d998a9ba65d b/tests/resources/mailmap/.gitted/objects/00/1387531bed84262f137837125d4d998a9ba65d new file mode 100644 index 000000000..1c564909a Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/00/1387531bed84262f137837125d4d998a9ba65d differ diff --git a/tests/resources/mailmap/.gitted/objects/02/7b2816ae0d7a08ba656d0417c09b4eac18cf00 b/tests/resources/mailmap/.gitted/objects/02/7b2816ae0d7a08ba656d0417c09b4eac18cf00 new file mode 100644 index 000000000..a4e8249af Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/02/7b2816ae0d7a08ba656d0417c09b4eac18cf00 differ diff --git a/tests/resources/mailmap/.gitted/objects/09/20975110511365e56aec2263082d0c3d56d1fa b/tests/resources/mailmap/.gitted/objects/09/20975110511365e56aec2263082d0c3d56d1fa new file mode 100644 index 000000000..49bceea46 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/09/20975110511365e56aec2263082d0c3d56d1fa differ diff --git a/tests/resources/mailmap/.gitted/objects/0c/d99501dfbec781a22ff7b84426b7bb308e709a b/tests/resources/mailmap/.gitted/objects/0c/d99501dfbec781a22ff7b84426b7bb308e709a new file mode 100644 index 000000000..23149a4ee Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/0c/d99501dfbec781a22ff7b84426b7bb308e709a differ diff --git a/tests/resources/mailmap/.gitted/objects/1e/1212e7674820c17f7b8797aee7bf38ece0e838 b/tests/resources/mailmap/.gitted/objects/1e/1212e7674820c17f7b8797aee7bf38ece0e838 new file mode 100644 index 000000000..89a859807 --- /dev/null +++ b/tests/resources/mailmap/.gitted/objects/1e/1212e7674820c17f7b8797aee7bf38ece0e838 @@ -0,0 +1,2 @@ +xu] +0})f7iZ(;l#5zz |LDZ/@B:i8bc163,:h|BIKZ,49Ĕ}#rxeh~x{>`=YƊ*-:D뱢 Q^ohUEq߭3d>I \ No newline at end of file diff --git a/tests/resources/mailmap/.gitted/objects/36/370b71f5aad1dd46bec5e14145280a843c9f49 b/tests/resources/mailmap/.gitted/objects/36/370b71f5aad1dd46bec5e14145280a843c9f49 new file mode 100644 index 000000000..5e8e3e596 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/36/370b71f5aad1dd46bec5e14145280a843c9f49 differ diff --git a/tests/resources/mailmap/.gitted/objects/3a/1295dbc9234c0c5947c72803618c7112a01447 b/tests/resources/mailmap/.gitted/objects/3a/1295dbc9234c0c5947c72803618c7112a01447 new file mode 100644 index 000000000..347828cb6 --- /dev/null +++ b/tests/resources/mailmap/.gitted/objects/3a/1295dbc9234c0c5947c72803618c7112a01447 @@ -0,0 +1,2 @@ +xmA +0D]$m(";$??(-dV34*(V0.>H #TQEeNd+"t]j]P}hvl{g5$s]0P[yVRY?<0̋#,?s!5_ԏ$^H \ No newline at end of file diff --git a/tests/resources/mailmap/.gitted/objects/3f/134546ae8fbe95a39dd20ea8c12b5fb0f48afb b/tests/resources/mailmap/.gitted/objects/3f/134546ae8fbe95a39dd20ea8c12b5fb0f48afb new file mode 100644 index 000000000..489c6104d --- /dev/null +++ b/tests/resources/mailmap/.gitted/objects/3f/134546ae8fbe95a39dd20ea8c12b5fb0f48afb @@ -0,0 +1,3 @@ +xmMn0) {lbGB(Teqcd\ zze^H<@s("6<{5G[t6PkqK +mq(zg[K̶"Kv -; ʞ~FBﴼ 6 +vH)jX5iZёri3Zp֏iUeoO \ No newline at end of file diff --git a/tests/resources/mailmap/.gitted/objects/43/179dc93939196f59b25387b5e44e9e8794f84c b/tests/resources/mailmap/.gitted/objects/43/179dc93939196f59b25387b5e44e9e8794f84c new file mode 100644 index 000000000..2f3693aa6 --- /dev/null +++ b/tests/resources/mailmap/.gitted/objects/43/179dc93939196f59b25387b5e44e9e8794f84c @@ -0,0 +1,2 @@ +xmA +0P9\4"ŵx1bHzzp?l aP6.'f-+ԕcU-:|ƋLCA<D:coc 7bYP5^¾ D듧 yK}xb_ˈA: \ No newline at end of file diff --git a/tests/resources/mailmap/.gitted/objects/46/b5bb908c78b575cac9f9e6e42ff9ba3f769a46 b/tests/resources/mailmap/.gitted/objects/46/b5bb908c78b575cac9f9e6e42ff9ba3f769a46 new file mode 100644 index 000000000..62c9db041 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/46/b5bb908c78b575cac9f9e6e42ff9ba3f769a46 differ diff --git a/tests/resources/mailmap/.gitted/objects/4b/4d2010ba256ef339c1d1854d20249da7478f01 b/tests/resources/mailmap/.gitted/objects/4b/4d2010ba256ef339c1d1854d20249da7478f01 new file mode 100644 index 000000000..169c7e7b4 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/4b/4d2010ba256ef339c1d1854d20249da7478f01 differ diff --git a/tests/resources/mailmap/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 b/tests/resources/mailmap/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 new file mode 100644 index 000000000..adf64119a Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 differ diff --git a/tests/resources/mailmap/.gitted/objects/4d/61d588546529ad27b2d77a3d6b05460ecb4be0 b/tests/resources/mailmap/.gitted/objects/4d/61d588546529ad27b2d77a3d6b05460ecb4be0 new file mode 100644 index 000000000..dabbf4ef3 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/4d/61d588546529ad27b2d77a3d6b05460ecb4be0 differ diff --git a/tests/resources/mailmap/.gitted/objects/50/d69f4e64be2cff2cedde8f9b7f970257caf4dd b/tests/resources/mailmap/.gitted/objects/50/d69f4e64be2cff2cedde8f9b7f970257caf4dd new file mode 100644 index 000000000..e6b337e1e --- /dev/null +++ b/tests/resources/mailmap/.gitted/objects/50/d69f4e64be2cff2cedde8f9b7f970257caf4dd @@ -0,0 +1 @@ +xmMj0) HcBY+6e(Qt~>y m>&&ޓ=gOĞR Bֹ6Zy\&c%(-mp FJQ'8Eŷ2,%/ uS+8!4V7xiaVdϗLrU2k\z`KN \ No newline at end of file diff --git a/tests/resources/mailmap/.gitted/objects/61/293f4c3d7500d227a755a7a8258e28e53449b2 b/tests/resources/mailmap/.gitted/objects/61/293f4c3d7500d227a755a7a8258e28e53449b2 new file mode 100644 index 000000000..409e6fd74 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/61/293f4c3d7500d227a755a7a8258e28e53449b2 differ diff --git a/tests/resources/mailmap/.gitted/objects/62/7f0bd2f4fb5e949b79ba450d84676fa876b1c8 b/tests/resources/mailmap/.gitted/objects/62/7f0bd2f4fb5e949b79ba450d84676fa876b1c8 new file mode 100644 index 000000000..6009c30cd Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/62/7f0bd2f4fb5e949b79ba450d84676fa876b1c8 differ diff --git a/tests/resources/mailmap/.gitted/objects/68/dfd5e5cb6138488680246d134f47ce559f4cf1 b/tests/resources/mailmap/.gitted/objects/68/dfd5e5cb6138488680246d134f47ce559f4cf1 new file mode 100644 index 000000000..ac5229f73 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/68/dfd5e5cb6138488680246d134f47ce559f4cf1 differ diff --git a/tests/resources/mailmap/.gitted/objects/6c/dec08ab9bfcd5a3d889f27bbed650317e3ec13 b/tests/resources/mailmap/.gitted/objects/6c/dec08ab9bfcd5a3d889f27bbed650317e3ec13 new file mode 100644 index 000000000..856ba31f0 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/6c/dec08ab9bfcd5a3d889f27bbed650317e3ec13 differ diff --git a/tests/resources/mailmap/.gitted/objects/71/00e631fb4d5deba31fdc8acc98f4fb5c1573fd b/tests/resources/mailmap/.gitted/objects/71/00e631fb4d5deba31fdc8acc98f4fb5c1573fd new file mode 100644 index 000000000..3b20e6df2 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/71/00e631fb4d5deba31fdc8acc98f4fb5c1573fd differ diff --git a/tests/resources/mailmap/.gitted/objects/7e/cbb98d860b304f622b38ce9ab8f08d14d981a8 b/tests/resources/mailmap/.gitted/objects/7e/cbb98d860b304f622b38ce9ab8f08d14d981a8 new file mode 100644 index 000000000..53e775ee4 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/7e/cbb98d860b304f622b38ce9ab8f08d14d981a8 differ diff --git a/tests/resources/mailmap/.gitted/objects/7e/e7b9a4a2a1eda925f6260338c063d8211d5ad5 b/tests/resources/mailmap/.gitted/objects/7e/e7b9a4a2a1eda925f6260338c063d8211d5ad5 new file mode 100644 index 000000000..0d4e94b29 --- /dev/null +++ b/tests/resources/mailmap/.gitted/objects/7e/e7b9a4a2a1eda925f6260338c063d8211d5ad5 @@ -0,0 +1,2 @@ +x +0D=+z* =~AFMMA޴m'sag+ XgEB[o$dtF;0(d=wb\R8k̫('8-Xޚk: 9ʋGm r</ ]hHS?9.p o3KљQ'" \ No newline at end of file diff --git a/tests/resources/mailmap/.gitted/objects/83/714a9223f3e072b85f0d4301cd2081fff3acf2 b/tests/resources/mailmap/.gitted/objects/83/714a9223f3e072b85f0d4301cd2081fff3acf2 new file mode 100644 index 000000000..a50f87e48 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/83/714a9223f3e072b85f0d4301cd2081fff3acf2 differ diff --git a/tests/resources/mailmap/.gitted/objects/87/ce8d4920a30ddb9547334e7c65806518863ff1 b/tests/resources/mailmap/.gitted/objects/87/ce8d4920a30ddb9547334e7c65806518863ff1 new file mode 100644 index 000000000..b8c480805 --- /dev/null +++ b/tests/resources/mailmap/.gitted/objects/87/ce8d4920a30ddb9547334e7c65806518863ff1 @@ -0,0 +1,2 @@ +x}NKjC1 ڧd?=[PݖAe^KRt5f)0 >n1ZCeʚ +XbM8E݇t; HVT3WR!Ų(7fN>rH_ _^'3e !nXûܾl]awXl}=GW=MV \ No newline at end of file diff --git a/tests/resources/mailmap/.gitted/objects/8c/f0547fcb649b44ebaf39b8104982bb0abb4e69 b/tests/resources/mailmap/.gitted/objects/8c/f0547fcb649b44ebaf39b8104982bb0abb4e69 new file mode 100644 index 000000000..402a48e79 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/8c/f0547fcb649b44ebaf39b8104982bb0abb4e69 differ diff --git a/tests/resources/mailmap/.gitted/objects/94/7ff75c33ac7941a32fe9900118b6ba85ab2be9 b/tests/resources/mailmap/.gitted/objects/94/7ff75c33ac7941a32fe9900118b6ba85ab2be9 new file mode 100644 index 000000000..8b23320fd Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/94/7ff75c33ac7941a32fe9900118b6ba85ab2be9 differ diff --git a/tests/resources/mailmap/.gitted/objects/95/d03c49d94de67d5a05553a1bb22e78f7cdf5ca b/tests/resources/mailmap/.gitted/objects/95/d03c49d94de67d5a05553a1bb22e78f7cdf5ca new file mode 100644 index 000000000..cd91a3f8c --- /dev/null +++ b/tests/resources/mailmap/.gitted/objects/95/d03c49d94de67d5a05553a1bb22e78f7cdf5ca @@ -0,0 +1 @@ +xmKn0 D)x$R`h@tcğ@Qo7۲L/B Ad;s7I؏2.Vh1p$^fYHъ2t#[=m)ry[.>%`ia;Vtfǯ3kSC=CxWs|L \ No newline at end of file diff --git a/tests/resources/mailmap/.gitted/objects/96/78a4325710507f7bf598a0fde5ebbd88148614 b/tests/resources/mailmap/.gitted/objects/96/78a4325710507f7bf598a0fde5ebbd88148614 new file mode 100644 index 000000000..887436602 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/96/78a4325710507f7bf598a0fde5ebbd88148614 differ diff --git a/tests/resources/mailmap/.gitted/objects/a1/6db1cbb8817dddcf199c12d3c81221cf8eefc4 b/tests/resources/mailmap/.gitted/objects/a1/6db1cbb8817dddcf199c12d3c81221cf8eefc4 new file mode 100644 index 000000000..d23d8cc5f --- /dev/null +++ b/tests/resources/mailmap/.gitted/objects/a1/6db1cbb8817dddcf199c12d3c81221cf8eefc4 @@ -0,0 +1 @@ +x+)JMU06c040031QHI+(aUإV_+ \ No newline at end of file diff --git a/tests/resources/mailmap/.gitted/objects/a7/054a4b356b3ecdec60cee66e50beaa5b863755 b/tests/resources/mailmap/.gitted/objects/a7/054a4b356b3ecdec60cee66e50beaa5b863755 new file mode 100644 index 000000000..06a3abc4f --- /dev/null +++ b/tests/resources/mailmap/.gitted/objects/a7/054a4b356b3ecdec60cee66e50beaa5b863755 @@ -0,0 +1,3 @@ +xmNKj0Z 4I`]lz44&[Jٽ/e +G]E$|bIH]. 1!ՍW+&]I9jc3f^4G +iF+eYaKe8' `|ETlǪp qnn_vh7uL_{zPG \ No newline at end of file diff --git a/tests/resources/mailmap/.gitted/objects/a7/eb40274887baeb01a958ead80d106b5977312c b/tests/resources/mailmap/.gitted/objects/a7/eb40274887baeb01a958ead80d106b5977312c new file mode 100644 index 000000000..39f70c203 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/a7/eb40274887baeb01a958ead80d106b5977312c differ diff --git a/tests/resources/mailmap/.gitted/objects/c9/e5462de8ec453e94d85f26f64b80ea76fda6d4 b/tests/resources/mailmap/.gitted/objects/c9/e5462de8ec453e94d85f26f64b80ea76fda6d4 new file mode 100644 index 000000000..dbf952372 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/c9/e5462de8ec453e94d85f26f64b80ea76fda6d4 differ diff --git a/tests/resources/mailmap/.gitted/objects/d3/e5e624cc7bfb09ac1960ebb6c458021b098f87 b/tests/resources/mailmap/.gitted/objects/d3/e5e624cc7bfb09ac1960ebb6c458021b098f87 new file mode 100644 index 000000000..c69ebe842 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/d3/e5e624cc7bfb09ac1960ebb6c458021b098f87 differ diff --git a/tests/resources/mailmap/.gitted/objects/fe/dd34e8baffdb2acfe9a6860bf339287ca942bc b/tests/resources/mailmap/.gitted/objects/fe/dd34e8baffdb2acfe9a6860bf339287ca942bc new file mode 100644 index 000000000..a13b83df8 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/fe/dd34e8baffdb2acfe9a6860bf339287ca942bc differ diff --git a/tests/resources/mailmap/.gitted/objects/fe/ef8f2135df4835496e4d576b1f1bd23510e1c5 b/tests/resources/mailmap/.gitted/objects/fe/ef8f2135df4835496e4d576b1f1bd23510e1c5 new file mode 100644 index 000000000..31f979bc1 --- /dev/null +++ b/tests/resources/mailmap/.gitted/objects/fe/ef8f2135df4835496e4d576b1f1bd23510e1c5 @@ -0,0 +1 @@ +xmK1]u%J 22/#7(4 ,`2x-QR) -+Thu#Aیi᱀U똳7 >^j#eLIЭti幃}}8 3jeCVYΗ=:j%]Ŀ,pK \ No newline at end of file diff --git a/tests/resources/mailmap/.gitted/refs/heads/master b/tests/resources/mailmap/.gitted/refs/heads/master new file mode 100644 index 000000000..0daf56a2e --- /dev/null +++ b/tests/resources/mailmap/.gitted/refs/heads/master @@ -0,0 +1 @@ +7100e631fb4d5deba31fdc8acc98f4fb5c1573fd diff --git a/tests/resources/mailmap/.mailmap b/tests/resources/mailmap/.mailmap new file mode 100644 index 000000000..7da2ed605 --- /dev/null +++ b/tests/resources/mailmap/.mailmap @@ -0,0 +1,9 @@ +# Simple Comment line + +Some Dude nick1 +Other Author nick2 +Other Author +Phil Hill # Comment at end of line + Joseph +Santa Claus +Untracked diff --git a/tests/resources/mailmap/file.txt b/tests/resources/mailmap/file.txt new file mode 100644 index 000000000..68dfd5e5c --- /dev/null +++ b/tests/resources/mailmap/file.txt @@ -0,0 +1,10 @@ +Added by Brad +Added by Brad L. +Added by nick1 +Added by nick2 +Added by nick3 +Added by Some Garbage +Added by unknown +Added by Joseph +Added by Clause +Added by Charles -- cgit v1.2.1 From 4ff44be8ce36b345340eea962d9df8a595c1c0bf Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sat, 17 Mar 2018 18:24:15 -0400 Subject: mailmap: Fix more bugs which snuck in when I rebased --- include/git2/mailmap.h | 4 ++-- src/blame.c | 1 + src/mailmap.c | 4 ++-- tests/mailmap/basic.c | 8 ++++---- tests/mailmap/blame.c | 1 - tests/mailmap/parsing.c | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/git2/mailmap.h b/include/git2/mailmap.h index a80ecb970..0c722b549 100644 --- a/include/git2/mailmap.h +++ b/include/git2/mailmap.h @@ -22,14 +22,14 @@ GIT_BEGIN_DECL /** * A single entry parsed from a mailmap. */ -struct git_mailmap_entry { +typedef struct git_mailmap_entry { unsigned int version; const char *real_name; /**< the real name (may be NULL) */ const char *real_email; /**< the real email (may be NULL) */ const char *replace_name; /**< the name to replace (may be NULL) */ const char *replace_email; /**< the email to replace */ -}; +} git_mailmap_entry; #define GIT_MAILMAP_ENTRY_VERSION 1 #define GIT_MAILMAP_ENTRY_INIT {GIT_MAILMAP_ENTRY_VERSION} diff --git a/src/blame.c b/src/blame.c index 967530b7e..0624bf4f6 100644 --- a/src/blame.c +++ b/src/blame.c @@ -14,6 +14,7 @@ #include "git2/diff.h" #include "git2/blob.h" #include "git2/signature.h" +#include "git2/mailmap.h" #include "util.h" #include "repository.h" #include "blame_git.h" diff --git a/src/mailmap.c b/src/mailmap.c index aaf5446f2..c0da98d48 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -215,7 +215,7 @@ int git_mailmap_parse( cleanup: git__free(entry); - if (error < 0) + if (error < 0) { git_mailmap_free(*mailmap); *mailmap = NULL; } @@ -317,7 +317,7 @@ static int git_mailmap_from_bare_repo( error = git_object_lookup_bypath( (git_object **) &blob, - treeish, + tree, ".mailmap", GIT_OBJ_BLOB); if (error < 0) diff --git a/tests/mailmap/basic.c b/tests/mailmap/basic.c index b507407a5..10fc30bdd 100644 --- a/tests/mailmap/basic.c +++ b/tests/mailmap/basic.c @@ -15,7 +15,7 @@ const char TEST_MAILMAP[] = void test_mailmap_basic__initialize(void) { - cl_git_pass(git_mailmap_parse(&mailmap, TEST_MAILMAP, sizeof(TEST_MAILMAP))); + cl_git_pass(git_mailmap_parse(&mailmap, TEST_MAILMAP, sizeof(TEST_MAILMAP) - 1)); } void test_mailmap_basic__cleanup(void) @@ -28,7 +28,7 @@ void test_mailmap_basic__cleanup(void) void test_mailmap_basic__entry(void) { - git_mailmap_entry* entry; + const git_mailmap_entry* entry; cl_assert(git_mailmap_entry_count(mailmap) == 4); @@ -43,7 +43,7 @@ void test_mailmap_basic__entry(void) void test_mailmap_basic__lookup_not_found(void) { - git_mailmap_entry* entry = git_mailmap_entry_lookup( + const git_mailmap_entry* entry = git_mailmap_entry_lookup( mailmap, "Whoever", "doesnotexist@fo.com"); @@ -52,7 +52,7 @@ void test_mailmap_basic__lookup_not_found(void) void test_mailmap_basic__lookup(void) { - git_mailmap_entry* entry = git_mailmap_entry_lookup( + const git_mailmap_entry* entry = git_mailmap_entry_lookup( mailmap, "Typoed the name once", "foo@baz.com"); diff --git a/tests/mailmap/blame.c b/tests/mailmap/blame.c index 2dd309588..45e9812a8 100644 --- a/tests/mailmap/blame.c +++ b/tests/mailmap/blame.c @@ -6,7 +6,6 @@ static git_repository *g_repo; static git_blame *g_blame; -static git_mailmap *g_mailmap; void test_mailmap_blame__initialize(void) { diff --git a/tests/mailmap/parsing.c b/tests/mailmap/parsing.c index 3fda25ff7..a81f2f9bf 100644 --- a/tests/mailmap/parsing.c +++ b/tests/mailmap/parsing.c @@ -24,7 +24,7 @@ void test_mailmap_parsing__cleanup(void) static void check_mailmap_entries( const git_mailmap *mailmap, const mailmap_entry *entries, size_t entries_size) { - const mailmap_entry *parsed = NULL; + const git_mailmap_entry *parsed = NULL; size_t idx = 0; /* Check that the parsed entries match */ -- cgit v1.2.1 From 5c6c8a9b50ca838013bc7b4197f7e86d7ac4027a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 18 Mar 2018 01:26:30 +0100 Subject: mailmap: Fix some other minor style nits --- include/git2/signature.h | 3 +-- tests/mailmap/basic.c | 14 +++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/include/git2/signature.h b/include/git2/signature.h index 18fae98c2..981a4f1c3 100644 --- a/include/git2/signature.h +++ b/include/git2/signature.h @@ -85,8 +85,7 @@ GIT_EXTERN(int) git_signature_from_buffer(git_signature **out, const char *buf); * @param mailmap mailmap to resolve with * @return 0 or an error code */ -GIT_EXTERN(int) git_signature_with_mailmap( - git_signature **out, const git_signature *sig, const git_mailmap *mailmap); +GIT_EXTERN(int) git_signature_with_mailmap(git_signature **out, const git_signature *sig, const git_mailmap *mailmap); /** * Create a copy of an existing signature. All internal strings are also diff --git a/tests/mailmap/basic.c b/tests/mailmap/basic.c index 10fc30bdd..9b06f184d 100644 --- a/tests/mailmap/basic.c +++ b/tests/mailmap/basic.c @@ -28,7 +28,7 @@ void test_mailmap_basic__cleanup(void) void test_mailmap_basic__entry(void) { - const git_mailmap_entry* entry; + const git_mailmap_entry *entry; cl_assert(git_mailmap_entry_count(mailmap) == 4); @@ -43,7 +43,7 @@ void test_mailmap_basic__entry(void) void test_mailmap_basic__lookup_not_found(void) { - const git_mailmap_entry* entry = git_mailmap_entry_lookup( + const git_mailmap_entry *entry = git_mailmap_entry_lookup( mailmap, "Whoever", "doesnotexist@fo.com"); @@ -52,7 +52,7 @@ void test_mailmap_basic__lookup_not_found(void) void test_mailmap_basic__lookup(void) { - const git_mailmap_entry* entry = git_mailmap_entry_lookup( + const git_mailmap_entry *entry = git_mailmap_entry_lookup( mailmap, "Typoed the name once", "foo@baz.com"); @@ -62,8 +62,8 @@ void test_mailmap_basic__lookup(void) void test_mailmap_basic__empty_email_query(void) { - const char* name; - const char* email; + const char *name; + const char *email; git_mailmap_resolve( &name, &email, @@ -76,8 +76,8 @@ void test_mailmap_basic__empty_email_query(void) void test_mailmap_basic__name_matching(void) { - const char* name; - const char* email; + const char *name; + const char *email; git_mailmap_resolve( &name, &email, -- cgit v1.2.1 From aa3a24a4682c7896024b87873f2cfa6cea3dd24d Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Mon, 26 Mar 2018 14:44:15 -0400 Subject: mailmap: Clean up the mailmap fixture's .gitted directory --- tests/resources/mailmap/.gitted/COMMIT_EDITMSG | 1 - .../mailmap/.gitted/hooks/applypatch-msg.sample | 15 -- .../mailmap/.gitted/hooks/commit-msg.sample | 24 --- .../mailmap/.gitted/hooks/post-update.sample | 8 - .../mailmap/.gitted/hooks/pre-applypatch.sample | 14 -- .../mailmap/.gitted/hooks/pre-commit.sample | 49 ------ .../mailmap/.gitted/hooks/pre-push.sample | 53 ------- .../mailmap/.gitted/hooks/pre-rebase.sample | 169 --------------------- .../mailmap/.gitted/hooks/pre-receive.sample | 24 --- .../.gitted/hooks/prepare-commit-msg.sample | 36 ----- .../resources/mailmap/.gitted/hooks/update.sample | 128 ---------------- tests/resources/mailmap/.gitted/logs/HEAD | 11 -- .../mailmap/.gitted/logs/refs/heads/master | 11 -- 13 files changed, 543 deletions(-) delete mode 100644 tests/resources/mailmap/.gitted/COMMIT_EDITMSG delete mode 100755 tests/resources/mailmap/.gitted/hooks/applypatch-msg.sample delete mode 100755 tests/resources/mailmap/.gitted/hooks/commit-msg.sample delete mode 100755 tests/resources/mailmap/.gitted/hooks/post-update.sample delete mode 100755 tests/resources/mailmap/.gitted/hooks/pre-applypatch.sample delete mode 100755 tests/resources/mailmap/.gitted/hooks/pre-commit.sample delete mode 100755 tests/resources/mailmap/.gitted/hooks/pre-push.sample delete mode 100755 tests/resources/mailmap/.gitted/hooks/pre-rebase.sample delete mode 100755 tests/resources/mailmap/.gitted/hooks/pre-receive.sample delete mode 100755 tests/resources/mailmap/.gitted/hooks/prepare-commit-msg.sample delete mode 100755 tests/resources/mailmap/.gitted/hooks/update.sample delete mode 100644 tests/resources/mailmap/.gitted/logs/HEAD delete mode 100644 tests/resources/mailmap/.gitted/logs/refs/heads/master diff --git a/tests/resources/mailmap/.gitted/COMMIT_EDITMSG b/tests/resources/mailmap/.gitted/COMMIT_EDITMSG deleted file mode 100644 index 14bee00c0..000000000 --- a/tests/resources/mailmap/.gitted/COMMIT_EDITMSG +++ /dev/null @@ -1 +0,0 @@ -+.mailmap diff --git a/tests/resources/mailmap/.gitted/hooks/applypatch-msg.sample b/tests/resources/mailmap/.gitted/hooks/applypatch-msg.sample deleted file mode 100755 index a5d7b84a6..000000000 --- a/tests/resources/mailmap/.gitted/hooks/applypatch-msg.sample +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message taken by -# applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. The hook is -# allowed to edit the commit message file. -# -# To enable this hook, rename this file to "applypatch-msg". - -. git-sh-setup -commitmsg="$(git rev-parse --git-path hooks/commit-msg)" -test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} -: diff --git a/tests/resources/mailmap/.gitted/hooks/commit-msg.sample b/tests/resources/mailmap/.gitted/hooks/commit-msg.sample deleted file mode 100755 index b58d1184a..000000000 --- a/tests/resources/mailmap/.gitted/hooks/commit-msg.sample +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# -# An example hook script to check the commit log message. -# Called by "git commit" with one argument, the name of the file -# that has the commit message. The hook should exit with non-zero -# status after issuing an appropriate message if it wants to stop the -# commit. The hook is allowed to edit the commit message file. -# -# To enable this hook, rename this file to "commit-msg". - -# Uncomment the below to add a Signed-off-by line to the message. -# Doing this in a hook is a bad idea in general, but the prepare-commit-msg -# hook is more suited to it. -# -# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" - -# This example catches duplicate Signed-off-by lines. - -test "" = "$(grep '^Signed-off-by: ' "$1" | - sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { - echo >&2 Duplicate Signed-off-by lines. - exit 1 -} diff --git a/tests/resources/mailmap/.gitted/hooks/post-update.sample b/tests/resources/mailmap/.gitted/hooks/post-update.sample deleted file mode 100755 index ec17ec193..000000000 --- a/tests/resources/mailmap/.gitted/hooks/post-update.sample +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare a packed repository for use over -# dumb transports. -# -# To enable this hook, rename this file to "post-update". - -exec git update-server-info diff --git a/tests/resources/mailmap/.gitted/hooks/pre-applypatch.sample b/tests/resources/mailmap/.gitted/hooks/pre-applypatch.sample deleted file mode 100755 index 4142082bc..000000000 --- a/tests/resources/mailmap/.gitted/hooks/pre-applypatch.sample +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed -# by applypatch from an e-mail message. -# -# The hook should exit with non-zero status after issuing an -# appropriate message if it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-applypatch". - -. git-sh-setup -precommit="$(git rev-parse --git-path hooks/pre-commit)" -test -x "$precommit" && exec "$precommit" ${1+"$@"} -: diff --git a/tests/resources/mailmap/.gitted/hooks/pre-commit.sample b/tests/resources/mailmap/.gitted/hooks/pre-commit.sample deleted file mode 100755 index 68d62d544..000000000 --- a/tests/resources/mailmap/.gitted/hooks/pre-commit.sample +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -# -# An example hook script to verify what is about to be committed. -# Called by "git commit" with no arguments. The hook should -# exit with non-zero status after issuing an appropriate message if -# it wants to stop the commit. -# -# To enable this hook, rename this file to "pre-commit". - -if git rev-parse --verify HEAD >/dev/null 2>&1 -then - against=HEAD -else - # Initial commit: diff against an empty tree object - against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 -fi - -# If you want to allow non-ASCII filenames set this variable to true. -allownonascii=$(git config --bool hooks.allownonascii) - -# Redirect output to stderr. -exec 1>&2 - -# Cross platform projects tend to avoid non-ASCII filenames; prevent -# them from being added to the repository. We exploit the fact that the -# printable range starts at the space character and ends with tilde. -if [ "$allownonascii" != "true" ] && - # Note that the use of brackets around a tr range is ok here, (it's - # even required, for portability to Solaris 10's /usr/bin/tr), since - # the square bracket bytes happen to fall in the designated range. - test $(git diff --cached --name-only --diff-filter=A -z $against | - LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 -then - cat <<\EOF -Error: Attempt to add a non-ASCII file name. - -This can cause problems if you want to work with people on other platforms. - -To be portable it is advisable to rename the file. - -If you know what you are doing you can disable this check using: - - git config hooks.allownonascii true -EOF - exit 1 -fi - -# If there are whitespace errors, print the offending file names and fail. -exec git diff-index --check --cached $against -- diff --git a/tests/resources/mailmap/.gitted/hooks/pre-push.sample b/tests/resources/mailmap/.gitted/hooks/pre-push.sample deleted file mode 100755 index 6187dbf43..000000000 --- a/tests/resources/mailmap/.gitted/hooks/pre-push.sample +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/sh - -# An example hook script to verify what is about to be pushed. Called by "git -# push" after it has checked the remote status, but before anything has been -# pushed. If this script exits with a non-zero status nothing will be pushed. -# -# This hook is called with the following parameters: -# -# $1 -- Name of the remote to which the push is being done -# $2 -- URL to which the push is being done -# -# If pushing without using a named remote those arguments will be equal. -# -# Information about the commits which are being pushed is supplied as lines to -# the standard input in the form: -# -# -# -# This sample shows how to prevent push of commits where the log message starts -# with "WIP" (work in progress). - -remote="$1" -url="$2" - -z40=0000000000000000000000000000000000000000 - -while read local_ref local_sha remote_ref remote_sha -do - if [ "$local_sha" = $z40 ] - then - # Handle delete - : - else - if [ "$remote_sha" = $z40 ] - then - # New branch, examine all commits - range="$local_sha" - else - # Update to existing branch, examine new commits - range="$remote_sha..$local_sha" - fi - - # Check for WIP commit - commit=`git rev-list -n 1 --grep '^WIP' "$range"` - if [ -n "$commit" ] - then - echo >&2 "Found WIP commit in $local_ref, not pushing" - exit 1 - fi - fi -done - -exit 0 diff --git a/tests/resources/mailmap/.gitted/hooks/pre-rebase.sample b/tests/resources/mailmap/.gitted/hooks/pre-rebase.sample deleted file mode 100755 index 33730ca64..000000000 --- a/tests/resources/mailmap/.gitted/hooks/pre-rebase.sample +++ /dev/null @@ -1,169 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2006, 2008 Junio C Hamano -# -# The "pre-rebase" hook is run just before "git rebase" starts doing -# its job, and can prevent the command from running by exiting with -# non-zero status. -# -# The hook is called with the following parameters: -# -# $1 -- the upstream the series was forked from. -# $2 -- the branch being rebased (or empty when rebasing the current branch). -# -# This sample shows how to prevent topic branches that are already -# merged to 'next' branch from getting rebased, because allowing it -# would result in rebasing already published history. - -publish=next -basebranch="$1" -if test "$#" = 2 -then - topic="refs/heads/$2" -else - topic=`git symbolic-ref HEAD` || - exit 0 ;# we do not interrupt rebasing detached HEAD -fi - -case "$topic" in -refs/heads/??/*) - ;; -*) - exit 0 ;# we do not interrupt others. - ;; -esac - -# Now we are dealing with a topic branch being rebased -# on top of master. Is it OK to rebase it? - -# Does the topic really exist? -git show-ref -q "$topic" || { - echo >&2 "No such branch $topic" - exit 1 -} - -# Is topic fully merged to master? -not_in_master=`git rev-list --pretty=oneline ^master "$topic"` -if test -z "$not_in_master" -then - echo >&2 "$topic is fully merged to master; better remove it." - exit 1 ;# we could allow it, but there is no point. -fi - -# Is topic ever merged to next? If so you should not be rebasing it. -only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` -only_next_2=`git rev-list ^master ${publish} | sort` -if test "$only_next_1" = "$only_next_2" -then - not_in_topic=`git rev-list "^$topic" master` - if test -z "$not_in_topic" - then - echo >&2 "$topic is already up-to-date with master" - exit 1 ;# we could allow it, but there is no point. - else - exit 0 - fi -else - not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` - /usr/bin/perl -e ' - my $topic = $ARGV[0]; - my $msg = "* $topic has commits already merged to public branch:\n"; - my (%not_in_next) = map { - /^([0-9a-f]+) /; - ($1 => 1); - } split(/\n/, $ARGV[1]); - for my $elem (map { - /^([0-9a-f]+) (.*)$/; - [$1 => $2]; - } split(/\n/, $ARGV[2])) { - if (!exists $not_in_next{$elem->[0]}) { - if ($msg) { - print STDERR $msg; - undef $msg; - } - print STDERR " $elem->[1]\n"; - } - } - ' "$topic" "$not_in_next" "$not_in_master" - exit 1 -fi - -<<\DOC_END - -This sample hook safeguards topic branches that have been -published from being rewound. - -The workflow assumed here is: - - * Once a topic branch forks from "master", "master" is never - merged into it again (either directly or indirectly). - - * Once a topic branch is fully cooked and merged into "master", - it is deleted. If you need to build on top of it to correct - earlier mistakes, a new topic branch is created by forking at - the tip of the "master". This is not strictly necessary, but - it makes it easier to keep your history simple. - - * Whenever you need to test or publish your changes to topic - branches, merge them into "next" branch. - -The script, being an example, hardcodes the publish branch name -to be "next", but it is trivial to make it configurable via -$GIT_DIR/config mechanism. - -With this workflow, you would want to know: - -(1) ... if a topic branch has ever been merged to "next". Young - topic branches can have stupid mistakes you would rather - clean up before publishing, and things that have not been - merged into other branches can be easily rebased without - affecting other people. But once it is published, you would - not want to rewind it. - -(2) ... if a topic branch has been fully merged to "master". - Then you can delete it. More importantly, you should not - build on top of it -- other people may already want to - change things related to the topic as patches against your - "master", so if you need further changes, it is better to - fork the topic (perhaps with the same name) afresh from the - tip of "master". - -Let's look at this example: - - o---o---o---o---o---o---o---o---o---o "next" - / / / / - / a---a---b A / / - / / / / - / / c---c---c---c B / - / / / \ / - / / / b---b C \ / - / / / / \ / - ---o---o---o---o---o---o---o---o---o---o---o "master" - - -A, B and C are topic branches. - - * A has one fix since it was merged up to "next". - - * B has finished. It has been fully merged up to "master" and "next", - and is ready to be deleted. - - * C has not merged to "next" at all. - -We would want to allow C to be rebased, refuse A, and encourage -B to be deleted. - -To compute (1): - - git rev-list ^master ^topic next - git rev-list ^master next - - if these match, topic has not merged in next at all. - -To compute (2): - - git rev-list master..topic - - if this is empty, it is fully merged to "master". - -DOC_END diff --git a/tests/resources/mailmap/.gitted/hooks/pre-receive.sample b/tests/resources/mailmap/.gitted/hooks/pre-receive.sample deleted file mode 100755 index a1fd29ec1..000000000 --- a/tests/resources/mailmap/.gitted/hooks/pre-receive.sample +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -# -# An example hook script to make use of push options. -# The example simply echoes all push options that start with 'echoback=' -# and rejects all pushes when the "reject" push option is used. -# -# To enable this hook, rename this file to "pre-receive". - -if test -n "$GIT_PUSH_OPTION_COUNT" -then - i=0 - while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" - do - eval "value=\$GIT_PUSH_OPTION_$i" - case "$value" in - echoback=*) - echo "echo from the pre-receive-hook: ${value#*=}" >&2 - ;; - reject) - exit 1 - esac - i=$((i + 1)) - done -fi diff --git a/tests/resources/mailmap/.gitted/hooks/prepare-commit-msg.sample b/tests/resources/mailmap/.gitted/hooks/prepare-commit-msg.sample deleted file mode 100755 index f093a02ec..000000000 --- a/tests/resources/mailmap/.gitted/hooks/prepare-commit-msg.sample +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# -# An example hook script to prepare the commit log message. -# Called by "git commit" with the name of the file that has the -# commit message, followed by the description of the commit -# message's source. The hook's purpose is to edit the commit -# message file. If the hook fails with a non-zero status, -# the commit is aborted. -# -# To enable this hook, rename this file to "prepare-commit-msg". - -# This hook includes three examples. The first comments out the -# "Conflicts:" part of a merge commit. -# -# The second includes the output of "git diff --name-status -r" -# into the message, just before the "git status" output. It is -# commented because it doesn't cope with --amend or with squashed -# commits. -# -# The third example adds a Signed-off-by line to the message, that can -# still be edited. This is rarely a good idea. - -case "$2,$3" in - merge,) - /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;; - -# ,|template,) -# /usr/bin/perl -i.bak -pe ' -# print "\n" . `git diff --cached --name-status -r` -# if /^#/ && $first++ == 0' "$1" ;; - - *) ;; -esac - -# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') -# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" diff --git a/tests/resources/mailmap/.gitted/hooks/update.sample b/tests/resources/mailmap/.gitted/hooks/update.sample deleted file mode 100755 index 80ba94135..000000000 --- a/tests/resources/mailmap/.gitted/hooks/update.sample +++ /dev/null @@ -1,128 +0,0 @@ -#!/bin/sh -# -# An example hook script to block unannotated tags from entering. -# Called by "git receive-pack" with arguments: refname sha1-old sha1-new -# -# To enable this hook, rename this file to "update". -# -# Config -# ------ -# hooks.allowunannotated -# This boolean sets whether unannotated tags will be allowed into the -# repository. By default they won't be. -# hooks.allowdeletetag -# This boolean sets whether deleting tags will be allowed in the -# repository. By default they won't be. -# hooks.allowmodifytag -# This boolean sets whether a tag may be modified after creation. By default -# it won't be. -# hooks.allowdeletebranch -# This boolean sets whether deleting branches will be allowed in the -# repository. By default they won't be. -# hooks.denycreatebranch -# This boolean sets whether remotely creating branches will be denied -# in the repository. By default this is allowed. -# - -# --- Command line -refname="$1" -oldrev="$2" -newrev="$3" - -# --- Safety check -if [ -z "$GIT_DIR" ]; then - echo "Don't run this script from the command line." >&2 - echo " (if you want, you could supply GIT_DIR then run" >&2 - echo " $0 )" >&2 - exit 1 -fi - -if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then - echo "usage: $0 " >&2 - exit 1 -fi - -# --- Config -allowunannotated=$(git config --bool hooks.allowunannotated) -allowdeletebranch=$(git config --bool hooks.allowdeletebranch) -denycreatebranch=$(git config --bool hooks.denycreatebranch) -allowdeletetag=$(git config --bool hooks.allowdeletetag) -allowmodifytag=$(git config --bool hooks.allowmodifytag) - -# check for no description -projectdesc=$(sed -e '1q' "$GIT_DIR/description") -case "$projectdesc" in -"Unnamed repository"* | "") - echo "*** Project description file hasn't been set" >&2 - exit 1 - ;; -esac - -# --- Check types -# if $newrev is 0000...0000, it's a commit to delete a ref. -zero="0000000000000000000000000000000000000000" -if [ "$newrev" = "$zero" ]; then - newrev_type=delete -else - newrev_type=$(git cat-file -t $newrev) -fi - -case "$refname","$newrev_type" in - refs/tags/*,commit) - # un-annotated tag - short_refname=${refname##refs/tags/} - if [ "$allowunannotated" != "true" ]; then - echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 - echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 - exit 1 - fi - ;; - refs/tags/*,delete) - # delete tag - if [ "$allowdeletetag" != "true" ]; then - echo "*** Deleting a tag is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/tags/*,tag) - # annotated tag - if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 - then - echo "*** Tag '$refname' already exists." >&2 - echo "*** Modifying a tag is not allowed in this repository." >&2 - exit 1 - fi - ;; - refs/heads/*,commit) - # branch - if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then - echo "*** Creating a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/heads/*,delete) - # delete branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - refs/remotes/*,commit) - # tracking branch - ;; - refs/remotes/*,delete) - # delete tracking branch - if [ "$allowdeletebranch" != "true" ]; then - echo "*** Deleting a tracking branch is not allowed in this repository" >&2 - exit 1 - fi - ;; - *) - # Anything else (is there anything else?) - echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 - exit 1 - ;; -esac - -# --- Finished -exit 0 diff --git a/tests/resources/mailmap/.gitted/logs/HEAD b/tests/resources/mailmap/.gitted/logs/HEAD deleted file mode 100644 index 53945f715..000000000 --- a/tests/resources/mailmap/.gitted/logs/HEAD +++ /dev/null @@ -1,11 +0,0 @@ -0000000000000000000000000000000000000000 43179dc93939196f59b25387b5e44e9e8794f84c Nika Layzell 1521306034 -0400 commit (initial): Brad -43179dc93939196f59b25387b5e44e9e8794f84c 3a1295dbc9234c0c5947c72803618c7112a01447 Nika Layzell 1521306086 -0400 commit: Brad L. -3a1295dbc9234c0c5947c72803618c7112a01447 a7054a4b356b3ecdec60cee66e50beaa5b863755 Nika Layzell 1521306181 -0400 commit: Some Dude -a7054a4b356b3ecdec60cee66e50beaa5b863755 95d03c49d94de67d5a05553a1bb22e78f7cdf5ca Nika Layzell 1521306222 -0400 commit: Other Author -95d03c49d94de67d5a05553a1bb22e78f7cdf5ca 1e1212e7674820c17f7b8797aee7bf38ece0e838 Nika Layzell 1521306263 -0400 commit: nick3 -1e1212e7674820c17f7b8797aee7bf38ece0e838 3f134546ae8fbe95a39dd20ea8c12b5fb0f48afb Nika Layzell 1521306341 -0400 commit: Other Author -3f134546ae8fbe95a39dd20ea8c12b5fb0f48afb 50d69f4e64be2cff2cedde8f9b7f970257caf4dd Nika Layzell 1521306417 -0400 commit: Phil Hill -50d69f4e64be2cff2cedde8f9b7f970257caf4dd feef8f2135df4835496e4d576b1f1bd23510e1c5 Nika Layzell 1521306468 -0400 commit: Joseph -feef8f2135df4835496e4d576b1f1bd23510e1c5 7ecbb98d860b304f622b38ce9ab8f08d14d981a8 Nika Layzell 1521306510 -0400 commit: Santa Claus -7ecbb98d860b304f622b38ce9ab8f08d14d981a8 87ce8d4920a30ddb9547334e7c65806518863ff1 Nika Layzell 1521306549 -0400 commit: Charles -87ce8d4920a30ddb9547334e7c65806518863ff1 7100e631fb4d5deba31fdc8acc98f4fb5c1573fd Nika Layzell 1521306767 -0400 commit: +.mailmap diff --git a/tests/resources/mailmap/.gitted/logs/refs/heads/master b/tests/resources/mailmap/.gitted/logs/refs/heads/master deleted file mode 100644 index 53945f715..000000000 --- a/tests/resources/mailmap/.gitted/logs/refs/heads/master +++ /dev/null @@ -1,11 +0,0 @@ -0000000000000000000000000000000000000000 43179dc93939196f59b25387b5e44e9e8794f84c Nika Layzell 1521306034 -0400 commit (initial): Brad -43179dc93939196f59b25387b5e44e9e8794f84c 3a1295dbc9234c0c5947c72803618c7112a01447 Nika Layzell 1521306086 -0400 commit: Brad L. -3a1295dbc9234c0c5947c72803618c7112a01447 a7054a4b356b3ecdec60cee66e50beaa5b863755 Nika Layzell 1521306181 -0400 commit: Some Dude -a7054a4b356b3ecdec60cee66e50beaa5b863755 95d03c49d94de67d5a05553a1bb22e78f7cdf5ca Nika Layzell 1521306222 -0400 commit: Other Author -95d03c49d94de67d5a05553a1bb22e78f7cdf5ca 1e1212e7674820c17f7b8797aee7bf38ece0e838 Nika Layzell 1521306263 -0400 commit: nick3 -1e1212e7674820c17f7b8797aee7bf38ece0e838 3f134546ae8fbe95a39dd20ea8c12b5fb0f48afb Nika Layzell 1521306341 -0400 commit: Other Author -3f134546ae8fbe95a39dd20ea8c12b5fb0f48afb 50d69f4e64be2cff2cedde8f9b7f970257caf4dd Nika Layzell 1521306417 -0400 commit: Phil Hill -50d69f4e64be2cff2cedde8f9b7f970257caf4dd feef8f2135df4835496e4d576b1f1bd23510e1c5 Nika Layzell 1521306468 -0400 commit: Joseph -feef8f2135df4835496e4d576b1f1bd23510e1c5 7ecbb98d860b304f622b38ce9ab8f08d14d981a8 Nika Layzell 1521306510 -0400 commit: Santa Claus -7ecbb98d860b304f622b38ce9ab8f08d14d981a8 87ce8d4920a30ddb9547334e7c65806518863ff1 Nika Layzell 1521306549 -0400 commit: Charles -87ce8d4920a30ddb9547334e7c65806518863ff1 7100e631fb4d5deba31fdc8acc98f4fb5c1573fd Nika Layzell 1521306767 -0400 commit: +.mailmap -- cgit v1.2.1 From 57cfeab9fe480591e3f56d61ccfbb68f9b500156 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Mon, 26 Mar 2018 15:05:37 -0400 Subject: mailmap: Switch mailmap parsing to use the git_parse module --- include/git2/mailmap.h | 44 +++---- src/blame.h | 3 +- src/mailmap.c | 340 +++++++++++++++++++++--------------------------- src/signature.c | 39 +----- tests/clar_libgit2.c | 3 +- tests/mailmap/basic.c | 28 ++-- tests/mailmap/blame.c | 9 +- tests/mailmap/parsing.c | 55 +++----- 8 files changed, 206 insertions(+), 315 deletions(-) diff --git a/include/git2/mailmap.h b/include/git2/mailmap.h index 0c722b549..30cc9cf69 100644 --- a/include/git2/mailmap.h +++ b/include/git2/mailmap.h @@ -9,6 +9,7 @@ #include "common.h" #include "types.h" +#include "buffer.h" /** * @file git2/mailmap.h @@ -35,22 +36,20 @@ typedef struct git_mailmap_entry { #define GIT_MAILMAP_ENTRY_INIT {GIT_MAILMAP_ENTRY_VERSION} /** - * Create a mailmap object by parsing a mailmap file. + * Create a mailmap object by parsing a mailmap file. Malformed entries in the + * mailmap are ignored. * * The mailmap must be freed with 'git_mailmap_free'. * * @param out pointer to store the mailmap - * @param data raw data buffer to parse - * @param size size of the raw data buffer - * @return 0 on success + * @param buffer buffer to parse the mailmap from + * @return 0 on success, otherwise an error code */ -GIT_EXTERN(int) git_mailmap_parse( - git_mailmap **out, - const char *data, - size_t size); +GIT_EXTERN(int) git_mailmap_from_buffer(git_mailmap **out, git_buf *buffer); /** - * Create a mailmap object from the given repository. + * Create a mailmap object from the given repository. Malformed entries in the + * mailmap are ignored. * * If the repository is not bare, the repository's working directory root will * be checked for the '.mailmap' file to be parsed. @@ -62,20 +61,23 @@ GIT_EXTERN(int) git_mailmap_parse( * * @param out pointer to store the mailmap * @param repo repository to find the .mailmap in - * @return 0 on success; GIT_ENOTFOUND if .mailmap could not be found. + * @return 0 on success; GIT_ENOTFOUND if .mailmap could not be found, + * otherwise an error code. */ -GIT_EXTERN(int) git_mailmap_from_repo( - git_mailmap **out, - git_repository *repo); +GIT_EXTERN(int) git_mailmap_from_repo(git_mailmap **out, git_repository *repo); /** - * Free a mailmap created by 'git_mailmap_parse' or 'git_mailmap_from_repo'. + * Free a mailmap created by 'git_mailmap_from_buffer' or + * 'git_mailmap_from_repo'. */ GIT_EXTERN(void) git_mailmap_free(git_mailmap *mailmap); /** * Resolve a name and email to the corresponding real name and email. * + * The lifetime of the string results is tied to the `mailmap`, `name`, and + * `email` parameters. + * * @param name_out either 'name', or the real name to use. * You should NOT free this value. * @param email_out either 'email' or the real email to use, @@ -85,11 +87,8 @@ GIT_EXTERN(void) git_mailmap_free(git_mailmap *mailmap); * @param email the email to resolve. */ GIT_EXTERN(void) git_mailmap_resolve( - const char **name_out, - const char **email_out, - const git_mailmap *mailmap, - const char *name, - const char *email); + const char **name_out, const char **email_out, + const git_mailmap *mailmap, const char *name, const char *email); /** * Get the number of mailmap entries in this mailmap. @@ -104,8 +103,7 @@ GIT_EXTERN(size_t) git_mailmap_entry_count(const git_mailmap *mailmap); * @return the mailmap entry at index, or NULL if it cannot be found. */ GIT_EXTERN(const git_mailmap_entry *) git_mailmap_entry_byindex( - const git_mailmap *mailmap, - size_t idx); + const git_mailmap *mailmap, size_t idx); /** * Lookup a mailmap entry by name/email pair. @@ -118,9 +116,7 @@ GIT_EXTERN(const git_mailmap_entry *) git_mailmap_entry_byindex( * @return the corresponding mailmap entry, or NULL if it cannot be found. */ GIT_EXTERN(const git_mailmap_entry *) git_mailmap_entry_lookup( - const git_mailmap *mailmap, - const char *name, - const char *email); + const git_mailmap *mailmap, const char *name, const char *email); /** @} */ GIT_END_DECL diff --git a/src/blame.h b/src/blame.h index 057413274..b31d2dc20 100644 --- a/src/blame.h +++ b/src/blame.h @@ -67,6 +67,7 @@ typedef struct git_blame__entry { struct git_blame { char *path; git_repository *repository; + git_mailmap *mailmap; git_blame_options options; git_vector hunks; @@ -84,8 +85,6 @@ struct git_blame { int num_lines; const char *final_buf; git_off_t final_buf_size; - - git_mailmap *mailmap; }; git_blame *git_blame__alloc( diff --git a/src/mailmap.c b/src/mailmap.c index c0da98d48..caac82c09 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -9,216 +9,180 @@ #include "blob.h" #include "commit.h" +#include "parse.h" #include "git2/common.h" #include "git2/repository.h" #include "git2/revparse.h" #include "git2/sys/commit.h" -/** - * Helper type and methods for the mailmap parser - */ -typedef struct char_range { - const char *p; - size_t len; -} char_range; +#define MAILMAP_FILE ".mailmap" -static const char_range NULL_RANGE = {0}; +struct git_mailmap { + git_vector entries; +}; -/* Split a range at the first instance of 'c'. Returns whether 'c' was found */ -static bool range_split( - char_range range, - char c, - char_range *before, - char_range *after) +/* Check if we're at the end of line, w/ comments */ +static bool is_eol(git_parse_ctx *ctx) { - const char *off; - - *before = *after = NULL_RANGE; - before->p = range.p; - off = memchr(range.p, c, range.len); - if (!off) { - before->len = range.len; - return false; - } - - before->len = off - range.p; - after->p = off + 1; - after->len = (range.p + range.len) - after->p; - return true; + char c; + return git_parse_peek(&c, ctx, GIT_PARSE_PEEK_SKIP_WHITESPACE) < 0 || c == '#'; } -/* Trim whitespace from the beginning and end of the range */ -static void range_trim(char_range *range) { - while (range->len > 0 && git__isspace(range->p[0])) { - ++range->p; - --range->len; - } - while (range->len > 0 && git__isspace(range->p[range->len - 1])) - --range->len; +static int advance_until( + const char **start, size_t *len, git_parse_ctx *ctx, char needle) +{ + *start = ctx->line; + while (ctx->line_len > 0 && *ctx->line != '#' && *ctx->line != needle) + git_parse_advance_chars(ctx, 1); + + if (ctx->line_len == 0 || *ctx->line == '#') + return -1; /* end of line */ + + *len = ctx->line - *start; + git_parse_advance_chars(ctx, 1); /* advance past needle */ + return 0; } -/** - * If `buf` is not NULL, copies range into it with a '\0', and bumps buf. - * If `size` is not NULL, adds the number of bytes to be written to it. - * returns a pointer to the copied string, or NULL. +/* Parse a single entry from a mailmap file. + * + * The output git_bufs will be non-owning, and should be copied before being + * persisted. */ -static const char *range_copyz(char **buf, size_t *size, char_range src) +static int parse_mailmap_entry( + git_buf *real_name, git_buf *real_email, + git_buf *replace_name, git_buf *replace_email, + git_parse_ctx *ctx) { - char *s = NULL; - if (src.p == NULL) - return NULL; + const char *start; + size_t len; - if (size) - *size += src.len + 1; + git_buf_clear(real_name); + git_buf_clear(real_email); + git_buf_clear(replace_name); + git_buf_clear(replace_email); - if (buf) { - s = *buf; - memcpy(s, src.p, src.len); - s[src.len] = '\0'; - *buf += src.len + 1; - } - return s; -} + /* Parse the real name */ + git_parse_advance_ws(ctx); + if (advance_until(&start, &len, ctx, '<') < 0) + return -1; -struct git_mailmap { - git_vector entries; -}; + git_buf_attach_notowned(real_name, start, len); + git_buf_rtrim(real_name); -/** - * Parse a single entry out of a mailmap file. - * Advances the `file` range past the parsed entry. - */ -static int git_mailmap_parse_single( - char_range *file, - bool *found, - char_range *real_name, - char_range *real_email, - char_range *replace_name, - char_range *replace_email) -{ - char_range line, comment, name_a, email_a, name_b, email_b; - bool two_emails = false; - - *found = false; - *real_name = NULL_RANGE; - *real_email = NULL_RANGE; - *replace_name = NULL_RANGE; - *replace_email = NULL_RANGE; - - while (file->len > 0) { - /* Get the line, and remove any comments */ - range_split(*file, '\n', &line, file); - range_split(line, '#', &line, &comment); - - /* Skip blank lines */ - range_trim(&line); - if (line.len == 0) - continue; + /* If this is the last email in the line, this is the email to replace, + * otherwise, it's the real email. */ + if (advance_until(&start, &len, ctx, '>') < 0) + return -1; - /* Get the first name and email */ - if (!range_split(line, '<', &name_a, &line)) - return -1; /* garbage in line */ - if (!range_split(line, '>', &email_a, &line)) - return -1; /* unfinished <> pair */ - - /* Get an optional second name and/or email */ - two_emails = range_split(line, '<', &name_b, &line); - if (two_emails && !range_split(line, '>', &email_b, &line)) - return -1; /* unfinished <> pair */ - - /* Trim whitespace from around names */ - range_trim(&name_a); - range_trim(&name_b); - - *found = true; - if (name_a.len > 0) - *real_name = name_a; - - if (two_emails) { - if (email_a.len > 0) - *real_email = email_a; - *replace_email = email_b; - - if (name_b.len > 0) - *replace_name = name_b; - } else { - *replace_email = email_a; - } - break; + /* If we aren't at the end of the line, parse a second name and email */ + if (!is_eol(ctx)) { + git_buf_attach_notowned(real_email, start, len); + + git_parse_advance_ws(ctx); + if (advance_until(&start, &len, ctx, '<') < 0) + return -1; + git_buf_attach_notowned(replace_name, start, len); + git_buf_rtrim(replace_name); + + if (advance_until(&start, &len, ctx, '>') < 0) + return -1; } + git_buf_attach_notowned(replace_email, start, len); + + if (!is_eol(ctx)) + return -1; + return 0; } -int git_mailmap_parse( - git_mailmap **mailmap, - const char *data, - size_t size) +int git_mailmap_from_buffer(git_mailmap **out, git_buf *buf) { - char_range file = { data, size }; - git_mailmap_entry* entry = NULL; - int error = 0; + int error; + git_mailmap *mm; + size_t entry_size; + char *entry_data; + git_mailmap_entry *entry = NULL; + git_parse_ctx ctx; + + /* Scratch buffers containing the real parsed names & emails */ + git_buf real_name = GIT_BUF_INIT; + git_buf real_email = GIT_BUF_INIT; + git_buf replace_name = GIT_BUF_INIT; + git_buf replace_email = GIT_BUF_INIT; + + if (git_buf_contains_nul(buf)) + return -1; - if (memchr(data, '\0', size) != NULL) - return -1; /* data may not contain '\0's */ + git_parse_ctx_init(&ctx, buf->ptr, buf->size); - *mailmap = git__calloc(1, sizeof(git_mailmap)); - if (!*mailmap) - return -1; + /* Create our mailmap object */ + mm = git__calloc(1, sizeof(git_mailmap)); + GITERR_CHECK_ALLOC(mm); - /* XXX: Is it worth it to precompute the size? */ - error = git_vector_init(&(*mailmap)->entries, 0, NULL); + error = git_vector_init(&mm->entries, 0, NULL); if (error < 0) goto cleanup; - while (file.len > 0) { - bool found = false; - char_range real_name, real_email, replace_name, replace_email; - size_t size = 0; - char *buf = NULL; - - error = git_mailmap_parse_single( - &file, &found, - &real_name, &real_email, - &replace_name, &replace_email); - if (error < 0 || !found) { - error = 0; + /* Run the parser */ + while (ctx.remain_len > 0) { + error = parse_mailmap_entry( + &real_name, &real_email, &replace_name, &replace_email, &ctx); + if (error < 0) { + error = 0; /* Skip lines which don't contain a valid entry */ + git_parse_advance_line(&ctx); continue; } - /* Compute how much space we'll need to store our entry */ - size = sizeof(git_mailmap_entry); - range_copyz(NULL, &size, real_name); - range_copyz(NULL, &size, real_email); - range_copyz(NULL, &size, replace_name); - range_copyz(NULL, &size, replace_email); + GITERR_CHECK_ALLOC_ADD5( + &entry_size, sizeof(git_mailmap_entry) + 4 /* 4x'\0' */, + real_name.size, real_email.size, + replace_name.size, replace_email.size); + entry = git__calloc(1, entry_size); + GITERR_CHECK_ALLOC(entry); - entry = git__malloc(size); - if (!entry) { - error = -1; - goto cleanup; - } entry->version = GIT_MAILMAP_ENTRY_VERSION; - buf = (char*)(entry + 1); - entry->real_name = range_copyz(&buf, NULL, real_name); - entry->real_email = range_copyz(&buf, NULL, real_email); - entry->replace_name = range_copyz(&buf, NULL, replace_name); - entry->replace_email = range_copyz(&buf, NULL, replace_email); - assert(buf == ((char*)entry) + size); + /* Copy strings into the buffer following entry */ + entry_data = (char *)(entry + 1); + if (real_name.size > 0) { + memcpy(entry_data, real_name.ptr, real_name.size); + entry->real_name = entry_data; + entry_data += real_name.size + 1; /* advance past null from calloc */ + } + if (real_email.size > 0) { + memcpy(entry_data, real_email.ptr, real_email.size); + entry->real_email = entry_data; + entry_data += real_email.size + 1; + } + if (replace_name.size > 0) { + memcpy(entry_data, replace_name.ptr, replace_name.size); + entry->replace_name = entry_data; + entry_data += replace_name.size + 1; + } + /* replace_email is always non-null */ + memcpy(entry_data, replace_email.ptr, replace_email.size); + entry->replace_email = entry_data; - error = git_vector_insert(&(*mailmap)->entries, entry); + error = git_vector_insert(&mm->entries, entry); if (error < 0) goto cleanup; entry = NULL; } + /* fill in *out, and make sure we don't free our mailmap */ + *out = mm; + mm = NULL; + cleanup: git__free(entry); - if (error < 0) { - git_mailmap_free(*mailmap); - *mailmap = NULL; - } + git_mailmap_free(mm); + + /* We never allocate data in these buffers, but better safe than sorry */ + git_buf_free(&real_name); + git_buf_free(&real_email); + git_buf_free(&replace_name); + git_buf_free(&replace_email); return error; } @@ -232,11 +196,9 @@ void git_mailmap_free(git_mailmap *mailmap) } void git_mailmap_resolve( - const char **name_out, - const char **email_out, + const char **name_out, const char **email_out, const git_mailmap *mailmap, - const char *name, - const char *email) + const char *name, const char *email) { const git_mailmap_entry *entry = NULL; assert(name && email); @@ -257,9 +219,7 @@ void git_mailmap_resolve( } const git_mailmap_entry *git_mailmap_entry_lookup( - const git_mailmap *mailmap, - const char *name, - const char *email) + const git_mailmap *mailmap, const char *name, const char *email) { size_t i; git_mailmap_entry *entry; @@ -293,15 +253,12 @@ size_t git_mailmap_entry_count(const git_mailmap *mailmap) return 0; } -static int git_mailmap_from_bare_repo( - git_mailmap **mailmap, - git_repository *repo) +static int mailmap_from_bare_repo(git_mailmap **mailmap, git_repository *repo) { git_reference *head = NULL; git_object *tree = NULL; git_blob *blob = NULL; - const char *content = NULL; - git_off_t size = 0; + git_buf content = GIT_BUF_INIT; int error; assert(git_repository_is_bare(repo)); @@ -316,31 +273,28 @@ static int git_mailmap_from_bare_repo( goto cleanup; error = git_object_lookup_bypath( - (git_object **) &blob, - tree, - ".mailmap", - GIT_OBJ_BLOB); + (git_object **) &blob, tree, MAILMAP_FILE, GIT_OBJ_BLOB); if (error < 0) goto cleanup; - content = git_blob_rawcontent(blob); - size = git_blob_rawsize(blob); + error = git_blob_filtered_content(&content, blob, MAILMAP_FILE, false); + if (error < 0) + goto cleanup; - error = git_mailmap_parse(mailmap, content, size); + error = git_mailmap_from_buffer(mailmap, &content); if (error < 0) goto cleanup; cleanup: - git_reference_free(head); - git_object_free(tree); + git_buf_free(&content); git_blob_free(blob); + git_object_free(tree); + git_reference_free(head); return error; } -static int git_mailmap_from_workdir_repo( - git_mailmap **mailmap, - git_repository *repo) +static int mailmap_from_workdir_repo(git_mailmap **mailmap, git_repository *repo) { git_buf path = GIT_BUF_INIT; git_buf data = GIT_BUF_INIT; @@ -349,7 +303,7 @@ static int git_mailmap_from_workdir_repo( assert(!git_repository_is_bare(repo)); /* In non-bare repositories, .mailmap should be read from the workdir */ - error = git_buf_joinpath(&path, git_repository_workdir(repo), ".mailmap"); + error = git_buf_joinpath(&path, git_repository_workdir(repo), MAILMAP_FILE); if (error < 0) goto cleanup; @@ -357,7 +311,7 @@ static int git_mailmap_from_workdir_repo( if (error < 0) goto cleanup; - error = git_mailmap_parse(mailmap, data.ptr, data.size); + error = git_mailmap_from_buffer(mailmap, &data); if (error < 0) goto cleanup; @@ -375,7 +329,7 @@ int git_mailmap_from_repo(git_mailmap **mailmap, git_repository *repo) *mailmap = NULL; if (git_repository_is_bare(repo)) - return git_mailmap_from_bare_repo(mailmap, repo); + return mailmap_from_bare_repo(mailmap, repo); else - return git_mailmap_from_workdir_repo(mailmap, repo); + return mailmap_from_workdir_repo(mailmap, repo); } diff --git a/src/signature.c b/src/signature.c index a93ba1019..723f8527a 100644 --- a/src/signature.c +++ b/src/signature.c @@ -99,27 +99,8 @@ int git_signature_new(git_signature **sig_out, const char *name, const char *ema int git_signature_dup(git_signature **dest, const git_signature *source) { - git_signature *signature; - - if (source == NULL) - return 0; - - signature = git__calloc(1, sizeof(git_signature)); - GITERR_CHECK_ALLOC(signature); - - signature->name = git__strdup(source->name); - GITERR_CHECK_ALLOC(signature->name); - - signature->email = git__strdup(source->email); - GITERR_CHECK_ALLOC(signature->email); - - signature->when.time = source->when.time; - signature->when.offset = source->when.offset; - signature->when.sign = source->when.sign; - - *dest = signature; - - return 0; + /* If mailmap is NULL, this method just copies the signature */ + return git_signature_with_mailmap(dest, source, NULL); } int git_signature_with_mailmap( @@ -132,32 +113,26 @@ int git_signature_with_mailmap( const char *email = NULL; if (source == NULL) - goto on_error; + return 0; git_mailmap_resolve(&name, &email, mailmap, source->name, source->email); signature = git__calloc(1, sizeof(git_signature)); - if (!signature) - goto on_error; + GITERR_CHECK_ALLOC(signature); signature->name = git__strdup(name); - if (!signature->name) - goto on_error; + GITERR_CHECK_ALLOC(signature->name); signature->email = git__strdup(email); - if (!signature->email) - goto on_error; + GITERR_CHECK_ALLOC(signature->email); signature->when.time = source->when.time; signature->when.offset = source->when.offset; signature->when.sign = source->when.sign; *dest = signature; - return 0; -on_error: - git_signature_free(signature); - return -1; + return 0; } int git_signature__pdup(git_signature **dest, const git_signature *source, git_pool *pool) diff --git a/tests/clar_libgit2.c b/tests/clar_libgit2.c index b50633a6c..8d1bbb731 100644 --- a/tests/clar_libgit2.c +++ b/tests/clar_libgit2.c @@ -227,8 +227,7 @@ git_repository *cl_git_sandbox_reopen(void) _cl_repo = NULL; cl_git_pass(git_repository_open( - &_cl_repo, - cl_fixture_basename(_cl_sandbox))); + &_cl_repo, cl_fixture_basename(_cl_sandbox))); } return _cl_repo; diff --git a/tests/mailmap/basic.c b/tests/mailmap/basic.c index 9b06f184d..508598440 100644 --- a/tests/mailmap/basic.c +++ b/tests/mailmap/basic.c @@ -15,7 +15,10 @@ const char TEST_MAILMAP[] = void test_mailmap_basic__initialize(void) { - cl_git_pass(git_mailmap_parse(&mailmap, TEST_MAILMAP, sizeof(TEST_MAILMAP) - 1)); + git_buf buf = GIT_BUF_INIT; + git_buf_attach_notowned(&buf, TEST_MAILMAP, sizeof(TEST_MAILMAP) - 1); + + cl_git_pass(git_mailmap_from_buffer(&mailmap, &buf)); } void test_mailmap_basic__cleanup(void) @@ -53,9 +56,7 @@ void test_mailmap_basic__lookup_not_found(void) void test_mailmap_basic__lookup(void) { const git_mailmap_entry *entry = git_mailmap_entry_lookup( - mailmap, - "Typoed the name once", - "foo@baz.com"); + mailmap, "Typoed the name once", "foo@baz.com"); cl_assert(entry); cl_assert(!git__strcmp(entry->real_name, "Foo bar")); } @@ -65,11 +66,7 @@ void test_mailmap_basic__empty_email_query(void) const char *name; const char *email; git_mailmap_resolve( - &name, - &email, - mailmap, - "Author name", - "otheremail@foo.com"); + &name, &email, mailmap, "Author name", "otheremail@foo.com"); cl_assert(!git__strcmp(name, "Author name")); cl_assert(!git__strcmp(email, "email@foo.com")); } @@ -79,20 +76,13 @@ void test_mailmap_basic__name_matching(void) const char *name; const char *email; git_mailmap_resolve( - &name, - &email, - mailmap, - "Other Name", - "yetanotheremail@foo.com"); + &name, &email, mailmap, "Other Name", "yetanotheremail@foo.com"); cl_assert(!git__strcmp(name, "Other Name")); cl_assert(!git__strcmp(email, "email@foo.com")); git_mailmap_resolve( - &name, - &email, - mailmap, - "Other Name That Doesn't Match", - "yetanotheremail@foo.com"); + &name, &email, mailmap, + "Other Name That Doesn't Match", "yetanotheremail@foo.com"); cl_assert(!git__strcmp(name, "Other Name That Doesn't Match")); cl_assert(!git__strcmp(email, "yetanotheremail@foo.com")); } diff --git a/tests/mailmap/blame.c b/tests/mailmap/blame.c index 45e9812a8..9ab085bd3 100644 --- a/tests/mailmap/blame.c +++ b/tests/mailmap/blame.c @@ -15,11 +15,8 @@ void test_mailmap_blame__initialize(void) void test_mailmap_blame__cleanup(void) { - cl_git_sandbox_cleanup(); - g_repo = NULL; - git_blame_free(g_blame); - g_blame = NULL; + cl_git_sandbox_cleanup(); } void test_mailmap_blame__hunks(void) @@ -32,7 +29,7 @@ void test_mailmap_blame__hunks(void) opts.flags |= GIT_BLAME_USE_MAILMAP; - cl_check_pass(git_blame_file(&g_blame, g_repo, "file.txt", &opts)); + cl_git_pass(git_blame_file(&g_blame, g_repo, "file.txt", &opts)); if (!g_blame) return; @@ -54,7 +51,7 @@ void test_mailmap_blame__hunks_no_mailmap(void) g_repo = cl_git_sandbox_init("mailmap"); - cl_check_pass(git_blame_file(&g_blame, g_repo, "file.txt", &opts)); + cl_git_pass(git_blame_file(&g_blame, g_repo, "file.txt", &opts)); if (!g_blame) return; diff --git a/tests/mailmap/parsing.c b/tests/mailmap/parsing.c index a81f2f9bf..fecb882cd 100644 --- a/tests/mailmap/parsing.c +++ b/tests/mailmap/parsing.c @@ -14,18 +14,15 @@ void test_mailmap_parsing__initialize(void) void test_mailmap_parsing__cleanup(void) { - cl_git_sandbox_cleanup(); - g_repo = NULL; - git_mailmap_free(g_mailmap); - g_mailmap = NULL; + cl_git_sandbox_cleanup(); } static void check_mailmap_entries( const git_mailmap *mailmap, const mailmap_entry *entries, size_t entries_size) { const git_mailmap_entry *parsed = NULL; - size_t idx = 0; + size_t idx; /* Check that the parsed entries match */ cl_assert_equal_sz(entries_size, git_mailmap_entry_count(mailmap)); @@ -43,7 +40,7 @@ static void check_mailmap_resolve( { const char *resolved_name = NULL; const char *resolved_email = NULL; - size_t idx = 0; + size_t idx; /* Check that the resolver behaves correctly */ for (idx = 0; idx < resolved_size; ++idx) { @@ -60,23 +57,17 @@ static void check_mailmap_resolve( void test_mailmap_parsing__string(void) { - cl_check_pass(git_mailmap_parse( - &g_mailmap, - string_mailmap, - strlen(string_mailmap))); + git_buf buf = GIT_BUF_INIT; + git_buf_attach_notowned(&buf, string_mailmap, strlen(string_mailmap)); + cl_git_pass(git_mailmap_from_buffer(&g_mailmap, &buf)); /* We should have parsed all of the entries */ - check_mailmap_entries( - g_mailmap, - entries, ARRAY_SIZE(entries)); + check_mailmap_entries(g_mailmap, entries, ARRAY_SIZE(entries)); /* Check that resolving the entries works */ + check_mailmap_resolve(g_mailmap, resolved, ARRAY_SIZE(resolved)); check_mailmap_resolve( - g_mailmap, - resolved, ARRAY_SIZE(resolved)); - check_mailmap_resolve( - g_mailmap, - resolved_untracked, ARRAY_SIZE(resolved_untracked)); + g_mailmap, resolved_untracked, ARRAY_SIZE(resolved_untracked)); } void test_mailmap_parsing__fromrepo(void) @@ -84,40 +75,30 @@ void test_mailmap_parsing__fromrepo(void) g_repo = cl_git_sandbox_init("mailmap"); cl_check(!git_repository_is_bare(g_repo)); - cl_check_pass(git_mailmap_from_repo(&g_mailmap, g_repo)); + cl_git_pass(git_mailmap_from_repo(&g_mailmap, g_repo)); /* We should have parsed all of the entries */ - check_mailmap_entries( - g_mailmap, - entries, ARRAY_SIZE(entries)); + check_mailmap_entries(g_mailmap, entries, ARRAY_SIZE(entries)); /* Check that resolving the entries works */ + check_mailmap_resolve(g_mailmap, resolved, ARRAY_SIZE(resolved)); check_mailmap_resolve( - g_mailmap, - resolved, ARRAY_SIZE(resolved)); - check_mailmap_resolve( - g_mailmap, - resolved_untracked, ARRAY_SIZE(resolved_untracked)); + g_mailmap, resolved_untracked, ARRAY_SIZE(resolved_untracked)); } void test_mailmap_parsing__frombare(void) { g_repo = cl_git_sandbox_init("mailmap/.gitted"); - cl_check_pass(git_repository_set_bare(g_repo)); + cl_git_pass(git_repository_set_bare(g_repo)); cl_check(git_repository_is_bare(g_repo)); - cl_check_pass(git_mailmap_from_repo(&g_mailmap, g_repo)); + cl_git_pass(git_mailmap_from_repo(&g_mailmap, g_repo)); /* We should have parsed all of the entries, except for the untracked one */ - check_mailmap_entries( - g_mailmap, - entries, ARRAY_SIZE(entries) - 1); + check_mailmap_entries(g_mailmap, entries, ARRAY_SIZE(entries) - 1); /* Check that resolving the entries works */ + check_mailmap_resolve(g_mailmap, resolved, ARRAY_SIZE(resolved)); check_mailmap_resolve( - g_mailmap, - resolved, ARRAY_SIZE(resolved)); - check_mailmap_resolve( - g_mailmap, - resolved_bare, ARRAY_SIZE(resolved_bare)); + g_mailmap, resolved_bare, ARRAY_SIZE(resolved_bare)); } -- cgit v1.2.1 From 18ff9babd7476097a67e122b9126c878f98ff47f Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Tue, 27 Mar 2018 22:48:03 -0400 Subject: mailmap: API and style cleanup --- include/git2/mailmap.h | 3 +- src/mailmap.c | 80 +++++++++++++++++++++++++++++-------------------- src/signature.c | 5 +++- tests/clar_libgit2.c | 3 +- tests/mailmap/basic.c | 71 ++++++++++++++++++++++++++----------------- tests/mailmap/parsing.c | 30 +++++++++++++++---- 6 files changed, 122 insertions(+), 70 deletions(-) diff --git a/include/git2/mailmap.h b/include/git2/mailmap.h index 30cc9cf69..a8c4ccbf7 100644 --- a/include/git2/mailmap.h +++ b/include/git2/mailmap.h @@ -85,8 +85,9 @@ GIT_EXTERN(void) git_mailmap_free(git_mailmap *mailmap); * @param mailmap the mailmap to perform the lookup in. (may be NULL) * @param name the name to resolve. * @param email the email to resolve. + * @return 0 on success, otherwise an error code. */ -GIT_EXTERN(void) git_mailmap_resolve( +GIT_EXTERN(int) git_mailmap_resolve( const char **name_out, const char **email_out, const git_mailmap *mailmap, const char *name, const char *email); diff --git a/src/mailmap.c b/src/mailmap.c index caac82c09..a178c3172 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -21,6 +21,18 @@ struct git_mailmap { git_vector entries; }; +static void mailmap_entry_free(git_mailmap_entry *entry) +{ + if (!entry) + return; + + git__free(entry->real_name); + git__free(entry->real_email); + git__free(entry->replace_name); + git__free(entry->replace_email); + git__free(entry); +} + /* Check if we're at the end of line, w/ comments */ static bool is_eol(git_parse_ctx *ctx) { @@ -43,7 +55,8 @@ static int advance_until( return 0; } -/* Parse a single entry from a mailmap file. +/* + * Parse a single entry from a mailmap file. * * The output git_bufs will be non-owning, and should be copied before being * persisted. @@ -61,16 +74,21 @@ static int parse_mailmap_entry( git_buf_clear(replace_name); git_buf_clear(replace_email); - /* Parse the real name */ git_parse_advance_ws(ctx); + if (is_eol(ctx)) + return -1; /* blank line */ + + /* Parse the real name */ if (advance_until(&start, &len, ctx, '<') < 0) return -1; git_buf_attach_notowned(real_name, start, len); git_buf_rtrim(real_name); - /* If this is the last email in the line, this is the email to replace, - * otherwise, it's the real email. */ + /* + * If this is the last email in the line, this is the email to replace, + * otherwise, it's the real email. + */ if (advance_until(&start, &len, ctx, '>') < 0) return -1; @@ -131,38 +149,27 @@ int git_mailmap_from_buffer(git_mailmap **out, git_buf *buf) if (error < 0) { error = 0; /* Skip lines which don't contain a valid entry */ git_parse_advance_line(&ctx); - continue; + continue; /* TODO: warn */ } - GITERR_CHECK_ALLOC_ADD5( - &entry_size, sizeof(git_mailmap_entry) + 4 /* 4x'\0' */, - real_name.size, real_email.size, - replace_name.size, replace_email.size); - entry = git__calloc(1, entry_size); + entry = git__calloc(1, sizeof(git_mailmap_entry)); GITERR_CHECK_ALLOC(entry); - entry->version = GIT_MAILMAP_ENTRY_VERSION; - /* Copy strings into the buffer following entry */ - entry_data = (char *)(entry + 1); if (real_name.size > 0) { - memcpy(entry_data, real_name.ptr, real_name.size); - entry->real_name = entry_data; - entry_data += real_name.size + 1; /* advance past null from calloc */ + entry->real_name = git__substrdup(real_name.ptr, real_name.size); + GITERR_CHECK_ALLOC(entry->real_name); } if (real_email.size > 0) { - memcpy(entry_data, real_email.ptr, real_email.size); - entry->real_email = entry_data; - entry_data += real_email.size + 1; + entry->real_email = git__substrdup(real_email.ptr, real_email.size); + GITERR_CHECK_ALLOC(entry->real_email); } if (replace_name.size > 0) { - memcpy(entry_data, replace_name.ptr, replace_name.size); - entry->replace_name = entry_data; - entry_data += replace_name.size + 1; + entry->replace_name = git__substrdup(replace_name.ptr, replace_name.size); + GITERR_CHECK_ALLOC(entry->replace_name); } - /* replace_email is always non-null */ - memcpy(entry_data, replace_email.ptr, replace_email.size); - entry->replace_email = entry_data; + entry->replace_email = git__substrdup(replace_email.ptr, replace_email.size); + GITERR_CHECK_ALLOC(entry->replace_email); error = git_vector_insert(&mm->entries, entry); if (error < 0) @@ -175,7 +182,7 @@ int git_mailmap_from_buffer(git_mailmap **out, git_buf *buf) mm = NULL; cleanup: - git__free(entry); + mailmap_entry_free(entry); git_mailmap_free(mm); /* We never allocate data in these buffers, but better safe than sorry */ @@ -191,11 +198,15 @@ void git_mailmap_free(git_mailmap *mailmap) if (!mailmap) return; - git_vector_free_deep(&mailmap->entries); + git_vector_foreach(&mailmap->entries, i, entry) { + mailmap_entry_free(entry); + } + git_vector_free(&mailmap->entries); + git__free(mailmap); } -void git_mailmap_resolve( +int git_mailmap_resolve( const char **name_out, const char **email_out, const git_mailmap *mailmap, const char *name, const char *email) @@ -207,7 +218,7 @@ void git_mailmap_resolve( *email_out = email; if (!mailmap) - return; + return 0; entry = git_mailmap_entry_lookup(mailmap, name, email); if (entry) { @@ -216,6 +227,7 @@ void git_mailmap_resolve( if (entry->real_email) *email_out = entry->real_email; } + return 0; } const git_mailmap_entry *git_mailmap_entry_lookup( @@ -229,10 +241,12 @@ const git_mailmap_entry *git_mailmap_entry_lookup( return NULL; git_vector_foreach(&mailmap->entries, i, entry) { - if (!git__strcmp(email, entry->replace_email) && - (!entry->replace_name || !git__strcmp(name, entry->replace_name))) { - return entry; - } + if (git__strcmp(email, entry->replace_email)) + continue; + if (entry->replace_name && git__strcmp(name, entry->replace_name)) + continue; + + return entry; } return NULL; diff --git a/src/signature.c b/src/signature.c index 723f8527a..d922fda4b 100644 --- a/src/signature.c +++ b/src/signature.c @@ -111,11 +111,14 @@ int git_signature_with_mailmap( git_signature *signature = NULL; const char *name = NULL; const char *email = NULL; + int error; if (source == NULL) return 0; - git_mailmap_resolve(&name, &email, mailmap, source->name, source->email); + error = git_mailmap_resolve(&name, &email, mailmap, source->name, source->email); + if (error < 0) + return error; signature = git__calloc(1, sizeof(git_signature)); GITERR_CHECK_ALLOC(signature); diff --git a/tests/clar_libgit2.c b/tests/clar_libgit2.c index 8d1bbb731..7ffa015a4 100644 --- a/tests/clar_libgit2.c +++ b/tests/clar_libgit2.c @@ -171,8 +171,7 @@ static git_repository *_cl_repo = NULL; git_repository *cl_git_sandbox_init(const char *sandbox) { - /* Get the name of the sandbox folder which will be created - */ + /* Get the name of the sandbox folder which will be created */ const char *basename = cl_fixture_basename(sandbox); /* Copy the whole sandbox folder from our fixtures to our test sandbox diff --git a/tests/mailmap/basic.c b/tests/mailmap/basic.c index 508598440..23f447f53 100644 --- a/tests/mailmap/basic.c +++ b/tests/mailmap/basic.c @@ -13,43 +13,59 @@ const char TEST_MAILMAP[] = " \n" " Other Name \n"; +struct { + const char *real_name; + const char *real_email; + const char *replace_name; + const char *replace_email; +} expected[] = { + { "Foo bar", "foo@bar.com", NULL, "foo@baz.com" }, + { "Foo bar", "foo@bar.com", NULL, "foo@bal.com" }, + { NULL, "email@foo.com", NULL, "otheremail@foo.com" }, + { NULL, "email@foo.com", "Other Name", "yetanotheremail@foo.com" } +}; + void test_mailmap_basic__initialize(void) { git_buf buf = GIT_BUF_INIT; - git_buf_attach_notowned(&buf, TEST_MAILMAP, sizeof(TEST_MAILMAP) - 1); + git_buf_attach_notowned(&buf, TEST_MAILMAP, strlen(TEST_MAILMAP)); cl_git_pass(git_mailmap_from_buffer(&mailmap, &buf)); } void test_mailmap_basic__cleanup(void) { - if (mailmap) { - git_mailmap_free(mailmap); - mailmap = NULL; - } + git_mailmap_free(mailmap); + mailmap = NULL; } void test_mailmap_basic__entry(void) { const git_mailmap_entry *entry; - cl_assert(git_mailmap_entry_count(mailmap) == 4); + cl_assert_equal_sz(ARRAY_SIZE(expected), git_mailmap_entry_count(mailmap)); - entry = git_mailmap_entry_byindex(mailmap, 0); - cl_assert(entry); - cl_assert(!entry->replace_name); - cl_assert(!git__strcmp(entry->replace_email, "foo@baz.com")); + for (size_t i = 0; i < ARRAY_SIZE(expected); ++i) { + entry = git_mailmap_entry_byindex(mailmap, i); + cl_assert(entry); + cl_assert_equal_s(entry->real_name, expected[i].real_name); + cl_assert_equal_s(entry->real_email, expected[i].real_email); + cl_assert_equal_s(entry->replace_name, expected[i].replace_name); + cl_assert_equal_s(entry->replace_email, expected[i].replace_email); + } +} - entry = git_mailmap_entry_byindex(mailmap, 10000); +void test_mailmap_basic__entry_large_index(void) +{ + const git_mailmap_entry *entry = + git_mailmap_entry_byindex(mailmap, 10000); cl_assert(!entry); } void test_mailmap_basic__lookup_not_found(void) { const git_mailmap_entry *entry = git_mailmap_entry_lookup( - mailmap, - "Whoever", - "doesnotexist@fo.com"); + mailmap, "Whoever", "doesnotexist@fo.com"); cl_assert(!entry); } @@ -58,31 +74,32 @@ void test_mailmap_basic__lookup(void) const git_mailmap_entry *entry = git_mailmap_entry_lookup( mailmap, "Typoed the name once", "foo@baz.com"); cl_assert(entry); - cl_assert(!git__strcmp(entry->real_name, "Foo bar")); + cl_assert_equal_s(entry->real_name, "Foo bar"); } void test_mailmap_basic__empty_email_query(void) { const char *name; const char *email; - git_mailmap_resolve( - &name, &email, mailmap, "Author name", "otheremail@foo.com"); - cl_assert(!git__strcmp(name, "Author name")); - cl_assert(!git__strcmp(email, "email@foo.com")); + cl_git_pass(git_mailmap_resolve( + &name, &email, mailmap, "Author name", "otheremail@foo.com")); + cl_assert_equal_s(name, "Author name"); + cl_assert_equal_s(email, "email@foo.com"); } void test_mailmap_basic__name_matching(void) { const char *name; const char *email; - git_mailmap_resolve( - &name, &email, mailmap, "Other Name", "yetanotheremail@foo.com"); - cl_assert(!git__strcmp(name, "Other Name")); - cl_assert(!git__strcmp(email, "email@foo.com")); + cl_git_pass(git_mailmap_resolve( + &name, &email, mailmap, "Other Name", "yetanotheremail@foo.com")); + + cl_assert_equal_s(name, "Other Name"); + cl_assert_equal_s(email, "email@foo.com"); - git_mailmap_resolve( + cl_git_pass(git_mailmap_resolve( &name, &email, mailmap, - "Other Name That Doesn't Match", "yetanotheremail@foo.com"); - cl_assert(!git__strcmp(name, "Other Name That Doesn't Match")); - cl_assert(!git__strcmp(email, "yetanotheremail@foo.com")); + "Other Name That Doesn't Match", "yetanotheremail@foo.com")); + cl_assert_equal_s(name, "Other Name That Doesn't Match"); + cl_assert_equal_s(email, "yetanotheremail@foo.com"); } diff --git a/tests/mailmap/parsing.c b/tests/mailmap/parsing.c index fecb882cd..a40d93b47 100644 --- a/tests/mailmap/parsing.c +++ b/tests/mailmap/parsing.c @@ -44,12 +44,9 @@ static void check_mailmap_resolve( /* Check that the resolver behaves correctly */ for (idx = 0; idx < resolved_size; ++idx) { - git_mailmap_resolve( - &resolved_name, - &resolved_email, - mailmap, - resolved[idx].replace_name, - resolved[idx].replace_email); + cl_git_pass(git_mailmap_resolve( + &resolved_name, &resolved_email, mailmap, + resolved[idx].replace_name, resolved[idx].replace_email)); cl_assert_equal_s(resolved_name, resolved[idx].real_name); cl_assert_equal_s(resolved_email, resolved[idx].real_email); } @@ -70,6 +67,27 @@ void test_mailmap_parsing__string(void) g_mailmap, resolved_untracked, ARRAY_SIZE(resolved_untracked)); } +void test_mailmap_parsing__windows_string(void) +{ + git_buf unixbuf = GIT_BUF_INIT; + git_buf winbuf = GIT_BUF_INIT; + + /* Parse with windows-style line endings */ + git_buf_attach_notowned(&unixbuf, string_mailmap, strlen(string_mailmap)); + git_buf_text_lf_to_crlf(&winbuf, &unixbuf); + + cl_git_pass(git_mailmap_from_buffer(&g_mailmap, &winbuf)); + git_buf_free(winbuf); + + /* We should have parsed all of the entries */ + check_mailmap_entries(g_mailmap, entries, ARRAY_SIZE(entries)); + + /* Check that resolving the entries works */ + check_mailmap_resolve(g_mailmap, resolved, ARRAY_SIZE(resolved)); + check_mailmap_resolve( + g_mailmap, resolved_untracked, ARRAY_SIZE(resolved_untracked)); +} + void test_mailmap_parsing__fromrepo(void) { g_repo = cl_git_sandbox_init("mailmap"); -- cgit v1.2.1 From 8ff0504dd38b804865342d1be2f9d27f6f5d94f0 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sun, 8 Apr 2018 03:01:14 -0400 Subject: mailmap: Rewrite API to support accurate mailmap resolution --- include/git2/mailmap.h | 130 ++++++++--------- src/blame.c | 2 +- src/mailmap.c | 382 +++++++++++++++++++++++++++++++------------------ src/mailmap.h | 35 +++++ src/signature.c | 3 +- 5 files changed, 344 insertions(+), 208 deletions(-) create mode 100644 src/mailmap.h diff --git a/include/git2/mailmap.h b/include/git2/mailmap.h index a8c4ccbf7..761db6720 100644 --- a/include/git2/mailmap.h +++ b/include/git2/mailmap.h @@ -21,103 +21,93 @@ GIT_BEGIN_DECL /** - * A single entry parsed from a mailmap. - */ -typedef struct git_mailmap_entry { - unsigned int version; - - const char *real_name; /**< the real name (may be NULL) */ - const char *real_email; /**< the real email (may be NULL) */ - const char *replace_name; /**< the name to replace (may be NULL) */ - const char *replace_email; /**< the email to replace */ -} git_mailmap_entry; - -#define GIT_MAILMAP_ENTRY_VERSION 1 -#define GIT_MAILMAP_ENTRY_INIT {GIT_MAILMAP_ENTRY_VERSION} - -/** - * Create a mailmap object by parsing a mailmap file. Malformed entries in the - * mailmap are ignored. + * Allocate a new mailmap object. * - * The mailmap must be freed with 'git_mailmap_free'. + * This object is empty, so you'll have to add a mailmap file before you can do + * anything with it. The mailmap must be freed with 'git_mailmap_free'. * - * @param out pointer to store the mailmap - * @param buffer buffer to parse the mailmap from - * @return 0 on success, otherwise an error code + * @param out pointer to store the new mailmap + * @return 0 on success, or an error code */ -GIT_EXTERN(int) git_mailmap_from_buffer(git_mailmap **out, git_buf *buffer); +GIT_EXTERN(int) git_mailmap_new(git_mailmap **out); /** - * Create a mailmap object from the given repository. Malformed entries in the - * mailmap are ignored. - * - * If the repository is not bare, the repository's working directory root will - * be checked for the '.mailmap' file to be parsed. - * - * If the repository is bare, the repository's HEAD commit's tree root will be - * searched for the '.mailmap' file to be parsed. - * - * The mailmap must be freed with 'git_mailmap_free'. + * Free the mailmap and its associated memory. * - * @param out pointer to store the mailmap - * @param repo repository to find the .mailmap in - * @return 0 on success; GIT_ENOTFOUND if .mailmap could not be found, - * otherwise an error code. + * @param mm the mailmap to free */ -GIT_EXTERN(int) git_mailmap_from_repo(git_mailmap **out, git_repository *repo); +GIT_EXTERN(void) git_mailmap_free(git_mailmap *mm); /** - * Free a mailmap created by 'git_mailmap_from_buffer' or - * 'git_mailmap_from_repo'. + * Add a single entry to the given mailmap object. If the entry already exists, + * it will be replaced with the new entry. + * + * @param mm mailmap to add the entry to + * @param real_name the real name to use, or NULL + * @param real_email the real email to use, or NULL + * @param replace_name the name to replace, or NULL + * @param replace_email the email to replace + * @return 0 if it was added, EEXISTS if it replaced an entry, or an error code */ -GIT_EXTERN(void) git_mailmap_free(git_mailmap *mailmap); +GIT_EXTERN(int) git_mailmap_add_entry( + git_mailmap *mm, const char *real_name, const char *real_email, + const char *replace_name, const char *replace_email); /** - * Resolve a name and email to the corresponding real name and email. + * Parse mailmap entries from a buffer. * - * The lifetime of the string results is tied to the `mailmap`, `name`, and - * `email` parameters. - * - * @param name_out either 'name', or the real name to use. - * You should NOT free this value. - * @param email_out either 'email' or the real email to use, - * You should NOT free this value. - * @param mailmap the mailmap to perform the lookup in. (may be NULL) - * @param name the name to resolve. - * @param email the email to resolve. - * @return 0 on success, otherwise an error code. + * @param mm mailmap to add the entries to + * @param buf the buffer to read the mailmap file from + * @return 0 on success, or an error code */ -GIT_EXTERN(int) git_mailmap_resolve( - const char **name_out, const char **email_out, - const git_mailmap *mailmap, const char *name, const char *email); +GIT_EXTERN(int) git_mailmap_add_buffer(git_mailmap *mm, const git_buf *buf); /** - * Get the number of mailmap entries in this mailmap. + * Create a new mailmap instance containing a single mailmap file + * + * This method is a simple utility wrapper for the following sequence + * of calls: + * - git_mailmap_new + * - git_mailmap_add_buffer + * + * @param out pointer to store the new mailmap + * @param buf buffer to parse the mailmap from + * @return 0 on success, or an error code */ -GIT_EXTERN(size_t) git_mailmap_entry_count(const git_mailmap *mailmap); +GIT_EXTERN(int) git_mailmap_from_buffer(git_mailmap **out, const git_buf *buf); /** - * Lookup a mailmap entry by index. + * Create a new mailmap instance from a repository, loading mailmap files based + * on the repository's configuration. * - * Do not free the mailmap entry, it is owned by the mailmap. + * Mailmaps are loaded in the following order: + * 1. '.mailmap' in the root of the repository's working directory, if present. + * 2. The blob object identified by the 'mailmap.blob' config entry, if set. + * [NOTE: 'mailmap.blob' defaults to 'HEAD:.mailmap' in bare repositories] + * 3. The path in the 'mailmap.file' config entry, if set. * - * @return the mailmap entry at index, or NULL if it cannot be found. + * @param out pointer to store the new mailmap + * @param repo repository to load mailmap information from + * @return 0 on success, or an error code */ -GIT_EXTERN(const git_mailmap_entry *) git_mailmap_entry_byindex( - const git_mailmap *mailmap, size_t idx); +GIT_EXTERN(int) git_mailmap_from_repository( + git_mailmap **out, git_repository *repo); /** - * Lookup a mailmap entry by name/email pair. + * Resolve a name and email to the corresponding real name and email. * - * Do not free the mailmap entry, it is owned by the mailmap. + * The lifetime of the strings are tied to `mm`, `name`, and `email` parameters. * - * @param mailmap the mailmap to perform the lookup in. (may be NULL) - * @param name the name to perform the lookup with. - * @param email the email to perform the lookup with. - * @return the corresponding mailmap entry, or NULL if it cannot be found. + * @param real_name pointer to store the real name + * @param real_email pointer to store the real email + * @param mm the mailmap to perform a lookup with (may be NULL) + * @param name the name to look up + * @param email the email to look up + * @return 0 on success, or an error code */ -GIT_EXTERN(const git_mailmap_entry *) git_mailmap_entry_lookup( - const git_mailmap *mailmap, const char *name, const char *email); +GIT_EXTERN(int) git_mailmap_resolve( + const char **real_name, const char **real_email, + const git_mailmap *mm, const char *name, const char *email); /** @} */ GIT_END_DECL diff --git a/src/blame.c b/src/blame.c index 0624bf4f6..fc87bd1c1 100644 --- a/src/blame.c +++ b/src/blame.c @@ -134,7 +134,7 @@ git_blame* git_blame__alloc( } if (opts.flags & GIT_BLAME_USE_MAILMAP) - git_mailmap_from_repo(&gbr->mailmap, repo); + git_mailmap_from_repository(&gbr->mailmap, repo); return gbr; } diff --git a/src/mailmap.c b/src/mailmap.c index a178c3172..3da46a83c 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -5,21 +5,20 @@ * a Linking Exception. For full terms see the included COPYING file. */ -#include "git2/mailmap.h" +#include "mailmap.h" +#include "common.h" +#include "path.h" +#include "repository.h" +#include "git2/config.h" +#include "git2/revparse.h" #include "blob.h" -#include "commit.h" #include "parse.h" -#include "git2/common.h" -#include "git2/repository.h" -#include "git2/revparse.h" -#include "git2/sys/commit.h" - -#define MAILMAP_FILE ".mailmap" -struct git_mailmap { - git_vector entries; -}; +#define MM_FILE ".mailmap" +#define MM_FILE_CONFIG "mailmap.file" +#define MM_BLOB_CONFIG "mailmap.blob" +#define MM_BLOB_DEFAULT "HEAD:" MM_FILE static void mailmap_entry_free(git_mailmap_entry *entry) { @@ -33,6 +32,37 @@ static void mailmap_entry_free(git_mailmap_entry *entry) git__free(entry); } +/* + * First we sort by replace_email, then replace_name (if present). + * Entries with names are greater than entries without. + */ +static int mailmap_entry_cmp(const void *a_raw, const void *b_raw) +{ + const git_mailmap_entry *a = (const git_mailmap_entry *)a_raw; + const git_mailmap_entry *b = (const git_mailmap_entry *)b_raw; + int cmp; + + assert(a && b && a->replace_email && b->replace_email); + + cmp = git__strcmp(a->replace_email, b->replace_email); + if (cmp) + return cmp; + + /* NULL replace_names are less than not-NULL ones */ + if (a->replace_name == NULL || b->replace_name == NULL) + return (int)(a->replace_name != NULL) - (int)(b->replace_name != NULL); + + return git__strcmp(a->replace_name, b->replace_name); +} + +/* Replace the old entry with the new on duplicate. */ +static int mailmap_entry_replace(void **old_raw, void *new_raw) +{ + mailmap_entry_free((git_mailmap_entry *)*old_raw); + *old_raw = new_raw; + return GIT_EEXISTS; +} + /* Check if we're at the end of line, w/ comments */ static bool is_eol(git_parse_ctx *ctx) { @@ -114,12 +144,68 @@ static int parse_mailmap_entry( return 0; } -int git_mailmap_from_buffer(git_mailmap **out, git_buf *buf) +int git_mailmap_new(git_mailmap **out) +{ + int error; + git_mailmap *mm = git__calloc(1, sizeof(git_mailmap)); + GITERR_CHECK_ALLOC(mm); + + error = git_vector_init(&mm->entries, 0, mailmap_entry_cmp); + if (error < 0) { + git__free(mm); + return error; + } + *out = mm; + return 0; +} + +void git_mailmap_free(git_mailmap *mm) +{ + size_t idx; + git_mailmap_entry *entry; + if (!mm) + return; + + git_vector_foreach(&mm->entries, idx, entry) + mailmap_entry_free(entry); + git__free(mm); +} + +int git_mailmap_add_entry( + git_mailmap *mm, const char *real_name, const char *real_email, + const char *replace_name, const char *replace_email) +{ + int error; + git_mailmap_entry *entry = git__calloc(1, sizeof(git_mailmap_entry)); + GITERR_CHECK_ALLOC(entry); + + assert(mm && replace_email && *replace_email); + + if (real_name && *real_name) { + entry->real_name = git__strdup(real_name); + GITERR_CHECK_ALLOC(entry->real_name); + } + if (real_email && *real_email) { + entry->real_email = git__strdup(real_email); + GITERR_CHECK_ALLOC(entry->real_email); + } + if (replace_name && *replace_name) { + entry->replace_name = git__strdup(replace_name); + GITERR_CHECK_ALLOC(entry->replace_name); + } + entry->replace_email = git__strdup(replace_email); + GITERR_CHECK_ALLOC(entry->replace_email); + + error = git_vector_insert_sorted(&mm->entries, entry, mailmap_entry_replace); + if (error < 0 && error != GIT_EEXISTS) + mailmap_entry_free(entry); + + return error; +} + +int git_mailmap_add_buffer(git_mailmap *mm, const git_buf *buf) { int error; - git_mailmap *mm; - size_t entry_size; - char *entry_data; git_mailmap_entry *entry = NULL; git_parse_ctx ctx; @@ -134,14 +220,6 @@ int git_mailmap_from_buffer(git_mailmap **out, git_buf *buf) git_parse_ctx_init(&ctx, buf->ptr, buf->size); - /* Create our mailmap object */ - mm = git__calloc(1, sizeof(git_mailmap)); - GITERR_CHECK_ALLOC(mm); - - error = git_vector_init(&mm->entries, 0, NULL); - if (error < 0) - goto cleanup; - /* Run the parser */ while (ctx.remain_len > 0) { error = parse_mailmap_entry( @@ -154,7 +232,6 @@ int git_mailmap_from_buffer(git_mailmap **out, git_buf *buf) entry = git__calloc(1, sizeof(git_mailmap_entry)); GITERR_CHECK_ALLOC(entry); - entry->version = GIT_MAILMAP_ENTRY_VERSION; if (real_name.size > 0) { entry->real_name = git__substrdup(real_name.ptr, real_name.size); @@ -171,19 +248,17 @@ int git_mailmap_from_buffer(git_mailmap **out, git_buf *buf) entry->replace_email = git__substrdup(replace_email.ptr, replace_email.size); GITERR_CHECK_ALLOC(entry->replace_email); - error = git_vector_insert(&mm->entries, entry); - if (error < 0) + error = git_vector_insert_sorted( + &mm->entries, entry, mailmap_entry_replace); + if (error < 0 && error != GIT_EEXISTS) goto cleanup; + entry = NULL; + error = 0; } - /* fill in *out, and make sure we don't free our mailmap */ - *out = mm; - mm = NULL; - cleanup: mailmap_entry_free(entry); - git_mailmap_free(mm); /* We never allocate data in these buffers, but better safe than sorry */ git_buf_free(&real_name); @@ -193,157 +268,192 @@ cleanup: return error; } -void git_mailmap_free(git_mailmap *mailmap) -{ - if (!mailmap) - return; - - git_vector_foreach(&mailmap->entries, i, entry) { - mailmap_entry_free(entry); - } - git_vector_free(&mailmap->entries); - - git__free(mailmap); -} - -int git_mailmap_resolve( - const char **name_out, const char **email_out, - const git_mailmap *mailmap, - const char *name, const char *email) -{ - const git_mailmap_entry *entry = NULL; - assert(name && email); - - *name_out = name; - *email_out = email; - - if (!mailmap) - return 0; - - entry = git_mailmap_entry_lookup(mailmap, name, email); - if (entry) { - if (entry->real_name) - *name_out = entry->real_name; - if (entry->real_email) - *email_out = entry->real_email; - } - return 0; -} - -const git_mailmap_entry *git_mailmap_entry_lookup( - const git_mailmap *mailmap, const char *name, const char *email) +int git_mailmap_from_buffer(git_mailmap **out, const git_buf *buffer) { - size_t i; - git_mailmap_entry *entry; - assert(name && email); - - if (!mailmap) - return NULL; - - git_vector_foreach(&mailmap->entries, i, entry) { - if (git__strcmp(email, entry->replace_email)) - continue; - if (entry->replace_name && git__strcmp(name, entry->replace_name)) - continue; + int error = git_mailmap_new(out); + if (error < 0) + return error; - return entry; + error = git_mailmap_add_buffer(*out, buffer); + if (error < 0) { + git_mailmap_free(*out); + *out = NULL; } - - return NULL; -} - -const git_mailmap_entry *git_mailmap_entry_byindex( - const git_mailmap *mailmap, size_t idx) -{ - if (mailmap) - return git_vector_get(&mailmap->entries, idx); - return NULL; -} - -size_t git_mailmap_entry_count(const git_mailmap *mailmap) -{ - if (mailmap) - return git_vector_length(&mailmap->entries); - return 0; + return error; } -static int mailmap_from_bare_repo(git_mailmap **mailmap, git_repository *repo) +static int mailmap_add_blob( + git_mailmap *mm, git_repository *repo, const char *spec) { - git_reference *head = NULL; - git_object *tree = NULL; + git_object *object = NULL; git_blob *blob = NULL; git_buf content = GIT_BUF_INIT; int error; - assert(git_repository_is_bare(repo)); + assert(mm && repo); - /* In bare repositories, fall back to reading from HEAD's tree */ - error = git_repository_head(&head, repo); + error = git_revparse_single(&object, repo, spec); if (error < 0) goto cleanup; - error = git_reference_peel(&tree, head, GIT_OBJ_TREE); + error = git_object_peel((git_object **)&blob, object, GIT_OBJ_BLOB); if (error < 0) goto cleanup; - error = git_object_lookup_bypath( - (git_object **) &blob, tree, MAILMAP_FILE, GIT_OBJ_BLOB); + error = git_blob__getbuf(&content, blob); if (error < 0) goto cleanup; - error = git_blob_filtered_content(&content, blob, MAILMAP_FILE, false); - if (error < 0) - goto cleanup; - - error = git_mailmap_from_buffer(mailmap, &content); + error = git_mailmap_add_buffer(mm, &content); if (error < 0) goto cleanup; cleanup: git_buf_free(&content); git_blob_free(blob); - git_object_free(tree); - git_reference_free(head); - + git_object_free(object); return error; } -static int mailmap_from_workdir_repo(git_mailmap **mailmap, git_repository *repo) +static int mailmap_add_file_ondisk( + git_mailmap *mm, const char *path, git_repository *repo) { - git_buf path = GIT_BUF_INIT; - git_buf data = GIT_BUF_INIT; + const char *base = repo ? git_repository_workdir(repo) : NULL; + git_buf fullpath = GIT_BUF_INIT; + git_buf content = GIT_BUF_INIT; int error; - assert(!git_repository_is_bare(repo)); - - /* In non-bare repositories, .mailmap should be read from the workdir */ - error = git_buf_joinpath(&path, git_repository_workdir(repo), MAILMAP_FILE); + error = git_path_join_unrooted(&fullpath, path, base, NULL); if (error < 0) goto cleanup; - error = git_futils_readbuffer(&data, git_buf_cstr(&path)); + error = git_futils_readbuffer(&content, fullpath.ptr); if (error < 0) goto cleanup; - error = git_mailmap_from_buffer(mailmap, &data); + error = git_mailmap_add_buffer(mm, &content); if (error < 0) goto cleanup; cleanup: - git_buf_free(&path); - git_buf_free(&data); - + git_buf_free(&fullpath); + git_buf_free(&content); return error; } -int git_mailmap_from_repo(git_mailmap **mailmap, git_repository *repo) +/* NOTE: Only expose with an error return, currently never errors */ +static void mailmap_add_from_repository(git_mailmap *mm, git_repository *repo) { - assert(mailmap && repo); + git_config *config = NULL; + git_buf spec_buf = GIT_BUF_INIT; + git_buf path_buf = GIT_BUF_INIT; + const char *spec = NULL; + const char *path = NULL; + + assert(mm && repo); + + /* If we're in a bare repo, default blob to 'HEAD:.mailmap' */ + if (repo->is_bare) + spec = MM_BLOB_DEFAULT; + + /* Try to load 'mailmap.file' and 'mailmap.blob' cfgs from the repo */ + if (git_repository_config(&config, repo) == 0) { + if (git_config_get_string_buf(&spec_buf, config, MM_BLOB_CONFIG) == 0) + spec = spec_buf.ptr; + if (git_config_get_path(&path_buf, config, MM_FILE_CONFIG) == 0) + path = path_buf.ptr; + } - *mailmap = NULL; + /* + * Load mailmap files in order, overriding previous entries with new ones. + * 1. The '.mailmap' file in the repository's workdir root, + * 2. The blob described by the 'mailmap.blob' config (default HEAD:.mailmap), + * 3. The file described by the 'mailmap.file' config. + * + * We ignore errors from these loads, as these files may not exist, or may + * contain invalid information, and we don't want to report that error. + * + * XXX: Warn? + */ + if (!repo->is_bare) + mailmap_add_file_ondisk(mm, MM_FILE, repo); + if (spec != NULL) + mailmap_add_blob(mm, repo, spec); + if (path != NULL) + mailmap_add_file_ondisk(mm, path, repo); + + git_buf_free(&spec_buf); + git_buf_free(&path_buf); + git_config_free(config); +} - if (git_repository_is_bare(repo)) - return mailmap_from_bare_repo(mailmap, repo); - else - return mailmap_from_workdir_repo(mailmap, repo); +int git_mailmap_from_repository(git_mailmap **out, git_repository *repo) +{ + int error = git_mailmap_new(out); + if (error < 0) + return error; + mailmap_add_from_repository(*out, repo); + return 0; +} + +const git_mailmap_entry *git_mailmap_entry_lookup( + const git_mailmap *mm, const char *name, const char *email) +{ + int error; + ssize_t fallback = -1; + size_t idx; + git_mailmap_entry *entry; + git_mailmap_entry needle = { NULL, NULL, NULL, (char *)email }; + + assert(email); + + if (!mm) + return NULL; + + /* + * We want to find the place to start looking. so we do a binary search for + * the "fallback" nameless entry. If we find it, we advance past it and record + * the index. + */ + error = git_vector_bsearch(&idx, (git_vector *)&mm->entries, &needle); + if (error >= 0) + fallback = idx++; + else if (error != GIT_ENOTFOUND) + return NULL; + + /* do a linear search for an exact match */ + for (; idx < git_vector_length(&mm->entries); ++idx) { + entry = git_vector_get(&mm->entries, idx); + + if (git__strcmp(entry->replace_email, email)) + break; /* it's a different email, so we're done looking */ + + assert(entry->replace_name); /* should be specific */ + if (!name || !git__strcmp(entry->replace_name, name)) + return entry; + } + + if (fallback < 0) + return NULL; /* no fallback */ + return git_vector_get(&mm->entries, fallback); +} + +int git_mailmap_resolve( + const char **real_name, const char **real_email, + const git_mailmap *mailmap, + const char *name, const char *email) +{ + const git_mailmap_entry *entry = NULL; + assert(name && email); + + *real_name = name; + *real_email = email; + + if ((entry = git_mailmap_entry_lookup(mailmap, name, email))) { + if (entry->real_name) + *real_name = entry->real_name; + if (entry->real_email) + *real_email = entry->real_email; + } + return 0; } diff --git a/src/mailmap.h b/src/mailmap.h new file mode 100644 index 000000000..2c9736a4a --- /dev/null +++ b/src/mailmap.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_mailmap_h__ +#define INCLUDE_mailmap_h__ + +#include "git2/mailmap.h" +#include "vector.h" + +/* + * A mailmap is stored as a sorted vector of 'git_mailmap_entry's. These entries + * are sorted first by 'replace_email', and then by 'replace_name'. NULL + * replace_names are ordered first. + * + * Looking up a name and email in the mailmap is done with a binary search. + */ +struct git_mailmap { + git_vector entries; +}; + +/* Single entry parsed from a mailmap */ +typedef struct git_mailmap_entry { + char *real_name; /**< the real name (may be NULL) */ + char *real_email; /**< the real email (may be NULL) */ + char *replace_name; /**< the name to replace (may be NULL) */ + char *replace_email; /**< the email to replace */ +} git_mailmap_entry; + +const git_mailmap_entry *git_mailmap_entry_lookup( + const git_mailmap *mm, const char *name, const char *email); + +#endif diff --git a/src/signature.c b/src/signature.c index d922fda4b..a8177e036 100644 --- a/src/signature.c +++ b/src/signature.c @@ -116,7 +116,8 @@ int git_signature_with_mailmap( if (source == NULL) return 0; - error = git_mailmap_resolve(&name, &email, mailmap, source->name, source->email); + error = git_mailmap_resolve( + &name, &email, mailmap, source->name, source->email); if (error < 0) return error; -- cgit v1.2.1 From a140c138757e6d4dbcd34a2c68ca34e87cc76238 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sun, 8 Apr 2018 03:01:37 -0400 Subject: mailmap: Updates tests for new API and features --- tests/mailmap/basic.c | 28 ++--- tests/mailmap/blame.c | 2 +- tests/mailmap/mailmap_helpers.h | 10 +- tests/mailmap/parsing.c | 140 +++++++++++++++++++-- tests/resources/mailmap/.gitted/index | Bin 209 -> 289 bytes .../69/b9768d022706dab26e2af4dd5a13f42039e36f | Bin 0 -> 123 bytes .../6a/0fc44893d4867166f9d321f78c269b3e42b08b | Bin 0 -> 67 bytes .../f6/3578091d884c3066a003c50eb6c85ae7542269 | 2 + tests/resources/mailmap/.gitted/refs/heads/master | 2 +- tests/resources/mailmap/file_override | 2 + 10 files changed, 153 insertions(+), 33 deletions(-) create mode 100644 tests/resources/mailmap/.gitted/objects/69/b9768d022706dab26e2af4dd5a13f42039e36f create mode 100644 tests/resources/mailmap/.gitted/objects/6a/0fc44893d4867166f9d321f78c269b3e42b08b create mode 100644 tests/resources/mailmap/.gitted/objects/f6/3578091d884c3066a003c50eb6c85ae7542269 create mode 100644 tests/resources/mailmap/file_override diff --git a/tests/mailmap/basic.c b/tests/mailmap/basic.c index 23f447f53..b8a91327e 100644 --- a/tests/mailmap/basic.c +++ b/tests/mailmap/basic.c @@ -2,7 +2,7 @@ #include "clar_libgit2.h" #include "common.h" -#include "git2/mailmap.h" +#include "mailmap.h" static git_mailmap *mailmap = NULL; @@ -41,27 +41,25 @@ void test_mailmap_basic__cleanup(void) void test_mailmap_basic__entry(void) { + size_t idx; const git_mailmap_entry *entry; - cl_assert_equal_sz(ARRAY_SIZE(expected), git_mailmap_entry_count(mailmap)); + /* Check that we have the expected # of entries */ + cl_assert_equal_sz(ARRAY_SIZE(expected), git_vector_length(&mailmap->entries)); + + for (idx = 0; idx < ARRAY_SIZE(expected); ++idx) { + /* Try to look up each entry and make sure they match */ + entry = git_mailmap_entry_lookup( + mailmap, expected[idx].replace_name, expected[idx].replace_email); - for (size_t i = 0; i < ARRAY_SIZE(expected); ++i) { - entry = git_mailmap_entry_byindex(mailmap, i); cl_assert(entry); - cl_assert_equal_s(entry->real_name, expected[i].real_name); - cl_assert_equal_s(entry->real_email, expected[i].real_email); - cl_assert_equal_s(entry->replace_name, expected[i].replace_name); - cl_assert_equal_s(entry->replace_email, expected[i].replace_email); + cl_assert_equal_s(entry->real_name, expected[idx].real_name); + cl_assert_equal_s(entry->real_email, expected[idx].real_email); + cl_assert_equal_s(entry->replace_name, expected[idx].replace_name); + cl_assert_equal_s(entry->replace_email, expected[idx].replace_email); } } -void test_mailmap_basic__entry_large_index(void) -{ - const git_mailmap_entry *entry = - git_mailmap_entry_byindex(mailmap, 10000); - cl_assert(!entry); -} - void test_mailmap_basic__lookup_not_found(void) { const git_mailmap_entry *entry = git_mailmap_entry_lookup( diff --git a/tests/mailmap/blame.c b/tests/mailmap/blame.c index 9ab085bd3..328f4bce1 100644 --- a/tests/mailmap/blame.c +++ b/tests/mailmap/blame.c @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "git2/repository.h" #include "git2/blame.h" -#include "git2/mailmap.h" +#include "mailmap.h" #include "mailmap_helpers.h" static git_repository *g_repo; diff --git a/tests/mailmap/mailmap_helpers.h b/tests/mailmap/mailmap_helpers.h index 49df55fb1..173536dd0 100644 --- a/tests/mailmap/mailmap_helpers.h +++ b/tests/mailmap/mailmap_helpers.h @@ -1,4 +1,4 @@ -#include "git2/mailmap.h" +#include "mailmap.h" typedef struct mailmap_entry { const char *real_name; @@ -42,11 +42,3 @@ static const mailmap_entry resolved[] = { { "Santa Claus", "santa.claus@northpole.xx", "Clause", "me@company.xx" }, { "Charles", "charles@charles.xx", "Charles", "charles@charles.xx" } }; - -static const mailmap_entry resolved_bare[] = { - { "xx", "untracked@company.xx", "xx", "untracked@company.xx" } -}; - -static const mailmap_entry resolved_untracked[] = { - { "Untracked", "untracked@company.xx", "xx", "untracked@company.xx" } -}; diff --git a/tests/mailmap/parsing.c b/tests/mailmap/parsing.c index a40d93b47..70110c033 100644 --- a/tests/mailmap/parsing.c +++ b/tests/mailmap/parsing.c @@ -2,32 +2,41 @@ #include "repository.h" #include "git2/sys/repository.h" #include "mailmap_helpers.h" +#include "buf_text.h" static git_repository *g_repo; static git_mailmap *g_mailmap; +static git_config *g_config; void test_mailmap_parsing__initialize(void) { g_repo = NULL; g_mailmap = NULL; + g_config = NULL; } void test_mailmap_parsing__cleanup(void) { git_mailmap_free(g_mailmap); + git_config_free(g_config); cl_git_sandbox_cleanup(); } static void check_mailmap_entries( const git_mailmap *mailmap, const mailmap_entry *entries, size_t entries_size) { - const git_mailmap_entry *parsed = NULL; + const git_mailmap_entry *parsed; size_t idx; - /* Check that the parsed entries match */ - cl_assert_equal_sz(entries_size, git_mailmap_entry_count(mailmap)); + /* Check the correct # of entries were parsed */ + cl_assert_equal_sz(entries_size, git_vector_length(&mailmap->entries)); + + /* Make sure looking up each entry succeeds */ for (idx = 0; idx < entries_size; ++idx) { - parsed = git_mailmap_entry_byindex(mailmap, idx); + parsed = git_mailmap_entry_lookup( + mailmap, entries[idx].replace_name, entries[idx].replace_email); + + cl_assert(parsed); cl_assert_equal_s(parsed->real_name, entries[idx].real_name); cl_assert_equal_s(parsed->real_email, entries[idx].real_email); cl_assert_equal_s(parsed->replace_name, entries[idx].replace_name); @@ -52,6 +61,10 @@ static void check_mailmap_resolve( } } +static const mailmap_entry resolved_untracked[] = { + { "Untracked", "untracked@company.xx", "xx", "untracked@company.xx" } +}; + void test_mailmap_parsing__string(void) { git_buf buf = GIT_BUF_INIT; @@ -77,7 +90,7 @@ void test_mailmap_parsing__windows_string(void) git_buf_text_lf_to_crlf(&winbuf, &unixbuf); cl_git_pass(git_mailmap_from_buffer(&g_mailmap, &winbuf)); - git_buf_free(winbuf); + git_buf_free(&winbuf); /* We should have parsed all of the entries */ check_mailmap_entries(g_mailmap, entries, ARRAY_SIZE(entries)); @@ -93,7 +106,7 @@ void test_mailmap_parsing__fromrepo(void) g_repo = cl_git_sandbox_init("mailmap"); cl_check(!git_repository_is_bare(g_repo)); - cl_git_pass(git_mailmap_from_repo(&g_mailmap, g_repo)); + cl_git_pass(git_mailmap_from_repository(&g_mailmap, g_repo)); /* We should have parsed all of the entries */ check_mailmap_entries(g_mailmap, entries, ARRAY_SIZE(entries)); @@ -104,13 +117,17 @@ void test_mailmap_parsing__fromrepo(void) g_mailmap, resolved_untracked, ARRAY_SIZE(resolved_untracked)); } +static const mailmap_entry resolved_bare[] = { + { "xx", "untracked@company.xx", "xx", "untracked@company.xx" } +}; + void test_mailmap_parsing__frombare(void) { g_repo = cl_git_sandbox_init("mailmap/.gitted"); cl_git_pass(git_repository_set_bare(g_repo)); cl_check(git_repository_is_bare(g_repo)); - cl_git_pass(git_mailmap_from_repo(&g_mailmap, g_repo)); + cl_git_pass(git_mailmap_from_repository(&g_mailmap, g_repo)); /* We should have parsed all of the entries, except for the untracked one */ check_mailmap_entries(g_mailmap, entries, ARRAY_SIZE(entries) - 1); @@ -120,3 +137,112 @@ void test_mailmap_parsing__frombare(void) check_mailmap_resolve( g_mailmap, resolved_bare, ARRAY_SIZE(resolved_bare)); } + +static const mailmap_entry resolved_with_file_override[] = { + { "Brad", "cto@company.xx", "Brad", "cto@coompany.xx" }, + { "Brad L", "cto@company.xx", "Brad L", "cto@coompany.xx" }, + { "Some Dude", "some@dude.xx", "nick1", "bugs@company.xx" }, + { "Other Author", "other@author.xx", "nick2", "bugs@company.xx" }, + { "nick3", "bugs@company.xx", "nick3", "bugs@company.xx" }, + { "Other Author", "other@author.xx", "Some Garbage", "nick2@company.xx" }, + { "Joseph", "joseph@company.xx", "Joseph", "bugs@company.xx" }, + { "Santa Claus", "santa.claus@northpole.xx", "Clause", "me@company.xx" }, + { "Charles", "charles@charles.xx", "Charles", "charles@charles.xx" }, + + /* This name is overridden by file_override */ + { "File Override", "phil@company.xx", "unknown", "phil@company.xx" }, + { "Other Name", "fileoverridename@company.xx", "override", "fileoverridename@company.xx" } +}; + +void test_mailmap_parsing__file_config(void) +{ + g_repo = cl_git_sandbox_init("mailmap"); + cl_git_pass(git_repository_config(&g_config, g_repo)); + + cl_git_pass(git_config_set_string( + g_config, "mailmap.file", cl_fixture("mailmap/file_override"))); + + cl_git_pass(git_mailmap_from_repository(&g_mailmap, g_repo)); + + /* Check we don't have duplicate entries */ + cl_assert_equal_sz(git_vector_length(&g_mailmap->entries), 9); + + /* Check that resolving the entries works */ + check_mailmap_resolve( + g_mailmap, resolved_with_file_override, + ARRAY_SIZE(resolved_with_file_override)); +} + +static const mailmap_entry resolved_with_blob_override[] = { + { "Brad", "cto@company.xx", "Brad", "cto@coompany.xx" }, + { "Brad L", "cto@company.xx", "Brad L", "cto@coompany.xx" }, + { "Some Dude", "some@dude.xx", "nick1", "bugs@company.xx" }, + { "Other Author", "other@author.xx", "nick2", "bugs@company.xx" }, + { "nick3", "bugs@company.xx", "nick3", "bugs@company.xx" }, + { "Other Author", "other@author.xx", "Some Garbage", "nick2@company.xx" }, + { "Joseph", "joseph@company.xx", "Joseph", "bugs@company.xx" }, + { "Santa Claus", "santa.claus@northpole.xx", "Clause", "me@company.xx" }, + { "Charles", "charles@charles.xx", "Charles", "charles@charles.xx" }, + + /* This name is overridden by blob_override */ + { "Blob Override", "phil@company.xx", "unknown", "phil@company.xx" }, + { "Other Name", "bloboverridename@company.xx", "override", "bloboverridename@company.xx" } +}; + +void test_mailmap_parsing__blob_config(void) +{ + g_repo = cl_git_sandbox_init("mailmap"); + cl_git_pass(git_repository_config(&g_config, g_repo)); + + cl_git_pass(git_config_set_string( + g_config, "mailmap.blob", "HEAD:blob_override")); + + cl_git_pass(git_mailmap_from_repository(&g_mailmap, g_repo)); + + /* Check we don't have duplicate entries */ + cl_assert_equal_sz(git_vector_length(&g_mailmap->entries), 9); + + /* Check that resolving the entries works */ + check_mailmap_resolve( + g_mailmap, resolved_with_blob_override, + ARRAY_SIZE(resolved_with_blob_override)); +} + +static const mailmap_entry bare_resolved_with_blob_override[] = { + /* As mailmap.blob is set, we won't load HEAD:.mailmap */ + { "Brad", "cto@coompany.xx", "Brad", "cto@coompany.xx" }, + { "Brad L", "cto@coompany.xx", "Brad L", "cto@coompany.xx" }, + { "nick1", "bugs@company.xx", "nick1", "bugs@company.xx" }, + { "nick2", "bugs@company.xx", "nick2", "bugs@company.xx" }, + { "nick3", "bugs@company.xx", "nick3", "bugs@company.xx" }, + { "Some Garbage", "nick2@company.xx", "Some Garbage", "nick2@company.xx" }, + { "Joseph", "bugs@company.xx", "Joseph", "bugs@company.xx" }, + { "Clause", "me@company.xx", "Clause", "me@company.xx" }, + { "Charles", "charles@charles.xx", "Charles", "charles@charles.xx" }, + + /* This name is overridden by blob_override */ + { "Blob Override", "phil@company.xx", "unknown", "phil@company.xx" }, + { "Other Name", "bloboverridename@company.xx", "override", "bloboverridename@company.xx" } +}; + +void test_mailmap_parsing__bare_blob_config(void) +{ + g_repo = cl_git_sandbox_init("mailmap/.gitted"); + cl_git_pass(git_repository_set_bare(g_repo)); + cl_check(git_repository_is_bare(g_repo)); + + cl_git_pass(git_repository_config(&g_config, g_repo)); + + cl_git_pass(git_config_set_string( + g_config, "mailmap.blob", "HEAD:blob_override")); + + cl_git_pass(git_mailmap_from_repository(&g_mailmap, g_repo)); + + /* Check that we only have the 2 entries */ + cl_assert_equal_sz(git_vector_length(&g_mailmap->entries), 2); + + /* Check that resolving the entries works */ + check_mailmap_resolve( + g_mailmap, bare_resolved_with_blob_override, + ARRAY_SIZE(bare_resolved_with_blob_override)); +} diff --git a/tests/resources/mailmap/.gitted/index b/tests/resources/mailmap/.gitted/index index c46a1b440..af175ca30 100644 Binary files a/tests/resources/mailmap/.gitted/index and b/tests/resources/mailmap/.gitted/index differ diff --git a/tests/resources/mailmap/.gitted/objects/69/b9768d022706dab26e2af4dd5a13f42039e36f b/tests/resources/mailmap/.gitted/objects/69/b9768d022706dab26e2af4dd5a13f42039e36f new file mode 100644 index 000000000..bda7a5d46 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/69/b9768d022706dab26e2af4dd5a13f42039e36f differ diff --git a/tests/resources/mailmap/.gitted/objects/6a/0fc44893d4867166f9d321f78c269b3e42b08b b/tests/resources/mailmap/.gitted/objects/6a/0fc44893d4867166f9d321f78c269b3e42b08b new file mode 100644 index 000000000..9c7003111 Binary files /dev/null and b/tests/resources/mailmap/.gitted/objects/6a/0fc44893d4867166f9d321f78c269b3e42b08b differ diff --git a/tests/resources/mailmap/.gitted/objects/f6/3578091d884c3066a003c50eb6c85ae7542269 b/tests/resources/mailmap/.gitted/objects/f6/3578091d884c3066a003c50eb6c85ae7542269 new file mode 100644 index 000000000..16fd91867 --- /dev/null +++ b/tests/resources/mailmap/.gitted/objects/f6/3578091d884c3066a003c50eb6c85ae7542269 @@ -0,0 +1,2 @@ +x[j0EUB_2ҌmE-$;߹.\u`z8`dm)YK32x(S`t$ρ%ю#/\3`!‡Z]޼+3+,}ZL{ \ No newline at end of file diff --git a/tests/resources/mailmap/.gitted/refs/heads/master b/tests/resources/mailmap/.gitted/refs/heads/master index 0daf56a2e..b6dd3087a 100644 --- a/tests/resources/mailmap/.gitted/refs/heads/master +++ b/tests/resources/mailmap/.gitted/refs/heads/master @@ -1 +1 @@ -7100e631fb4d5deba31fdc8acc98f4fb5c1573fd +f63578091d884c3066a003c50eb6c85ae7542269 diff --git a/tests/resources/mailmap/file_override b/tests/resources/mailmap/file_override new file mode 100644 index 000000000..94293a971 --- /dev/null +++ b/tests/resources/mailmap/file_override @@ -0,0 +1,2 @@ +File Override +Other Name -- cgit v1.2.1 From 56303e1ade453648230115cdaaba8244273f3315 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Mon, 7 May 2018 11:59:00 -0700 Subject: mailmap: API and style cleanup --- include/git2/mailmap.h | 21 ++++++- include/git2/signature.h | 12 ---- include/git2/types.h | 2 +- src/commit.c | 5 +- src/mailmap.c | 132 +++++++++++++++++++++++---------------- src/signature.c | 24 +------ tests/mailmap/basic.c | 5 +- tests/mailmap/blame.c | 8 +-- tests/mailmap/mailmap_helpers.h | 44 ------------- tests/mailmap/mailmap_testdata.h | 44 +++++++++++++ tests/mailmap/parsing.c | 8 +-- 11 files changed, 156 insertions(+), 149 deletions(-) delete mode 100644 tests/mailmap/mailmap_helpers.h create mode 100644 tests/mailmap/mailmap_testdata.h diff --git a/include/git2/mailmap.h b/include/git2/mailmap.h index 761db6720..b22a00c67 100644 --- a/include/git2/mailmap.h +++ b/include/git2/mailmap.h @@ -58,9 +58,11 @@ GIT_EXTERN(int) git_mailmap_add_entry( * * @param mm mailmap to add the entries to * @param buf the buffer to read the mailmap file from + * @param len the length of the input buffer [optional: 0 defaults to 'strlen'] * @return 0 on success, or an error code */ -GIT_EXTERN(int) git_mailmap_add_buffer(git_mailmap *mm, const git_buf *buf); +GIT_EXTERN(int) git_mailmap_add_buffer( + git_mailmap *mm, const char *buf, size_t len); /** * 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); * * @param out pointer to store the new mailmap * @param buf buffer to parse the mailmap from + * @param len the length of the input buffer [optional: 0 defaults to 'strlen'] * @return 0 on success, or an error code */ -GIT_EXTERN(int) git_mailmap_from_buffer(git_mailmap **out, const git_buf *buf); +GIT_EXTERN(int) git_mailmap_from_buffer( + git_mailmap **out, const char *buf, size_t len); /** * Create a new mailmap instance from a repository, loading mailmap files based @@ -109,6 +113,19 @@ GIT_EXTERN(int) git_mailmap_resolve( const char **real_name, const char **real_email, const git_mailmap *mm, const char *name, const char *email); +/** + * Resolve a signature to use real names and emails with a mailmap. + * + * Call `git_signature_free()` to free the data. + * + * @param out new signature + * @param mm mailmap to resolve with + * @param sig signature to resolve + * @return 0 or an error code + */ +GIT_EXTERN(int) git_mailmap_resolve_signature( + git_signature **out, const git_mailmap *mm, const git_signature *sig); + /** @} */ GIT_END_DECL #endif diff --git a/include/git2/signature.h b/include/git2/signature.h index 981a4f1c3..7a2a0238a 100644 --- a/include/git2/signature.h +++ b/include/git2/signature.h @@ -75,18 +75,6 @@ GIT_EXTERN(int) git_signature_default(git_signature **out, git_repository *repo) */ GIT_EXTERN(int) git_signature_from_buffer(git_signature **out, const char *buf); -/** - * Create a signature with names updated respecting the mailmap. - * - * Call `git_signature_free()` to free the data. - * - * @param out new signature - * @param sig signature to resolve - * @param mailmap mailmap to resolve with - * @return 0 or an error code - */ -GIT_EXTERN(int) git_signature_with_mailmap(git_signature **out, const git_signature *sig, const git_mailmap *mailmap); - /** * Create a copy of an existing signature. All internal strings are also * duplicated. diff --git a/include/git2/types.h b/include/git2/types.h index 943a7e987..607a62a5a 100644 --- a/include/git2/types.h +++ b/include/git2/types.h @@ -434,7 +434,7 @@ struct git_writestream { void (*free)(git_writestream *stream); }; -/** A parsed representation of a .mailmap file. */ +/** Representation of .mailmap file state. */ typedef struct git_mailmap git_mailmap; /** @} */ diff --git a/src/commit.c b/src/commit.c index 03ecea8e8..e0ba51d47 100644 --- a/src/commit.c +++ b/src/commit.c @@ -11,6 +11,7 @@ #include "git2/object.h" #include "git2/repository.h" #include "git2/signature.h" +#include "git2/mailmap.h" #include "git2/sys/commit.h" #include "odb.h" @@ -893,11 +894,11 @@ cleanup: int git_commit_committer_with_mailmap( git_signature **out, const git_commit *commit, const git_mailmap *mailmap) { - return git_signature_with_mailmap(out, commit->committer, mailmap); + return git_mailmap_resolve_signature(out, mailmap, commit->committer); } int git_commit_author_with_mailmap( git_signature **out, const git_commit *commit, const git_mailmap *mailmap) { - return git_signature_with_mailmap(out, commit->author, mailmap); + return git_mailmap_resolve_signature(out, mailmap, commit->author); } diff --git a/src/mailmap.c b/src/mailmap.c index 3da46a83c..bfee4890a 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -10,6 +10,7 @@ #include "common.h" #include "path.h" #include "repository.h" +#include "signature.h" #include "git2/config.h" #include "git2/revparse.h" #include "blob.h" @@ -171,9 +172,12 @@ void git_mailmap_free(git_mailmap *mm) git__free(mm); } -int git_mailmap_add_entry( - git_mailmap *mm, const char *real_name, const char *real_email, - const char *replace_name, const char *replace_email) +static int mailmap_add_entry_unterminated( + git_mailmap *mm, + const char *real_name, size_t real_name_size, + const char *real_email, size_t real_email_size, + const char *replace_name, size_t replace_name_size, + const char *replace_email, size_t replace_email_size) { int error; git_mailmap_entry *entry = git__calloc(1, sizeof(git_mailmap_entry)); @@ -181,19 +185,19 @@ int git_mailmap_add_entry( assert(mm && replace_email && *replace_email); - if (real_name && *real_name) { - entry->real_name = git__strdup(real_name); + if (real_name_size > 0) { + entry->real_name = git__substrdup(real_name, real_name_size); GITERR_CHECK_ALLOC(entry->real_name); } - if (real_email && *real_email) { - entry->real_email = git__strdup(real_email); + if (real_email_size > 0) { + entry->real_email = git__substrdup(real_email, real_email_size); GITERR_CHECK_ALLOC(entry->real_email); } - if (replace_name && *replace_name) { - entry->replace_name = git__strdup(replace_name); + if (replace_name_size > 0) { + entry->replace_name = git__substrdup(replace_name, replace_name_size); GITERR_CHECK_ALLOC(entry->replace_name); } - entry->replace_email = git__strdup(replace_email); + entry->replace_email = git__substrdup(replace_email, replace_email_size); GITERR_CHECK_ALLOC(entry->replace_email); error = git_vector_insert_sorted(&mm->entries, entry, mailmap_entry_replace); @@ -203,10 +207,21 @@ int git_mailmap_add_entry( return error; } -int git_mailmap_add_buffer(git_mailmap *mm, const git_buf *buf) +int git_mailmap_add_entry( + git_mailmap *mm, const char *real_name, const char *real_email, + const char *replace_name, const char *replace_email) +{ + return mailmap_add_entry_unterminated( + mm, + real_name, real_name ? strlen(real_name) : 0, + real_email, real_email ? strlen(real_email) : 0, + replace_name, replace_name ? strlen(replace_name) : 0, + replace_email, strlen(replace_email)); +} + +int git_mailmap_add_buffer(git_mailmap *mm, const char *buf, size_t len) { int error; - git_mailmap_entry *entry = NULL; git_parse_ctx ctx; /* Scratch buffers containing the real parsed names & emails */ @@ -215,10 +230,15 @@ int git_mailmap_add_buffer(git_mailmap *mm, const git_buf *buf) git_buf replace_name = GIT_BUF_INIT; git_buf replace_email = GIT_BUF_INIT; - if (git_buf_contains_nul(buf)) + /* If `len` is passed as 0, use strlen to get the real length */ + if (buf && len == 0) + len = strlen(buf); + + /* Buffers may not contain '\0's. */ + if (memchr(buf, '\0', len) != NULL) return -1; - git_parse_ctx_init(&ctx, buf->ptr, buf->size); + git_parse_ctx_init(&ctx, buf, len); /* Run the parser */ while (ctx.remain_len > 0) { @@ -230,37 +250,17 @@ int git_mailmap_add_buffer(git_mailmap *mm, const git_buf *buf) continue; /* TODO: warn */ } - entry = git__calloc(1, sizeof(git_mailmap_entry)); - GITERR_CHECK_ALLOC(entry); - - if (real_name.size > 0) { - entry->real_name = git__substrdup(real_name.ptr, real_name.size); - GITERR_CHECK_ALLOC(entry->real_name); - } - if (real_email.size > 0) { - entry->real_email = git__substrdup(real_email.ptr, real_email.size); - GITERR_CHECK_ALLOC(entry->real_email); - } - if (replace_name.size > 0) { - entry->replace_name = git__substrdup(replace_name.ptr, replace_name.size); - GITERR_CHECK_ALLOC(entry->replace_name); - } - entry->replace_email = git__substrdup(replace_email.ptr, replace_email.size); - GITERR_CHECK_ALLOC(entry->replace_email); - - error = git_vector_insert_sorted( - &mm->entries, entry, mailmap_entry_replace); + /* NOTE: Can't use add_entry(...) as our buffers aren't terminated */ + error = mailmap_add_entry_unterminated( + mm, real_name.ptr, real_name.size, real_email.ptr, real_email.size, + replace_name.ptr, replace_name.size, replace_email.ptr, replace_email.size); if (error < 0 && error != GIT_EEXISTS) goto cleanup; - entry = NULL; error = 0; } cleanup: - mailmap_entry_free(entry); - - /* We never allocate data in these buffers, but better safe than sorry */ git_buf_free(&real_name); git_buf_free(&real_email); git_buf_free(&replace_name); @@ -268,13 +268,13 @@ cleanup: return error; } -int git_mailmap_from_buffer(git_mailmap **out, const git_buf *buffer) +int git_mailmap_from_buffer(git_mailmap **out, const char *data, size_t len) { int error = git_mailmap_new(out); if (error < 0) return error; - error = git_mailmap_add_buffer(*out, buffer); + error = git_mailmap_add_buffer(*out, data, len); if (error < 0) { git_mailmap_free(*out); *out = NULL; @@ -283,7 +283,7 @@ int git_mailmap_from_buffer(git_mailmap **out, const git_buf *buffer) } static int mailmap_add_blob( - git_mailmap *mm, git_repository *repo, const char *spec) + git_mailmap *mm, git_repository *repo, const char *rev) { git_object *object = NULL; git_blob *blob = NULL; @@ -292,7 +292,7 @@ static int mailmap_add_blob( assert(mm && repo); - error = git_revparse_single(&object, repo, spec); + error = git_revparse_single(&object, repo, rev); if (error < 0) goto cleanup; @@ -304,7 +304,7 @@ static int mailmap_add_blob( if (error < 0) goto cleanup; - error = git_mailmap_add_buffer(mm, &content); + error = git_mailmap_add_buffer(mm, content.ptr, content.size); if (error < 0) goto cleanup; @@ -331,7 +331,7 @@ static int mailmap_add_file_ondisk( if (error < 0) goto cleanup; - error = git_mailmap_add_buffer(mm, &content); + error = git_mailmap_add_buffer(mm, content.ptr, content.size); if (error < 0) goto cleanup; @@ -345,21 +345,21 @@ cleanup: static void mailmap_add_from_repository(git_mailmap *mm, git_repository *repo) { git_config *config = NULL; - git_buf spec_buf = GIT_BUF_INIT; + git_buf rev_buf = GIT_BUF_INIT; git_buf path_buf = GIT_BUF_INIT; - const char *spec = NULL; + const char *rev = NULL; const char *path = NULL; assert(mm && repo); /* If we're in a bare repo, default blob to 'HEAD:.mailmap' */ if (repo->is_bare) - spec = MM_BLOB_DEFAULT; + rev = MM_BLOB_DEFAULT; /* Try to load 'mailmap.file' and 'mailmap.blob' cfgs from the repo */ if (git_repository_config(&config, repo) == 0) { - if (git_config_get_string_buf(&spec_buf, config, MM_BLOB_CONFIG) == 0) - spec = spec_buf.ptr; + if (git_config_get_string_buf(&rev_buf, config, MM_BLOB_CONFIG) == 0) + rev = rev_buf.ptr; if (git_config_get_path(&path_buf, config, MM_FILE_CONFIG) == 0) path = path_buf.ptr; } @@ -377,12 +377,12 @@ static void mailmap_add_from_repository(git_mailmap *mm, git_repository *repo) */ if (!repo->is_bare) mailmap_add_file_ondisk(mm, MM_FILE, repo); - if (spec != NULL) - mailmap_add_blob(mm, repo, spec); + if (rev != NULL) + mailmap_add_blob(mm, repo, rev); if (path != NULL) mailmap_add_file_ondisk(mm, path, repo); - git_buf_free(&spec_buf); + git_buf_free(&rev_buf); git_buf_free(&path_buf); git_config_free(config); } @@ -403,7 +403,10 @@ const git_mailmap_entry *git_mailmap_entry_lookup( ssize_t fallback = -1; size_t idx; git_mailmap_entry *entry; - git_mailmap_entry needle = { NULL, NULL, NULL, (char *)email }; + + /* The lookup needle we want to use only sets the replace_email. */ + git_mailmap_entry needle = { NULL }; + needle.replace_email = (char *)email; assert(email); @@ -457,3 +460,26 @@ int git_mailmap_resolve( } return 0; } + +int git_mailmap_resolve_signature( + git_signature **out, const git_mailmap *mailmap, const git_signature *sig) +{ + const char *name = NULL; + const char *email = NULL; + int error; + + if (!sig) + return 0; + + error = git_mailmap_resolve(&name, &email, mailmap, sig->name, sig->email); + if (error < 0) + return error; + + error = git_signature_new(out, name, email, sig->when.time, sig->when.offset); + if (error < 0) + return error; + + /* Copy over the sign, as git_signature_new doesn't let you pass it. */ + (*out)->when.sign = sig->when.sign; + return 0; +} diff --git a/src/signature.c b/src/signature.c index a8177e036..cd6852326 100644 --- a/src/signature.c +++ b/src/signature.c @@ -9,7 +9,6 @@ #include "repository.h" #include "git2/common.h" -#include "git2/mailmap.h" #include "posix.h" void git_signature_free(git_signature *sig) @@ -99,35 +98,18 @@ int git_signature_new(git_signature **sig_out, const char *name, const char *ema int git_signature_dup(git_signature **dest, const git_signature *source) { - /* If mailmap is NULL, this method just copies the signature */ - return git_signature_with_mailmap(dest, source, NULL); -} - -int git_signature_with_mailmap( - git_signature **dest, - const git_signature *source, - const git_mailmap *mailmap) -{ - git_signature *signature = NULL; - const char *name = NULL; - const char *email = NULL; - int error; + git_signature *signature; if (source == NULL) return 0; - error = git_mailmap_resolve( - &name, &email, mailmap, source->name, source->email); - if (error < 0) - return error; - signature = git__calloc(1, sizeof(git_signature)); GITERR_CHECK_ALLOC(signature); - signature->name = git__strdup(name); + signature->name = git__strdup(source->name); GITERR_CHECK_ALLOC(signature->name); - signature->email = git__strdup(email); + signature->email = git__strdup(source->email); GITERR_CHECK_ALLOC(signature->email); signature->when.time = source->when.time; diff --git a/tests/mailmap/basic.c b/tests/mailmap/basic.c index b8a91327e..20fa8be7b 100644 --- a/tests/mailmap/basic.c +++ b/tests/mailmap/basic.c @@ -27,10 +27,7 @@ struct { void test_mailmap_basic__initialize(void) { - git_buf buf = GIT_BUF_INIT; - git_buf_attach_notowned(&buf, TEST_MAILMAP, strlen(TEST_MAILMAP)); - - cl_git_pass(git_mailmap_from_buffer(&mailmap, &buf)); + cl_git_pass(git_mailmap_from_buffer(&mailmap, TEST_MAILMAP, 0)); } void test_mailmap_basic__cleanup(void) diff --git a/tests/mailmap/blame.c b/tests/mailmap/blame.c index 328f4bce1..e6bc1a41f 100644 --- a/tests/mailmap/blame.c +++ b/tests/mailmap/blame.c @@ -2,7 +2,7 @@ #include "git2/repository.h" #include "git2/blame.h" #include "mailmap.h" -#include "mailmap_helpers.h" +#include "mailmap_testdata.h" static git_repository *g_repo; static git_blame *g_blame; @@ -30,8 +30,7 @@ void test_mailmap_blame__hunks(void) opts.flags |= GIT_BLAME_USE_MAILMAP; cl_git_pass(git_blame_file(&g_blame, g_repo, "file.txt", &opts)); - if (!g_blame) - return; + cl_assert(g_blame); for (idx = 0; idx < ARRAY_SIZE(resolved); ++idx) { hunk = git_blame_get_hunk_byline(g_blame, idx + 1); @@ -52,8 +51,7 @@ void test_mailmap_blame__hunks_no_mailmap(void) g_repo = cl_git_sandbox_init("mailmap"); cl_git_pass(git_blame_file(&g_blame, g_repo, "file.txt", &opts)); - if (!g_blame) - return; + cl_assert(g_blame); for (idx = 0; idx < ARRAY_SIZE(resolved); ++idx) { hunk = git_blame_get_hunk_byline(g_blame, idx + 1); diff --git a/tests/mailmap/mailmap_helpers.h b/tests/mailmap/mailmap_helpers.h deleted file mode 100644 index 173536dd0..000000000 --- a/tests/mailmap/mailmap_helpers.h +++ /dev/null @@ -1,44 +0,0 @@ -#include "mailmap.h" - -typedef struct mailmap_entry { - const char *real_name; - const char *real_email; - const char *replace_name; - const char *replace_email; -} mailmap_entry; - -static const char string_mailmap[] = - "# Simple Comment line\n" - " \n" - "Some Dude nick1 \n" - "Other Author nick2 \n" - "Other Author \n" - "Phil Hill # Comment at end of line\n" - " Joseph \n" - "Santa Claus \n" - "Untracked "; - -static const mailmap_entry entries[] = { - { NULL, "cto@company.xx", NULL, "cto@coompany.xx" }, - { "Some Dude", "some@dude.xx", "nick1", "bugs@company.xx" }, - { "Other Author", "other@author.xx", "nick2", "bugs@company.xx" }, - { "Other Author", "other@author.xx", NULL, "nick2@company.xx" }, - { "Phil Hill", NULL, NULL, "phil@company.xx" }, - { NULL, "joseph@company.xx", "Joseph", "bugs@company.xx" }, - { "Santa Claus", "santa.claus@northpole.xx", NULL, "me@company.xx" }, - /* This entry isn't in the bare repository */ - { "Untracked", NULL, NULL, "untracked@company.xx" } -}; - -static const mailmap_entry resolved[] = { - { "Brad", "cto@company.xx", "Brad", "cto@coompany.xx" }, - { "Brad L", "cto@company.xx", "Brad L", "cto@coompany.xx" }, - { "Some Dude", "some@dude.xx", "nick1", "bugs@company.xx" }, - { "Other Author", "other@author.xx", "nick2", "bugs@company.xx" }, - { "nick3", "bugs@company.xx", "nick3", "bugs@company.xx" }, - { "Other Author", "other@author.xx", "Some Garbage", "nick2@company.xx" }, - { "Phil Hill", "phil@company.xx", "unknown", "phil@company.xx" }, - { "Joseph", "joseph@company.xx", "Joseph", "bugs@company.xx" }, - { "Santa Claus", "santa.claus@northpole.xx", "Clause", "me@company.xx" }, - { "Charles", "charles@charles.xx", "Charles", "charles@charles.xx" } -}; diff --git a/tests/mailmap/mailmap_testdata.h b/tests/mailmap/mailmap_testdata.h new file mode 100644 index 000000000..173536dd0 --- /dev/null +++ b/tests/mailmap/mailmap_testdata.h @@ -0,0 +1,44 @@ +#include "mailmap.h" + +typedef struct mailmap_entry { + const char *real_name; + const char *real_email; + const char *replace_name; + const char *replace_email; +} mailmap_entry; + +static const char string_mailmap[] = + "# Simple Comment line\n" + " \n" + "Some Dude nick1 \n" + "Other Author nick2 \n" + "Other Author \n" + "Phil Hill # Comment at end of line\n" + " Joseph \n" + "Santa Claus \n" + "Untracked "; + +static const mailmap_entry entries[] = { + { NULL, "cto@company.xx", NULL, "cto@coompany.xx" }, + { "Some Dude", "some@dude.xx", "nick1", "bugs@company.xx" }, + { "Other Author", "other@author.xx", "nick2", "bugs@company.xx" }, + { "Other Author", "other@author.xx", NULL, "nick2@company.xx" }, + { "Phil Hill", NULL, NULL, "phil@company.xx" }, + { NULL, "joseph@company.xx", "Joseph", "bugs@company.xx" }, + { "Santa Claus", "santa.claus@northpole.xx", NULL, "me@company.xx" }, + /* This entry isn't in the bare repository */ + { "Untracked", NULL, NULL, "untracked@company.xx" } +}; + +static const mailmap_entry resolved[] = { + { "Brad", "cto@company.xx", "Brad", "cto@coompany.xx" }, + { "Brad L", "cto@company.xx", "Brad L", "cto@coompany.xx" }, + { "Some Dude", "some@dude.xx", "nick1", "bugs@company.xx" }, + { "Other Author", "other@author.xx", "nick2", "bugs@company.xx" }, + { "nick3", "bugs@company.xx", "nick3", "bugs@company.xx" }, + { "Other Author", "other@author.xx", "Some Garbage", "nick2@company.xx" }, + { "Phil Hill", "phil@company.xx", "unknown", "phil@company.xx" }, + { "Joseph", "joseph@company.xx", "Joseph", "bugs@company.xx" }, + { "Santa Claus", "santa.claus@northpole.xx", "Clause", "me@company.xx" }, + { "Charles", "charles@charles.xx", "Charles", "charles@charles.xx" } +}; diff --git a/tests/mailmap/parsing.c b/tests/mailmap/parsing.c index 70110c033..2cb830450 100644 --- a/tests/mailmap/parsing.c +++ b/tests/mailmap/parsing.c @@ -1,7 +1,7 @@ #include "clar_libgit2.h" #include "repository.h" #include "git2/sys/repository.h" -#include "mailmap_helpers.h" +#include "mailmap_testdata.h" #include "buf_text.h" static git_repository *g_repo; @@ -67,9 +67,7 @@ static const mailmap_entry resolved_untracked[] = { void test_mailmap_parsing__string(void) { - git_buf buf = GIT_BUF_INIT; - git_buf_attach_notowned(&buf, string_mailmap, strlen(string_mailmap)); - cl_git_pass(git_mailmap_from_buffer(&g_mailmap, &buf)); + cl_git_pass(git_mailmap_from_buffer(&g_mailmap, string_mailmap, 0)); /* We should have parsed all of the entries */ check_mailmap_entries(g_mailmap, entries, ARRAY_SIZE(entries)); @@ -89,7 +87,7 @@ void test_mailmap_parsing__windows_string(void) git_buf_attach_notowned(&unixbuf, string_mailmap, strlen(string_mailmap)); git_buf_text_lf_to_crlf(&winbuf, &unixbuf); - cl_git_pass(git_mailmap_from_buffer(&g_mailmap, &winbuf)); + cl_git_pass(git_mailmap_from_buffer(&g_mailmap, winbuf.ptr, winbuf.size)); git_buf_free(&winbuf); /* We should have parsed all of the entries */ -- cgit v1.2.1 From c1a85ae2ab609ac9d5e9a18c4f644108c8462a43 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Mon, 4 Jun 2018 11:36:44 -0400 Subject: mailmap: Free the mailmap vector --- src/mailmap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mailmap.c b/src/mailmap.c index bfee4890a..e4b924c05 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -169,6 +169,8 @@ void git_mailmap_free(git_mailmap *mm) git_vector_foreach(&mm->entries, idx, entry) mailmap_entry_free(entry); + + git_vector_free(&mm->entries); git__free(mm); } -- cgit v1.2.1 From d91d2968a662ee2b2120c3b44aa6956d9ac57b89 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Jun 2018 16:49:48 -0700 Subject: mailmap: Hide EEXISTS to simplify git_mailmap_add_entry callers --- include/git2/mailmap.h | 2 +- src/mailmap.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/git2/mailmap.h b/include/git2/mailmap.h index b22a00c67..c6ed4811f 100644 --- a/include/git2/mailmap.h +++ b/include/git2/mailmap.h @@ -47,7 +47,7 @@ GIT_EXTERN(void) git_mailmap_free(git_mailmap *mm); * @param real_email the real email to use, or NULL * @param replace_name the name to replace, or NULL * @param replace_email the email to replace - * @return 0 if it was added, EEXISTS if it replaced an entry, or an error code + * @return 0 on success, or an error code */ GIT_EXTERN(int) git_mailmap_add_entry( git_mailmap *mm, const char *real_name, const char *real_email, diff --git a/src/mailmap.c b/src/mailmap.c index e4b924c05..f249c5261 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -203,7 +203,9 @@ static int mailmap_add_entry_unterminated( GITERR_CHECK_ALLOC(entry->replace_email); error = git_vector_insert_sorted(&mm->entries, entry, mailmap_entry_replace); - if (error < 0 && error != GIT_EEXISTS) + if (error == GIT_EEXISTS) + error = GIT_OK; + else if (error < 0) mailmap_entry_free(entry); return error; @@ -256,7 +258,7 @@ int git_mailmap_add_buffer(git_mailmap *mm, const char *buf, size_t len) error = mailmap_add_entry_unterminated( mm, real_name.ptr, real_name.size, real_email.ptr, real_email.size, replace_name.ptr, replace_name.size, replace_email.ptr, replace_email.size); - if (error < 0 && error != GIT_EEXISTS) + if (error < 0) goto cleanup; error = 0; -- cgit v1.2.1 From 9faf36a6e89d1cc161bb6bf3afff7a3552b8a349 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Thu, 14 Jun 2018 22:48:58 -0700 Subject: mailmap: git_buf_free => git_buf_dispose --- src/mailmap.c | 18 +++++++++--------- tests/mailmap/parsing.c | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/mailmap.c b/src/mailmap.c index f249c5261..b5fb7f69c 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -265,10 +265,10 @@ int git_mailmap_add_buffer(git_mailmap *mm, const char *buf, size_t len) } cleanup: - git_buf_free(&real_name); - git_buf_free(&real_email); - git_buf_free(&replace_name); - git_buf_free(&replace_email); + git_buf_dispose(&real_name); + git_buf_dispose(&real_email); + git_buf_dispose(&replace_name); + git_buf_dispose(&replace_email); return error; } @@ -313,7 +313,7 @@ static int mailmap_add_blob( goto cleanup; cleanup: - git_buf_free(&content); + git_buf_dispose(&content); git_blob_free(blob); git_object_free(object); return error; @@ -340,8 +340,8 @@ static int mailmap_add_file_ondisk( goto cleanup; cleanup: - git_buf_free(&fullpath); - git_buf_free(&content); + git_buf_dispose(&fullpath); + git_buf_dispose(&content); return error; } @@ -386,8 +386,8 @@ static void mailmap_add_from_repository(git_mailmap *mm, git_repository *repo) if (path != NULL) mailmap_add_file_ondisk(mm, path, repo); - git_buf_free(&rev_buf); - git_buf_free(&path_buf); + git_buf_dispose(&rev_buf); + git_buf_dispose(&path_buf); git_config_free(config); } diff --git a/tests/mailmap/parsing.c b/tests/mailmap/parsing.c index 2cb830450..d3efe400e 100644 --- a/tests/mailmap/parsing.c +++ b/tests/mailmap/parsing.c @@ -88,7 +88,7 @@ void test_mailmap_parsing__windows_string(void) git_buf_text_lf_to_crlf(&winbuf, &unixbuf); cl_git_pass(git_mailmap_from_buffer(&g_mailmap, winbuf.ptr, winbuf.size)); - git_buf_free(&winbuf); + git_buf_dispose(&winbuf); /* We should have parsed all of the entries */ check_mailmap_entries(g_mailmap, entries, ARRAY_SIZE(entries)); -- cgit v1.2.1 From f98131be911df5e4c47e51ac92e6e7de79e30219 Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sun, 17 Jun 2018 00:40:25 -0400 Subject: Require the length argument to git_mailmap_from_buffer and make mailmap_add_buffer internal --- include/git2/mailmap.h | 18 +----------------- src/mailmap.c | 12 ++++-------- tests/mailmap/basic.c | 3 ++- tests/mailmap/parsing.c | 3 ++- 4 files changed, 9 insertions(+), 27 deletions(-) diff --git a/include/git2/mailmap.h b/include/git2/mailmap.h index c6ed4811f..7c3f60fcc 100644 --- a/include/git2/mailmap.h +++ b/include/git2/mailmap.h @@ -53,28 +53,12 @@ GIT_EXTERN(int) git_mailmap_add_entry( git_mailmap *mm, const char *real_name, const char *real_email, const char *replace_name, const char *replace_email); -/** - * Parse mailmap entries from a buffer. - * - * @param mm mailmap to add the entries to - * @param buf the buffer to read the mailmap file from - * @param len the length of the input buffer [optional: 0 defaults to 'strlen'] - * @return 0 on success, or an error code - */ -GIT_EXTERN(int) git_mailmap_add_buffer( - git_mailmap *mm, const char *buf, size_t len); - /** * Create a new mailmap instance containing a single mailmap file * - * This method is a simple utility wrapper for the following sequence - * of calls: - * - git_mailmap_new - * - git_mailmap_add_buffer - * * @param out pointer to store the new mailmap * @param buf buffer to parse the mailmap from - * @param len the length of the input buffer [optional: 0 defaults to 'strlen'] + * @param len the length of the input buffer * @return 0 on success, or an error code */ GIT_EXTERN(int) git_mailmap_from_buffer( diff --git a/src/mailmap.c b/src/mailmap.c index b5fb7f69c..fe4d452d5 100644 --- a/src/mailmap.c +++ b/src/mailmap.c @@ -223,7 +223,7 @@ int git_mailmap_add_entry( replace_email, strlen(replace_email)); } -int git_mailmap_add_buffer(git_mailmap *mm, const char *buf, size_t len) +static int mailmap_add_buffer(git_mailmap *mm, const char *buf, size_t len) { int error; git_parse_ctx ctx; @@ -234,10 +234,6 @@ int git_mailmap_add_buffer(git_mailmap *mm, const char *buf, size_t len) git_buf replace_name = GIT_BUF_INIT; git_buf replace_email = GIT_BUF_INIT; - /* If `len` is passed as 0, use strlen to get the real length */ - if (buf && len == 0) - len = strlen(buf); - /* Buffers may not contain '\0's. */ if (memchr(buf, '\0', len) != NULL) return -1; @@ -278,7 +274,7 @@ int git_mailmap_from_buffer(git_mailmap **out, const char *data, size_t len) if (error < 0) return error; - error = git_mailmap_add_buffer(*out, data, len); + error = mailmap_add_buffer(*out, data, len); if (error < 0) { git_mailmap_free(*out); *out = NULL; @@ -308,7 +304,7 @@ static int mailmap_add_blob( if (error < 0) goto cleanup; - error = git_mailmap_add_buffer(mm, content.ptr, content.size); + error = mailmap_add_buffer(mm, content.ptr, content.size); if (error < 0) goto cleanup; @@ -335,7 +331,7 @@ static int mailmap_add_file_ondisk( if (error < 0) goto cleanup; - error = git_mailmap_add_buffer(mm, content.ptr, content.size); + error = mailmap_add_buffer(mm, content.ptr, content.size); if (error < 0) goto cleanup; diff --git a/tests/mailmap/basic.c b/tests/mailmap/basic.c index 20fa8be7b..1f8ca56c2 100644 --- a/tests/mailmap/basic.c +++ b/tests/mailmap/basic.c @@ -27,7 +27,8 @@ struct { void test_mailmap_basic__initialize(void) { - cl_git_pass(git_mailmap_from_buffer(&mailmap, TEST_MAILMAP, 0)); + cl_git_pass(git_mailmap_from_buffer( + &mailmap, TEST_MAILMAP, strlen(TEST_MAILMAP))); } void test_mailmap_basic__cleanup(void) diff --git a/tests/mailmap/parsing.c b/tests/mailmap/parsing.c index d3efe400e..4479e4131 100644 --- a/tests/mailmap/parsing.c +++ b/tests/mailmap/parsing.c @@ -67,7 +67,8 @@ static const mailmap_entry resolved_untracked[] = { void test_mailmap_parsing__string(void) { - cl_git_pass(git_mailmap_from_buffer(&g_mailmap, string_mailmap, 0)); + cl_git_pass(git_mailmap_from_buffer( + &g_mailmap, string_mailmap, strlen(string_mailmap))); /* We should have parsed all of the entries */ check_mailmap_entries(g_mailmap, entries, ARRAY_SIZE(entries)); -- cgit v1.2.1