Commit Diff


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;