commit c9956ddf7cbdd423962dfe489379e54cecc3eb1d from: Stefan Sperling date: Sun Sep 08 16:13:54 2019 UTC use author name/email from ~/.gitconfig if GOT_AUTHOR is not set commit - aba9c984d1420b77b23320520e70b27ecc83acf7 commit + c9956ddf7cbdd423962dfe489379e54cecc3eb1d blob - ba35bfd0b7a92102f226ca60b973aafe8a4083e7 blob + f8920a6d328a5d4595e4376db6fe7e58674b2378 --- got/got.1 +++ got/got.1 @@ -97,7 +97,9 @@ and .Dv user.email configuration settings can be obtained from the repository's .Pa .git/config -file. +file or from Git's global +.Pa ~/.gitconfig +configuration file. .Pp The options for .Cm got import @@ -704,7 +706,9 @@ and .Dv user.email configuration settings can be obtained from the repository's .Pa .git/config -file. +file or from Git's global +.Pa ~/.gitconfig +configuration file. .Pp The options for .Cm got commit @@ -1226,13 +1230,25 @@ may fail to parse commits without an email address in attempts to reject .Ev GOT_AUTHOR environment variables with a missing email address. -Git's +.Pp +If present, Git's .Dv user.name and .Dv user.email configuration settings in the repository's .Pa .git/config file will override the value of .Ev GOT_AUTHOR . +However, the +.Dv user.name +and +.Dv user.email +configuration settings contained in Git's global +.Pa ~/.gitconfig +configuration file will be used only if the +.Ev GOT_AUTHOR +environment variable is +.Em not +set. .It Ev VISUAL , EDITOR The editor spawned by .Cm got commit , blob - 5f3779846731a64630d792b8c821b712956c9160 blob + 6f3b5690a4904d553f8f4701e41410074501f214 --- got/got.c +++ got/got.c @@ -495,21 +495,27 @@ static const struct got_error * get_author(char **author, struct got_repository *repo) { const struct got_error *err = NULL; - const char *got_author, *gitconfig_name, *gitconfig_email; + const char *got_author, *name, *email; *author = NULL; - gitconfig_name = got_repo_get_gitconfig_author_name(repo); - gitconfig_email = got_repo_get_gitconfig_author_email(repo); - if (gitconfig_name && gitconfig_email) { - if (asprintf(author, "%s <%s>", - gitconfig_name, gitconfig_email) == -1) + name = got_repo_get_gitconfig_author_name(repo); + email = got_repo_get_gitconfig_author_email(repo); + if (name && email) { + if (asprintf(author, "%s <%s>", name, email) == -1) return got_error_from_errno("asprintf"); return NULL; } got_author = getenv("GOT_AUTHOR"); if (got_author == NULL) { + name = got_repo_get_global_gitconfig_author_name(repo); + email = got_repo_get_global_gitconfig_author_email(repo); + if (name && email) { + if (asprintf(author, "%s <%s>", name, email) == -1) + return got_error_from_errno("asprintf"); + return NULL; + } /* TODO: Look up user in password database? */ return got_error(GOT_ERR_COMMIT_NO_AUTHOR); } @@ -544,6 +550,20 @@ done: *author = NULL; } return err; +} + +static const struct got_error * +get_gitconfig_path(char **gitconfig_path) +{ + const char *homedir = getenv("HOME"); + + *gitconfig_path = NULL; + if (homedir) { + if (asprintf(gitconfig_path, "%s/.gitconfig", homedir) == -1) + return got_error_from_errno("asprintf"); + + } + return NULL; } static const struct got_error * @@ -551,7 +571,7 @@ cmd_import(int argc, char *argv[]) { const struct got_error *error = NULL; char *path_dir = NULL, *repo_path = NULL, *logmsg = NULL; - char *editor = NULL, *author = NULL; + char *gitconfig_path = NULL, *editor = NULL, *author = NULL; const char *branch_name = "master"; char *refname = NULL, *id_str = NULL; struct got_repository *repo = NULL; @@ -614,7 +634,10 @@ cmd_import(int argc, char *argv[]) return got_error_from_errno("getcwd"); } got_path_strip_trailing_slashes(repo_path); - error = got_repo_open(&repo, repo_path); + error = get_gitconfig_path(&gitconfig_path); + if (error) + goto done; + error = got_repo_open(&repo, repo_path, gitconfig_path); if (error) goto done; @@ -705,6 +728,7 @@ done: free(new_commit_id); free(id_str); free(author); + free(gitconfig_path); if (branch_ref) got_ref_close(branch_ref); if (head_ref) @@ -986,7 +1010,7 @@ cmd_checkout(int argc, char *argv[]) got_path_strip_trailing_slashes(repo_path); got_path_strip_trailing_slashes(worktree_path); - error = got_repo_open(&repo, repo_path); + error = got_repo_open(&repo, repo_path, NULL); if (error != NULL) goto done; @@ -1239,7 +1263,8 @@ cmd_update(int argc, char *argv[]) if (error) goto done; - error = got_repo_open(&repo, got_worktree_get_repo_path(worktree)); + error = got_repo_open(&repo, got_worktree_get_repo_path(worktree), + NULL); if (error != NULL) goto done; @@ -1795,7 +1820,7 @@ cmd_log(int argc, char *argv[]) goto done; } - error = got_repo_open(&repo, repo_path); + error = got_repo_open(&repo, repo_path, NULL); if (error != NULL) goto done; @@ -2194,7 +2219,7 @@ cmd_diff(int argc, char *argv[]) return got_error_from_errno("getcwd"); } - error = got_repo_open(&repo, repo_path); + error = got_repo_open(&repo, repo_path, NULL); free(repo_path); if (error != NULL) goto done; @@ -2491,7 +2516,7 @@ cmd_blame(int argc, char *argv[]) } } - error = got_repo_open(&repo, repo_path); + error = got_repo_open(&repo, repo_path, NULL); if (error != NULL) goto done; @@ -2790,7 +2815,7 @@ cmd_tree(int argc, char *argv[]) } } - error = got_repo_open(&repo, repo_path); + error = got_repo_open(&repo, repo_path, NULL); if (error != NULL) goto done; @@ -2911,7 +2936,8 @@ cmd_status(int argc, char *argv[]) if (error != NULL) goto done; - error = got_repo_open(&repo, got_worktree_get_repo_path(worktree)); + error = got_repo_open(&repo, got_worktree_get_repo_path(worktree), + NULL); if (error != NULL) goto done; @@ -3146,7 +3172,7 @@ cmd_ref(int argc, char *argv[]) } } - error = got_repo_open(&repo, repo_path); + error = got_repo_open(&repo, repo_path, NULL); if (error != NULL) goto done; @@ -3386,7 +3412,7 @@ cmd_branch(int argc, char *argv[]) } } - error = got_repo_open(&repo, repo_path); + error = got_repo_open(&repo, repo_path, NULL); if (error != NULL) goto done; @@ -3764,6 +3790,7 @@ cmd_tag(int argc, char *argv[]) struct got_repository *repo = NULL; struct got_worktree *worktree = NULL; char *cwd = NULL, *repo_path = NULL, *commit_id_str = NULL; + char *gitconfig_path = NULL; const char *tag_name, *commit_id_arg = NULL, *tagmsg = NULL; int ch, do_list = 0; @@ -3839,18 +3866,23 @@ cmd_tag(int argc, char *argv[]) } } } - - error = got_repo_open(&repo, repo_path); - if (error != NULL) - goto done; - if (do_list) { + error = got_repo_open(&repo, repo_path, NULL); + if (error != NULL) + goto done; error = apply_unveil(got_repo_get_path(repo), 1, NULL); if (error) goto done; error = list_tags(repo, worktree); } else { + error = get_gitconfig_path(&gitconfig_path); + if (error) + goto done; + error = got_repo_open(&repo, repo_path, gitconfig_path); + if (error != NULL) + goto done; + if (tagmsg) { error = apply_unveil(got_repo_get_path(repo), 1, NULL); if (error) @@ -3885,6 +3917,7 @@ done: got_worktree_close(worktree); free(cwd); free(repo_path); + free(gitconfig_path); free(commit_id_str); return error; } @@ -3938,7 +3971,8 @@ cmd_add(int argc, char *argv[]) if (error) goto done; - error = got_repo_open(&repo, got_worktree_get_repo_path(worktree)); + error = got_repo_open(&repo, got_worktree_get_repo_path(worktree), + NULL); if (error != NULL) goto done; @@ -4030,7 +4064,8 @@ cmd_remove(int argc, char *argv[]) if (error) goto done; - error = got_repo_open(&repo, got_worktree_get_repo_path(worktree)); + error = got_repo_open(&repo, got_worktree_get_repo_path(worktree), + NULL); if (error) goto done; @@ -4244,7 +4279,8 @@ cmd_revert(int argc, char *argv[]) if (error) goto done; - error = got_repo_open(&repo, got_worktree_get_repo_path(worktree)); + error = got_repo_open(&repo, got_worktree_get_repo_path(worktree), + NULL); if (error != NULL) goto done; @@ -4406,7 +4442,7 @@ cmd_commit(int argc, char *argv[]) struct got_object_id *id = NULL; const char *logmsg = NULL; struct collect_commit_logmsg_arg cl_arg; - char *editor = NULL, *author = NULL; + char *gitconfig_path = NULL, *editor = NULL, *author = NULL; int ch, rebase_in_progress, histedit_in_progress; struct got_pathlist_head paths; @@ -4454,7 +4490,11 @@ cmd_commit(int argc, char *argv[]) if (error) goto done; - error = got_repo_open(&repo, got_worktree_get_repo_path(worktree)); + error = get_gitconfig_path(&gitconfig_path); + if (error) + goto done; + error = got_repo_open(&repo, got_worktree_get_repo_path(worktree), + gitconfig_path); if (error != NULL) goto done; @@ -4514,6 +4554,7 @@ done: got_worktree_close(worktree); free(cwd); free(id_str); + free(gitconfig_path); free(editor); free(author); return error; @@ -4567,7 +4608,8 @@ cmd_cherrypick(int argc, char *argv[]) if (error) goto done; - error = got_repo_open(&repo, got_worktree_get_repo_path(worktree)); + error = got_repo_open(&repo, got_worktree_get_repo_path(worktree), + NULL); if (error != NULL) goto done; @@ -4682,7 +4724,8 @@ cmd_backout(int argc, char *argv[]) if (error) goto done; - error = got_repo_open(&repo, got_worktree_get_repo_path(worktree)); + error = got_repo_open(&repo, got_worktree_get_repo_path(worktree), + NULL); if (error != NULL) goto done; @@ -5073,7 +5116,8 @@ cmd_rebase(int argc, char *argv[]) if (error) goto done; - error = got_repo_open(&repo, got_worktree_get_repo_path(worktree)); + error = got_repo_open(&repo, got_worktree_get_repo_path(worktree), + NULL); if (error != NULL) goto done; @@ -6067,7 +6111,8 @@ cmd_histedit(int argc, char *argv[]) if (error) goto done; - error = got_repo_open(&repo, got_worktree_get_repo_path(worktree)); + error = got_repo_open(&repo, got_worktree_get_repo_path(worktree), + NULL); if (error != NULL) goto done; @@ -6425,7 +6470,8 @@ cmd_stage(int argc, char *argv[]) if (error) goto done; - error = got_repo_open(&repo, got_worktree_get_repo_path(worktree)); + error = got_repo_open(&repo, got_worktree_get_repo_path(worktree), + NULL); if (error != NULL) goto done; @@ -6532,7 +6578,8 @@ cmd_unstage(int argc, char *argv[]) if (error) goto done; - error = got_repo_open(&repo, got_worktree_get_repo_path(worktree)); + error = got_repo_open(&repo, got_worktree_get_repo_path(worktree), + NULL); if (error != NULL) goto done; @@ -6793,7 +6840,7 @@ cmd_cat(int argc, char *argv[]) return got_error_from_errno("getcwd"); } - error = got_repo_open(&repo, repo_path); + error = got_repo_open(&repo, repo_path, NULL); free(repo_path); if (error != NULL) goto done; blob - f2ecc7472a8da5185c853683082cf7806c36d290 blob + 7ed477b1d49d732af4362f4100cb33659065f814 --- include/got_repository.h +++ include/got_repository.h @@ -19,7 +19,8 @@ struct got_pathlist_head; struct got_tag_object; /* Open and close repositories. */ -const struct got_error *got_repo_open(struct got_repository**, const char *); +const struct got_error *got_repo_open(struct got_repository**, const char *, + const char *); const struct got_error *got_repo_close(struct got_repository*); /* Obtain the on-disk path to the repository. */ @@ -37,6 +38,12 @@ const char *got_repo_get_gitconfig_author_name(struct /* Obtain the commit author email if parsed from gitconfig, else NULL. */ const char *got_repo_get_gitconfig_author_email(struct got_repository *); +/* Obtain global commit author name parsed ~/.gitconfig, else NULL. */ +const char *got_repo_get_global_gitconfig_author_name(struct got_repository *); + +/* Obtain global commit author email parsed ~/.gitconfig, else NULL. */ +const char *got_repo_get_global_gitconfig_author_email(struct got_repository *); + /* * Obtain paths to various directories within a repository. * The caller must dispose of a path with free(3). blob - 71d6c0578341427205b4086dc64fde982ec030e4 blob + c304faf993ada599d3d88ab1f3172d00c4ba1225 --- lib/got_lib_repository.h +++ lib/got_lib_repository.h @@ -45,6 +45,8 @@ struct got_repository { int gitconfig_repository_format_version; char *gitconfig_author_name; char *gitconfig_author_email; + char *global_gitconfig_author_name; + char *global_gitconfig_author_email; }; const struct got_error*got_repo_cache_object(struct got_repository *, blob - 454319ad653bfd26ee86f6f74aa4302c19018868 blob + 2882ec45e57417dc6535ad0d2db736c180bfde42 --- lib/repository.c +++ lib/repository.c @@ -94,11 +94,22 @@ got_repo_get_gitconfig_author_name(struct got_reposito return repo->gitconfig_author_name; } -/* Obtain the commit author email address parsed from gitconfig. */ const char * got_repo_get_gitconfig_author_email(struct got_repository *repo) { return repo->gitconfig_author_email; +} + +const char * +got_repo_get_global_gitconfig_author_name(struct got_repository *repo) +{ + return repo->global_gitconfig_author_name; +} + +const char * +got_repo_get_global_gitconfig_author_email(struct got_repository *repo) +{ + return repo->global_gitconfig_author_email; } int @@ -351,31 +362,25 @@ done: } static const struct got_error * -read_gitconfig(struct got_repository *repo) +parse_gitconfig_file(int *gitconfig_repository_format_version, + char **gitconfig_author_name, char **gitconfig_author_email, + const char *gitconfig_path) { const struct got_error *err = NULL, *child_err = NULL; - char *gitconfig_path = NULL; int fd = -1; int imsg_fds[2] = { -1, -1 }; pid_t pid; struct imsgbuf *ibuf; - /* TODO: Read settings from ~/.gitconfig as well? */ - - /* Read repository's .git/config file. */ - err = get_path_gitconfig(&gitconfig_path, repo); - if (err) - return err; + *gitconfig_repository_format_version = 0; + *gitconfig_author_name = NULL; + *gitconfig_author_email = NULL; fd = open(gitconfig_path, O_RDONLY); if (fd == -1) { - if (errno == ENOENT) { - free(gitconfig_path); + if (errno == ENOENT) return NULL; - } - err = got_error_from_errno2("open", gitconfig_path); - free(gitconfig_path); - return err; + return got_error_from_errno2("open", gitconfig_path); } ibuf = calloc(1, sizeof(*ibuf)); @@ -395,7 +400,7 @@ read_gitconfig(struct got_repository *repo) goto done; } else if (pid == 0) { got_privsep_exec_child(imsg_fds, GOT_PATH_PROG_READ_GITCONFIG, - repo->path); + gitconfig_path); /* not reached */ } @@ -416,7 +421,7 @@ read_gitconfig(struct got_repository *repo) goto done; err = got_privsep_recv_gitconfig_int( - &repo->gitconfig_repository_format_version, ibuf); + gitconfig_repository_format_version, ibuf); if (err) goto done; @@ -424,8 +429,7 @@ read_gitconfig(struct got_repository *repo) if (err) goto done; - err = got_privsep_recv_gitconfig_str(&repo->gitconfig_author_name, - ibuf); + err = got_privsep_recv_gitconfig_str(gitconfig_author_name, ibuf); if (err) goto done; @@ -433,8 +437,7 @@ read_gitconfig(struct got_repository *repo) if (err) goto done; - err = got_privsep_recv_gitconfig_str(&repo->gitconfig_author_email, - ibuf); + err = got_privsep_recv_gitconfig_str(gitconfig_author_email, ibuf); if (err) goto done; @@ -450,13 +453,45 @@ done: err = got_error_from_errno("close"); if (fd != -1 && close(fd) == -1 && err == NULL) err = got_error_from_errno2("close", gitconfig_path); - free(gitconfig_path); free(ibuf); + return err; +} + +static const struct got_error * +read_gitconfig(struct got_repository *repo, const char *global_gitconfig_path) +{ + const struct got_error *err = NULL; + char *repo_gitconfig_path = NULL; + + if (global_gitconfig_path) { + /* Read settings from ~/.gitconfig. */ + int dummy_repo_version; + err = parse_gitconfig_file(&dummy_repo_version, + &repo->global_gitconfig_author_name, + &repo->global_gitconfig_author_email, + global_gitconfig_path); + if (err) + return err; + } + + /* Read repository's .git/config file. */ + err = get_path_gitconfig(&repo_gitconfig_path, repo); + if (err) + return err; + + err = parse_gitconfig_file(&repo->gitconfig_repository_format_version, + &repo->gitconfig_author_name, &repo->gitconfig_author_email, + repo_gitconfig_path); + if (err) + goto done; +done: + free(repo_gitconfig_path); return err; } const struct got_error * -got_repo_open(struct got_repository **repop, const char *path) +got_repo_open(struct got_repository **repop, const char *path, + const char *global_gitconfig_path) { struct got_repository *repo = NULL; const struct got_error *err = NULL; @@ -527,7 +562,7 @@ got_repo_open(struct got_repository **repop, const cha } } while (path); - err = read_gitconfig(repo); + err = read_gitconfig(repo, global_gitconfig_path); if (err) goto done; if (repo->gitconfig_repository_format_version != 0) blob - 789f8587cf7b614618fe2d04be478ed8373e1200 blob + 9ccc0f4caee926967fe680a36d48c59f39910e07 --- lib/worktree.c +++ lib/worktree.c @@ -401,7 +401,7 @@ open_worktree(struct got_worktree **worktree, const ch goto done; } - err = got_repo_open(&repo, (*worktree)->repo_path); + err = got_repo_open(&repo, (*worktree)->repo_path, NULL); if (err) goto done; blob - 287db60001a49e95834395146d0734d2761f0aea blob + a0deace55b016d24b028c446ed393f9eb3412b51 --- tog/tog.c +++ tog/tog.c @@ -1905,7 +1905,7 @@ open_log_view(struct tog_view *view, struct got_object view->search_start = search_start_log_view; view->search_next = search_next_log_view; - err = got_repo_open(&thread_repo, got_repo_get_path(repo)); + err = got_repo_open(&thread_repo, got_repo_get_path(repo), NULL); if (err) goto done; err = got_commit_graph_open(&thread_graph, start_id, s->in_repo_path, @@ -2278,7 +2278,7 @@ cmd_log(int argc, char *argv[]) init_curses(); - error = got_repo_open(&repo, repo_path); + error = got_repo_open(&repo, repo_path, NULL); if (error != NULL) goto done; @@ -2924,7 +2924,7 @@ cmd_diff(int argc, char *argv[]) init_curses(); - error = got_repo_open(&repo, repo_path); + error = got_repo_open(&repo, repo_path, NULL); if (error) goto done; @@ -3307,7 +3307,7 @@ run_blame(struct tog_blame *blame, struct tog_view *vi goto done; } - err = got_repo_open(&thread_repo, got_repo_get_path(repo)); + err = got_repo_open(&thread_repo, got_repo_get_path(repo), NULL); if (err) goto done; @@ -3800,7 +3800,7 @@ cmd_blame(int argc, char *argv[]) init_curses(); - error = got_repo_open(&repo, repo_path); + error = got_repo_open(&repo, repo_path, NULL); if (error != NULL) goto done; @@ -4579,7 +4579,7 @@ cmd_tree(int argc, char *argv[]) init_curses(); - error = got_repo_open(&repo, repo_path); + error = got_repo_open(&repo, repo_path, NULL); if (error != NULL) goto done;