diff options
author | Nika Layzell <nika@thelayzells.com> | 2018-03-17 18:15:01 -0400 |
---|---|---|
committer | Nika Layzell <nika@thelayzells.com> | 2018-06-14 22:43:27 -0700 |
commit | e3dcaca579ba344ccdacfe4835dcc7bf52c5ba57 (patch) | |
tree | 6a11cd2d34e6df58e7ac36c03c78c86e35cab64b | |
parent | b05fbba394b9f2befea8b50817fd64209538e384 (diff) | |
download | libgit2-e3dcaca579ba344ccdacfe4835dcc7bf52c5ba57.tar.gz |
mailmap: Integrate mailmaps with blame and signatures
-rw-r--r-- | include/git2/blame.h | 10 | ||||
-rw-r--r-- | include/git2/commit.h | 28 | ||||
-rw-r--r-- | include/git2/signature.h | 13 | ||||
-rw-r--r-- | include/git2/types.h | 3 | ||||
-rw-r--r-- | src/blame.c | 14 | ||||
-rw-r--r-- | src/blame.h | 2 | ||||
-rw-r--r-- | src/commit.c | 12 | ||||
-rw-r--r-- | 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 @@ -173,6 +173,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. * * @param commit a previously loaded commit 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 @@ -76,6 +76,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; |