Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
8ff0504d
Commit
8ff0504d
authored
Apr 08, 2018
by
Nika Layzell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mailmap: Rewrite API to support accurate mailmap resolution
parent
18ff9bab
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
343 additions
and
207 deletions
+343
-207
include/git2/mailmap.h
+60
-70
src/blame.c
+1
-1
src/mailmap.c
+245
-135
src/mailmap.h
+35
-0
src/signature.c
+2
-1
No files found.
include/git2/mailmap.h
View file @
8ff0504d
...
...
@@ -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
...
...
src/blame.c
View file @
8ff0504d
...
...
@@ -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_repo
sitory
(
&
gbr
->
mailmap
,
repo
);
return
gbr
;
}
...
...
src/mailmap.c
View file @
8ff0504d
...
...
@@ -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
;
}
/* NOTE: Only expose with an error return, currently never errors */
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
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
;
}
/*
* 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
);
}
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_from_repo
(
git_mailmap
**
mailmap
,
git_repository
*
repo
)
int
git_mailmap_resolve
(
const
char
**
real_name
,
const
char
**
real_email
,
const
git_mailmap
*
mailmap
,
const
char
*
name
,
const
char
*
email
)
{
assert
(
mailmap
&&
repo
);
const
git_mailmap_entry
*
entry
=
NULL
;
assert
(
name
&&
email
);
*
mailmap
=
NULL
;
*
real_name
=
name
;
*
real_email
=
email
;
if
(
git_repository_is_bare
(
repo
))
return
mailmap_from_bare_repo
(
mailmap
,
repo
);
else
return
mailmap_from_workdir_repo
(
mailmap
,
repo
);
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
;
}
src/mailmap.h
0 → 100644
View file @
8ff0504d
/*
* 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
src/signature.c
View file @
8ff0504d
...
...
@@ -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
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment