Commit 274f2c213fdb2402b586827e6e6e27b2e055101c

Vicent Martí 2011-05-19T14:18:57

Merge pull request #193 from carlosmn/config A couple of config improvements

diff --git a/include/git2/config.h b/include/git2/config.h
index 3ebbe64..9ae54f1 100644
--- a/include/git2/config.h
+++ b/include/git2/config.h
@@ -51,7 +51,21 @@ GIT_EXTERN(int) git_config_new(git_config **out);
 GIT_EXTERN(int) git_config_open_bare(git_config **cfg_out, const char *path);
 
 /**
+ * Open the global configuration file at $HOME/.gitconfig
  *
+ * @param cfg pointer to the configuration
+ */
+GIT_EXTERN(int) git_config_open_global(git_config **cfg);
+
+/**
+ * Add a config backend to an existing instance
+ *
+ * Note that the configuration will call the backend's ->free()
+ * function.
+ *
+ * @param cfg the configuration to add the backend to
+ * @param backend the backend to add
+ * @param priority the priority the backend should have
  */
 GIT_EXTERN(int) git_config_add_backend(git_config *cfg, git_config_backend *backend, int priority);
 
diff --git a/src/config.c b/src/config.c
index cd0a73c..0ade5cf 100644
--- a/src/config.c
+++ b/src/config.c
@@ -70,6 +70,40 @@ int git_config_open_bare(git_config **out, const char *path)
 	return error;
 }
 
+int git_config_open_global(git_config **out)
+{
+	char *home = NULL, *filename = NULL;
+	const char *gitconfig = ".gitconfig";
+	int filename_len, ret, error;
+
+	home = git__strdup(getenv("HOME"));
+	if (home == NULL)
+		return GIT_ENOMEM;
+
+	filename_len = strlen(home) + strlen(gitconfig) + 1;
+	filename = git__malloc(filename_len + 1);
+	if (filename == NULL) {
+		error = GIT_ENOMEM;
+		goto out;
+	}
+
+	ret = snprintf(filename, filename_len, "%s/%s", home, gitconfig);
+	if (ret < 0) {
+		error = git__throw(GIT_EOSERR, "Failed to build global filename. OS err: %s", strerror(errno));
+		goto out;
+	} else if (ret >= filename_len) {
+		error = git__throw(GIT_ERROR, "Failed to build global filename. Length calulation wrong");
+		goto out;
+	}
+
+	error = git_config_open_bare(out, filename);
+
+ out:
+	free(home);
+	free(filename);
+	return error;
+}
+
 void git_config_free(git_config *cfg)
 {
 	unsigned int i;
diff --git a/src/config_file.c b/src/config_file.c
index 75319a6..40829eb 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -197,36 +197,49 @@ static cvar_t *cvar_list_find(cvar_t_list *list, const char *name)
 	return NULL;
 }
 
-static int cvar_name_normalize(const char *input, char **output)
+static int cvar_normalize_name(cvar_t *var, char **output)
 {
-	char *input_sp = strchr(input, ' ');
-	char *quote, *str;
-	int i;
+	char *section_sp = strchr(var->section, ' ');
+	char *quote, *name;
+	int len, ret;
 
-	/* We need to make a copy anyway */
-	str = git__strdup(input);
-	if (str == NULL)
+	/*
+	 * The final string is going to be at most one char longer than
+	 * the input
+	 */
+	len = strlen(var->section) + strlen(var->name) + 1;
+	name = git__malloc(len + 1);
+	if (name == NULL)
 		return GIT_ENOMEM;
 
-	*output = str;
+	/* If there aren't any spaces in the section, it's easy */
+	if (section_sp == NULL) {
+		ret = snprintf(name, len + 1, "%s.%s", var->section, var->name);
+		if (ret < 0)
+			return git__throw(GIT_EOSERR, "Failed to normalize name. OS err: %s", strerror(errno));
 
-	/* If there aren't any spaces, we don't need to do anything */
-	if (input_sp == NULL)
+		*output = name;
 		return GIT_SUCCESS;
+	}
 
 	/*
-	 * If there are spaces, we replace the space by a dot, move the
-	 * variable name so that the dot before it replaces the last
-	 * quotation mark and repeat so that the first quotation mark
-	 * disappears.
+	 * If there are spaces, we replace the space by a dot, move
+	 * section name so it overwrites the first quotation mark and
+	 * replace the last quotation mark by a dot. We then append the
+	 * variable name.
 	 */
-	str[input_sp - input] = '.';
-
-	for (i = 0; i < 2; ++i) {
-		quote = strrchr(str, '"');
-		memmove(quote, quote + 1, strlen(quote));
-	}
-
+	strcpy(name, var->section);
+	section_sp = strchr(name, ' ');
+	*section_sp = '.';
+	/* Remove first quote */
+	quote = strchr(name, '"');
+	memmove(quote, quote+1, strlen(quote+1));
+	/* Remove second quote */
+	quote = strchr(name, '"');
+	*quote = '.';
+	strcpy(quote+1, var->name);
+
+	*output = name;
 	return GIT_SUCCESS;
 }
 
@@ -276,7 +289,7 @@ static int file_foreach(git_config_backend *backend, int (*fn)(const char *, voi
 	file_backend *b = (file_backend *)backend;
 
 	CVAR_LIST_FOREACH(&b->var_list, var) {
-		ret = cvar_name_normalize(var->name, &normalized);
+		ret = cvar_normalize_name(var, &normalized);
 		if (ret < GIT_SUCCESS)
 			return ret;