1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2018 - TortoiseGit
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 // gitdll.cpp : Defines the exported functions for the DLL application.
23 #include "../build/libgit-defines.h"
25 #pragma warning(disable: 4100 4018 4127 4244 4267)
26 #include "git-compat-util.h"
39 #include "run-command.h"
43 extern char g_last_error
[];
44 const char * g_prefix
;
46 static_assert(sizeof(struct object_id
) == sizeof(struct GIT_OBJECT_OID
), "Required to be equal in gitdll.h");
48 extern NORETURN
void die_dll(const char* err
, va_list params
);
49 extern void handle_error(const char* err
, va_list params
);
50 extern void handle_warning(const char* warn
, va_list params
);
51 extern int die_is_recursing_dll(void);
53 extern void libgit_initialize(void);
54 extern void free_all_pack(void);
55 extern void reset_git_env(void);
56 extern void drop_all_attr_stacks(void);
57 extern void git_atexit_dispatch(void);
58 extern void git_atexit_clear(void);
59 extern void invalidate_ref_cache(void);
60 extern void cmd_log_init(int argc
, const char** argv
, const char* prefix
, struct rev_info
* rev
, struct setup_revision_opt
* opt
);
61 extern int estimate_commit_count(struct rev_info
* rev
, struct commit_list
* list
);
62 extern int log_tree_commit(struct rev_info
*, struct commit
*);
63 extern int write_entry(struct cache_entry
* ce
, char* path
, const struct checkout
* state
, int to_tempfile
);
64 extern struct object
* deref_tag(struct object
* o
, const char* warn
, int warnlen
);
65 extern void diff_flush_stat(struct diff_filepair
* p
, struct diff_options
* o
, struct diffstat_t
* diffstat
);
66 extern void free_diffstat_info(struct diffstat_t
* diffstat
);
67 static_assert(sizeof(unsigned long long) == sizeof(timestamp_t
), "Required for each_reflog_ent_fn definition in gitdll.h");
68 extern int for_each_reflog_ent(const char* refname
, each_reflog_ent_fn fn
, void* cb_data
);
69 extern int for_each_ref_in(const char* prefix
, each_ref_fn fn
, void* cb_data
);
73 set_die_routine(die_dll
);
74 set_error_routine(handle_error
);
75 set_warn_routine(handle_warning
);
76 set_die_is_recursing_routine(die_is_recursing_dll
);
80 int git_get_sha1(const char *name
, GIT_HASH sha1
)
82 struct object_id oid
= { 0 };
83 int ret
= get_oid(name
, &oid
);
84 hashcpy(sha1
, oid
.hash
);
88 static int convert_slash(char * path
)
101 char path
[MAX_PATH
+1];
104 _setmode(_fileno(stdin
), _O_BINARY
);
105 _setmode(_fileno(stdout
), _O_BINARY
);
106 _setmode(_fileno(stderr
), _O_BINARY
);
108 GetModuleFileName(NULL
, path
, MAX_PATH
);
111 git_extract_argv0_path(path
);
113 // set HOME if not set already
114 gitsetenv("HOME", get_windows_home_directory(), 0);
115 drop_all_attr_stacks();
117 g_prefix
= setup_git_directory();
118 git_config(git_default_config
, NULL
);
119 invalidate_ref_cache();
124 static int git_parse_commit_author(struct GIT_COMMIT_AUTHOR
* author
, const char* pbuff
)
129 end
=strchr(pbuff
,'<');
134 author
->NameSize
= (int)(end
- pbuff
- 1);
137 end
= strchr(pbuff
, '>');
141 author
->Email
= pbuff
;
142 author
->EmailSize
= (int)(end
- pbuff
);
146 author
->Date
= atol(pbuff
);
147 end
= strchr(pbuff
, ' ');
152 author
->TimeZone
= atol(pbuff
);
157 int git_parse_commit(GIT_COMMIT
*commit
)
164 p
= (struct commit
*)commit
->m_pGitCommit
;
166 memcpy(commit
->m_hash
, p
->object
.oid
.hash
, GIT_HASH_SIZE
);
168 commit
->m_Encode
= NULL
;
169 commit
->m_EncodeSize
= 0;
171 commit
->buffer
= detach_commit_buffer(commit
->m_pGitCommit
, NULL
);
173 pbuf
= commit
->buffer
;
176 if (strncmp(pbuf
, "author", 6) == 0)
178 ret
= git_parse_commit_author(&commit
->m_Author
,pbuf
+ 7);
182 else if (strncmp(pbuf
, "committer", 9) == 0)
184 ret
= git_parse_commit_author(&commit
->m_Committer
,pbuf
+ 10);
188 pbuf
= strchr(pbuf
,'\n');
192 else if (strncmp(pbuf
, "encoding", 8) == 0)
195 commit
->m_Encode
=pbuf
;
196 end
= strchr(pbuf
,'\n');
197 commit
->m_EncodeSize
= (int)(end
-pbuf
);
200 // the headers end after the first empty line
201 else if (*pbuf
== '\n')
205 commit
->m_Subject
=pbuf
;
206 end
= strchr(pbuf
,'\n');
208 commit
->m_SubjectSize
= (int)strlen(pbuf
);
211 commit
->m_SubjectSize
= (int)(end
- pbuf
);
213 commit
->m_Body
= pbuf
;
214 commit
->m_BodySize
= (int)strlen(pbuf
);
219 pbuf
= strchr(pbuf
,'\n');
226 int git_get_commit_from_hash(GIT_COMMIT
* commit
, const GIT_HASH hash
)
231 struct object_id oid
;
236 memset(commit
,0,sizeof(GIT_COMMIT
));
238 hashcpy(oid
.hash
, hash
);
240 commit
->m_pGitCommit
= p
= lookup_commit(&oid
);
245 ret
= parse_commit(p
);
249 return git_parse_commit(commit
);
252 int git_get_commit_first_parent(GIT_COMMIT
*commit
,GIT_COMMIT_LIST
*list
)
254 struct commit
*p
= commit
->m_pGitCommit
;
259 *list
= (GIT_COMMIT_LIST
*)p
->parents
;
263 int git_commit_is_root(const GIT_COMMIT
* commit
)
265 struct commit
* p
= commit
->m_pGitCommit
;
266 return (struct commit_list
**)p
->parents
? 1 : 0;
269 int git_get_commit_next_parent(GIT_COMMIT_LIST
*list
, GIT_HASH hash
)
271 struct commit_list
*l
;
275 l
= *(struct commit_list
**)list
;
280 memcpy(hash
, l
->item
->object
.oid
.hash
, GIT_HASH_SIZE
);
282 *list
= (GIT_COMMIT_LIST
*)l
->next
;
288 int git_free_commit(GIT_COMMIT
*commit
)
290 struct commit
*p
= commit
->m_pGitCommit
;
293 free_commit_list(p
->parents
);
296 free_tree_buffer(p
->tree
);
298 #pragma warning(push)
299 #pragma warning(disable: 4090)
301 free(commit
->buffer
);
304 p
->object
.parsed
= 0;
308 memset(commit
,0,sizeof(GIT_COMMIT
));
312 char **strtoargv(char *arg
, int *size
)
334 argv
=malloc(strlen(arg
)+1 + (count
+2)*sizeof(void*));
335 p
=(char*)(argv
+count
+2);
354 if((*arg
== space
) || (*arg
== 0))
370 int git_open_log(GIT_LOG
* handle
, char * arg
)
372 struct rev_info
*p_Rev
;
375 struct setup_revision_opt opt
;
378 unsigned int obj_size
= get_max_object_index();
379 for (unsigned int i
= 0; i
< obj_size
; ++i
)
381 struct object
*ob
= get_indexed_object(i
);
385 if (ob
->parsed
&& ob
->type
== OBJ_COMMIT
)
387 struct commit
* commit
= (struct commit
*)ob
;
388 free_commit_list(commit
->parents
);
389 commit
->parents
= NULL
;
391 free_tree_buffer(commit
->tree
);
399 argv
= strtoargv(arg
,&argc
);
404 p_Rev
= malloc(sizeof(struct rev_info
));
411 memset(p_Rev
,0,sizeof(struct rev_info
));
413 invalidate_ref_cache();
415 init_revisions(p_Rev
, g_prefix
);
418 memset(&opt
, 0, sizeof(opt
));
421 cmd_log_init(argc
, argv
, g_prefix
,p_Rev
,&opt
);
423 p_Rev
->pPrivate
= argv
;
428 int git_get_log_firstcommit(GIT_LOG handle
)
430 return prepare_revision_walk(handle
);
433 int git_get_log_estimate_commit_count(GIT_LOG handle
)
435 struct rev_info
*p_Rev
;
436 p_Rev
=(struct rev_info
*)handle
;
438 return estimate_commit_count(p_Rev
, p_Rev
->commits
);
441 int git_get_log_nextcommit(GIT_LOG handle
, GIT_COMMIT
*commit
, int follow
)
448 memset(commit
, 0, sizeof(GIT_COMMIT
));
450 commit
->m_pGitCommit
= get_revision(handle
);
451 if( commit
->m_pGitCommit
== NULL
)
454 if (follow
&& !log_tree_commit(handle
, commit
->m_pGitCommit
))
456 commit
->m_ignore
= 1;
459 commit
->m_ignore
= 0;
461 ret
=git_parse_commit(commit
);
468 struct notes_tree
**display_notes_trees
;
469 int git_close_log(GIT_LOG handle
)
473 struct rev_info
*p_Rev
;
474 p_Rev
=(struct rev_info
*)handle
;
476 free(p_Rev
->pPrivate
);
481 if (display_notes_trees
)
482 free_notes(*display_notes_trees
);
483 display_notes_trees
= 0;
487 int git_open_diff(GIT_DIFF
*diff
, char * arg
)
489 struct rev_info
*p_Rev
;
494 argv
= strtoargv(arg
,&argc
);
496 p_Rev
= malloc(sizeof(struct rev_info
));
497 memset(p_Rev
,0,sizeof(struct rev_info
));
499 p_Rev
->pPrivate
= argv
;
500 *diff
= (GIT_DIFF
)p_Rev
;
502 init_revisions(p_Rev
, g_prefix
);
503 git_config(git_diff_basic_config
, NULL
); /* no "diff" UI options */
506 argc
= setup_revisions(argc
, argv
, p_Rev
, NULL
);
510 int git_close_diff(GIT_DIFF handle
)
512 git_diff_flush(handle
);
515 struct rev_info
*p_Rev
;
516 p_Rev
=(struct rev_info
*)handle
;
518 free(p_Rev
->pPrivate
);
523 int git_diff_flush(GIT_DIFF diff
)
525 struct diff_queue_struct
*q
= &diff_queued_diff
;
526 struct rev_info
*p_Rev
;
527 p_Rev
= (struct rev_info
*)diff
;
532 for (int i
= 0; i
< q
->nr
; ++i
)
533 diff_free_filepair(q
->queue
[i
]);
539 q
->nr
= q
->alloc
= 0;
542 if (p_Rev
->diffopt
.close_file
)
543 fclose(p_Rev
->diffopt
.file
);
545 free_diffstat_info(&p_Rev
->diffstat
);
549 int git_root_diff(GIT_DIFF diff
, GIT_HASH hash
,GIT_FILE
*file
, int *count
, int isstat
)
552 struct object_id oid
;
553 struct rev_info
*p_Rev
;
554 struct diff_queue_struct
*q
= &diff_queued_diff
;
556 p_Rev
= (struct rev_info
*)diff
;
558 hashcpy(oid
.hash
, hash
);
560 ret
= diff_root_tree_oid(&oid
, "", &p_Rev
->diffopt
);
567 diffcore_std(&p_Rev
->diffopt
);
569 memset(&p_Rev
->diffstat
, 0, sizeof(struct diffstat_t
));
570 for (int i
= 0; i
< q
->nr
; ++i
) {
571 struct diff_filepair
*p
= q
->queue
[i
];
572 //if (check_pair_status(p))
573 diff_flush_stat(p
, &p_Rev
->diffopt
, &p_Rev
->diffstat
);
585 int git_do_diff(GIT_DIFF diff
, GIT_HASH hash1
, GIT_HASH hash2
, GIT_FILE
* file
, int *count
,int isstat
)
587 struct rev_info
*p_Rev
;
589 struct object_id oid1
, oid2
;
590 struct diff_queue_struct
*q
= &diff_queued_diff
;
592 p_Rev
= (struct rev_info
*)diff
;
594 hashcpy(oid1
.hash
, hash1
);
595 hashcpy(oid2
.hash
, hash2
);
597 ret
= diff_tree_oid(&oid1
, &oid2
, "", &p_Rev
->diffopt
);
606 diffcore_std(&p_Rev
->diffopt
);
607 memset(&p_Rev
->diffstat
, 0, sizeof(struct diffstat_t
));
608 for (int i
= 0; i
< q
->nr
; ++i
) {
609 struct diff_filepair
*p
= q
->queue
[i
];
610 //if (check_pair_status(p))
611 diff_flush_stat(p
, &p_Rev
->diffopt
, &p_Rev
->diffstat
);
622 int git_get_diff_file(GIT_DIFF diff
, GIT_FILE file
, int i
, char** newname
, char** oldname
, int* IsDir
, int* status
, int* IsBin
, int* inc
, int* dec
)
624 struct diff_queue_struct
*q
= &diff_queued_diff
;
625 struct rev_info
*p_Rev
;
626 p_Rev
= (struct rev_info
*)diff
;
628 q
= (struct diff_queue_struct
*)file
;
634 assert(newname
&& oldname
&& status
&& IsDir
);
636 *newname
= q
->queue
[i
]->two
->path
;
637 *oldname
= q
->queue
[i
]->one
->path
;
638 *status
= q
->queue
[i
]->status
;
640 *IsDir
= (q
->queue
[i
]->one
->mode
& S_IFDIR
) == S_IFDIR
;
642 *IsDir
= (q
->queue
[i
]->two
->mode
& S_IFDIR
) == S_IFDIR
;
644 if (q
->queue
[i
]->one
->mode
&& q
->queue
[i
]->two
->mode
&& DIFF_PAIR_TYPE_CHANGED(q
->queue
[i
]))
647 if(p_Rev
->diffstat
.files
)
650 for (j
= 0; j
< p_Rev
->diffstat
.nr
; ++j
)
652 if(strcmp(*newname
,p_Rev
->diffstat
.files
[j
]->name
)==0)
655 if( j
== p_Rev
->diffstat
.nr
)
663 *IsBin
= p_Rev
->diffstat
.files
[j
]->is_binary
;
665 *inc
= (int)p_Rev
->diffstat
.files
[j
]->added
;
667 *dec
= (int)p_Rev
->diffstat
.files
[j
]->deleted
;
678 int git_add_exclude(const char *string
, const char *base
,
679 int baselen
, EXCLUDE_LIST which
, int lineno
)
681 add_exclude(string
, base
, baselen
, which
, lineno
);
685 int git_create_exclude_list(EXCLUDE_LIST
*which
)
687 *which
= malloc(sizeof(struct exclude_list
));
688 memset(*which
,0,sizeof(struct exclude_list
));
692 int git_free_exclude_list(EXCLUDE_LIST which
)
694 struct exclude_list
*p
= (struct exclude_list
*) which
;
696 for (int i
= 0; i
< p
->nr
; ++i
)
698 free(p
->excludes
[i
]);
705 int git_check_excluded_1(const char *pathname
,
706 int pathlen
, const char *basename
, int *dtype
,
707 EXCLUDE_LIST el
, int ignorecase
)
709 ignore_case
= ignorecase
;
710 return is_excluded_from_list(pathname
, pathlen
, basename
, dtype
, el
, &the_index
);
713 int git_get_notes(const GIT_HASH hash
, char** p_note
)
715 struct object_id oid
;
719 hashcpy(oid
.hash
, hash
);
720 format_display_notes(&oid
, &sb
, "utf-8", 1);
721 *p_note
= strbuf_detach(&sb
,&size
);
728 int (*fn
)(int, const char **, const char *);
732 #define RUN_SETUP (1<<0)
734 static struct cmd_struct commands
[] = {
735 { "update-index", cmd_update_index
, RUN_SETUP
},
738 int git_run_cmd(char *cmd
, char *arg
)
746 for (int i
= 0; i
< sizeof(commands
) / sizeof(struct cmd_struct
); ++i
)
748 if(strcmp(cmd
,commands
[i
].cmd
)==0)
752 argv
= strtoargv(arg
,&argc
);
754 ret
= commands
[i
].fn(argc
, argv
, NULL
);
770 void git_exit_cleanup(void)
772 git_atexit_dispatch();
773 // do not clear the atexit list, as lots of methods register it just once (and have a local static int flag)
776 int git_for_each_reflog_ent(const char *ref
, each_reflog_ent_fn fn
, void *cb_data
)
778 return for_each_reflog_ent(ref
,fn
,cb_data
);
781 static int update_some(const unsigned char* sha1
, struct strbuf
* base
,
782 const char *pathname
, unsigned mode
, int stage
, void *context
)
784 struct cache_entry
*ce
;
785 UNREFERENCED_PARAMETER(stage
);
787 ce
= (struct cache_entry
*)context
;
790 return READ_TREE_RECURSIVE
;
792 hashcpy(ce
->oid
.hash
, sha1
);
793 memcpy(ce
->name
, base
->buf
, base
->len
);
794 memcpy(ce
->name
+ base
->len
, pathname
, strlen(pathname
));
795 ce
->ce_flags
= create_ce_flags((unsigned int)(strlen(pathname
) + base
->len
));
796 ce
->ce_mode
= create_ce_mode(mode
);
801 int git_checkout_file(const char* ref
, const char* path
, char* outputpath
)
803 struct cache_entry
*ce
;
805 struct object_id oid
;
807 struct checkout state
;
808 struct pathspec pathspec
;
809 const char *matchbuf
[1];
810 ret
= get_oid(ref
, &oid
);
814 reprepare_packed_git();
815 root
= parse_tree_indirect(&oid
);
823 ce
= xcalloc(1, cache_entry_size(strlen(path
)));
826 parse_pathspec(&pathspec
, PATHSPEC_ALL_MAGIC
, PATHSPEC_PREFER_CWD
, path
, matchbuf
);
827 pathspec
.items
[0].nowildcard_len
= pathspec
.items
[0].len
;
828 ret
= read_tree_recursive(root
, "", 0, 0, &pathspec
, update_some
, ce
);
829 clear_pathspec(&pathspec
);
837 memset(&state
, 0, sizeof(state
));
839 state
.refresh_cache
= 0;
841 ret
= write_entry(ce
, outputpath
, &state
, 0);
854 static int get_config(const char *key_
, const char *value_
, void *cb
)
856 struct config_buf
*buf
;
857 buf
=(struct config_buf
*)cb
;
858 if(strcmp(key_
, buf
->key
))
862 strncpy(buf
->buf
,value_
,buf
->size
);
876 // wchar_t wrapper for program_data_config()
877 const wchar_t* wget_program_data_config(void)
879 static const wchar_t *programdata_git_config
= NULL
;
880 wchar_t wpointer
[MAX_PATH
];
882 if (programdata_git_config
)
883 return programdata_git_config
;
885 if (xutftowcs_path(wpointer
, program_data_config()) < 0)
888 programdata_git_config
= _wcsdup(wpointer
);
890 return programdata_git_config
;
893 // wchar_t wrapper for git_etc_gitconfig()
894 const wchar_t *wget_msysgit_etc(void)
896 static const wchar_t *etc_gitconfig
= NULL
;
897 wchar_t wpointer
[MAX_PATH
];
900 return etc_gitconfig
;
902 if (xutftowcs_path(wpointer
, git_etc_gitconfig()) < 0)
905 etc_gitconfig
= _wcsdup(wpointer
);
907 return etc_gitconfig
;
910 int git_get_config(const char *key
, char *buffer
, int size
)
912 const char *home
, *system
, *programdata
;
913 struct config_buf buf
;
914 struct git_config_source config_source
= { 0 };
916 struct config_options opts
= { 0 };
917 opts
.respect_includes
= 1;
926 opts
.git_dir
= get_git_dir();
927 char* local
= git_pathdup("config");
928 config_source
.file
= local
;
929 config_with_options(get_config
, &buf
, &config_source
, &opts
);
935 home
= get_windows_home_directory();
938 char* global
= xstrdup(mkpath("%s/.gitconfig", home
));
941 config_source
.file
= global
;
942 config_with_options(get_config
, &buf
, &config_source
, &opts
);
947 char* globalxdg
= xstrdup(mkpath("%s/.config/git/config", home
));
950 config_source
.file
= globalxdg
;
951 config_with_options(get_config
, &buf
, &config_source
, &opts
);
958 system
= git_etc_gitconfig();
961 config_source
.file
= system
;
962 config_with_options(get_config
, &buf
, &config_source
, &opts
);
967 programdata
= git_program_data_config();
970 config_source
.file
= programdata
;
971 config_with_options(get_config
, &buf
, &config_source
, &opts
);
977 // taken from msysgit: compat/mingw.c
978 const char *get_windows_home_directory(void)
980 static const char *home_directory
= NULL
;
984 return home_directory
;
986 if ((tmp
= getenv("HOME")) != NULL
&& *tmp
)
988 home_directory
= _strdup(tmp
);
989 return home_directory
;
992 if ((tmp
= getenv("HOMEDRIVE")) != NULL
)
994 struct strbuf buf
= STRBUF_INIT
;
995 strbuf_addstr(&buf
, tmp
);
996 if ((tmp
= getenv("HOMEPATH")) != NULL
)
998 strbuf_addstr(&buf
, tmp
);
999 if (is_directory(buf
.buf
))
1001 home_directory
= strbuf_detach(&buf
, NULL
);
1002 return home_directory
;
1005 strbuf_release(&buf
);
1008 if ((tmp
= getenv("USERPROFILE")) != NULL
&& *tmp
)
1009 home_directory
= _strdup(tmp
);
1011 return home_directory
;
1014 // wchar_t wrapper for get_windows_home_directory()
1015 const wchar_t *wget_windows_home_directory(void)
1017 static const wchar_t *home_directory
= NULL
;
1018 wchar_t wpointer
[MAX_PATH
];
1021 return home_directory
;
1023 if (xutftowcs_path(wpointer
, get_windows_home_directory()) < 0)
1026 home_directory
= _wcsdup(wpointer
);
1028 return home_directory
;
1031 int get_set_config(const char *key
, const char *value
, CONFIG_TYPE type
)
1033 char * config_exclusive_filename
= NULL
;
1039 config_exclusive_filename
= git_pathdup("config");
1042 case CONFIG_XDGGLOBAL
:
1044 const char *home
= get_windows_home_directory();
1047 if (type
== CONFIG_GLOBAL
)
1048 config_exclusive_filename
= xstrdup(mkpath("%s/.gitconfig", home
));
1050 config_exclusive_filename
= xstrdup(mkpath("%s/.config/git/config", home
));
1056 if(!config_exclusive_filename
)
1059 ret
= git_config_set_multivar_in_file_gently(config_exclusive_filename
, key
, value
, NULL
, 0);
1060 free(config_exclusive_filename
);
1064 struct mailmap_info
{
1069 struct mailmap_entry
{
1070 /* name and email for the simple mail-only case */
1074 /* name and email for the complex mail and name matching case */
1075 struct string_list namemap
;
1078 int git_read_mailmap(GIT_MAILMAP
*mailmap
)
1080 struct string_list
*map
;
1087 if ((map
= (struct string_list
*)calloc(1, sizeof(struct string_list
))) == NULL
)
1090 if ((result
= read_mailmap(map
, NULL
)) != 0)
1109 int git_lookup_mailmap(GIT_MAILMAP mailmap
, const char** email1
, const char** name1
, const char* email2
, void* payload
, const char *(*author2_cb
)(void*))
1111 struct string_list
*map
;
1117 map
= (struct string_list
*)mailmap
;
1119 while (imax
>= imin
)
1121 int i
= imin
+ ((imax
- imin
) / 2);
1122 struct string_list_item
*si
= (struct string_list_item
*)&map
->items
[i
];
1123 struct mailmap_entry
*me
= (struct mailmap_entry
*)si
->util
;
1124 int comp
= map
->cmp(si
->string
, email2
);
1130 const char *author2
= author2_cb(payload
);
1131 for (unsigned int j
= 0; j
< me
->namemap
.nr
; ++j
)
1133 struct string_list_item
*sj
= (struct string_list_item
*)&me
->namemap
.items
[j
];
1134 struct mailmap_info
*mi
= (struct mailmap_info
*)sj
->util
;
1136 if (!map
->cmp(sj
->string
, author2
))
1139 *email1
= mi
->email
;
1148 *email1
= me
->email
;
1162 void git_free_mailmap(GIT_MAILMAP mailmap
)
1167 clear_mailmap((struct string_list
*)mailmap
);
1171 // just for regression tests
1172 int git_mkdir(const char* path
)
1174 return mkdir(path
, 0);