Commits

Anonymous committed c0a2e1c Merge

Merge branch 'pb/config'

* pb/config:
git_config: access() returns 0 on success, not > 0
repo-config: Fix late-night bug
Read configuration also from $HOME/.gitconfig
Fix setting config variables with an alternative GIT_CONFIG
Support for extracting configuration from different files

Comments (0)

Files changed (5)

Documentation/git-repo-config.txt

 	List all variables set in .git/config.
 
 
+ENVIRONMENT
+-----------
+
+GIT_CONFIG::
+	Take the configuration from the given file instead of .git/config.
+
+GIT_CONFIG_LOCAL::
+	Currently the same as $GIT_CONFIG; when Git will support global
+	configuration files, this will cause it to take the configuration
+	from the global configuration file in addition to the given file.
+
+
 EXAMPLE
 -------
 
 
 int git_config(config_fn_t fn)
 {
-	return git_config_from_file(fn, git_path("config"));
+	int ret = 0;
+	char *repo_config = NULL;
+	const char *home = NULL, *filename;
+
+	/* $GIT_CONFIG makes git read _only_ the given config file,
+	 * $GIT_CONFIG_LOCAL will make it process it in addition to the
+	 * global config file, the same way it would the per-repository
+	 * config file otherwise. */
+	filename = getenv("GIT_CONFIG");
+	if (!filename) {
+		home = getenv("HOME");
+		filename = getenv("GIT_CONFIG_LOCAL");
+		if (!filename)
+			filename = repo_config = strdup(git_path("config"));
+	}
+
+	if (home) {
+		char *user_config = strdup(mkpath("%s/.gitconfig", home));
+		if (!access(user_config, R_OK))
+			ret = git_config_from_file(fn, user_config);
+		free(user_config);
+	}
+
+	ret += git_config_from_file(fn, filename);
+	if (repo_config)
+		free(repo_config);
+	return ret;
 }
 
 /*
 	int i, dot;
 	int fd = -1, in_fd;
 	int ret;
-	char* config_filename = strdup(git_path("config"));
-	char* lock_file = strdup(git_path("config.lock"));
+	char* config_filename;
+	char* lock_file;
 	const char* last_dot = strrchr(key, '.');
 
+	config_filename = getenv("GIT_CONFIG");
+	if (!config_filename) {
+		config_filename = getenv("GIT_CONFIG_LOCAL");
+		if (!config_filename)
+			config_filename  = git_path("config");
+	}
+	config_filename = strdup(config_filename);
+	lock_file = strdup(mkpath("%s.lock", config_filename));
+
 	/*
 	 * Since "key" actually contains the section name and the real
 	 * key name separated by a dot, we have to know where the dot is.
 		 * As a side effect, we make sure to transform only a valid
 		 * existing config file.
 		 */
-		if (git_config(store_aux)) {
+		if (git_config_from_file(store_aux, config_filename)) {
 			fprintf(stderr, "invalid config file\n");
 			free(store.key);
 			if (store.value_regex != NULL) {
 
 static int get_value(const char* key_, const char* regex_)
 {
+	int ret = -1;
 	char *tl;
+	char *global = NULL, *repo_config = NULL;
+	const char *local;
+
+	local = getenv("GIT_CONFIG");
+	if (!local) {
+		const char *home = getenv("HOME");
+		local = getenv("GIT_CONFIG_LOCAL");
+		if (!local)
+			local = repo_config = strdup(git_path("config"));
+		if (home)
+			global = strdup(mkpath("%s/.gitconfig", home));
+	}
 
 	key = strdup(key_);
 	for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl)
 		key_regexp = (regex_t*)malloc(sizeof(regex_t));
 		if (regcomp(key_regexp, key, REG_EXTENDED)) {
 			fprintf(stderr, "Invalid key pattern: %s\n", key_);
-			return -1;
+			goto free_strings;
 		}
 	}
 
 		regexp = (regex_t*)malloc(sizeof(regex_t));
 		if (regcomp(regexp, regex_, REG_EXTENDED)) {
 			fprintf(stderr, "Invalid pattern: %s\n", regex_);
-			return -1;
+			goto free_strings;
 		}
 	}
 
-	git_config(show_config);
+	if (do_all && global)
+		git_config_from_file(show_config, global);
+	git_config_from_file(show_config, local);
+	if (!do_all && !seen && global)
+		git_config_from_file(show_config, global);
+
 	free(key);
 	if (regexp) {
 		regfree(regexp);
 	}
 
 	if (do_all)
-		return !seen;
-
-	return (seen == 1) ? 0 : 1;
+		ret = !seen;
+	else
+		ret =  (seen == 1) ? 0 : 1;
+
+free_strings:
+	if (repo_config)
+		free(repo_config);
+	if (global)
+		free(global);
+	return ret;
 }
 
 int main(int argc, const char **argv)
 all: $(T) clean
 
 $(T):
-	@echo "*** $@ ***"; '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
+	@echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
 
 clean:
 	rm -fr trash

t/t1300-repo-config.sh

 
 test_expect_success 'new variable inserts into proper section' 'cmp .git/config expect'
 
+cat > other-config << EOF
+[ein]
+	bahn = strasse
+EOF
+
+cat > expect << EOF
+ein.bahn=strasse
+EOF
+
+GIT_CONFIG=other-config git-repo-config -l > output
+
+test_expect_success 'alternative GIT_CONFIG' 'cmp output expect'
+
+GIT_CONFIG=other-config git-repo-config anwohner.park ausweis
+
+cat > expect << EOF
+[ein]
+	bahn = strasse
+[anwohner]
+	park = ausweis
+EOF
+
+test_expect_success '--set in alternative GIT_CONFIG' 'cmp other-config expect'
+
 test_done