summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2015-01-14 15:05:43 +0100
committerCarlos Martín Nieto <cmn@dwim.me>2015-01-14 19:36:50 +0100
commiteac773d92bccc7d3fc7ce1b18578d374873e0d7a (patch)
treeeb165d11a1a30274ed7ff40d27bd461640067bc3
parent4d6f55acce14eeec55729e55335635375e9026df (diff)
downloadlibgit2-cmn/config-get-path.tar.gz
config: add parsing and getter for pathscmn/config-get-path
-rw-r--r--CHANGELOG.md4
-rw-r--r--include/git2/config.h32
-rw-r--r--src/config.c41
-rw-r--r--tests/config/read.c46
4 files changed, 123 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 96bd9a16e..892a489a8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@ v0.22 + 1
### API additions
+* Parsing and retrieving a configuration value as a path is exposed
+ via `git_config_parse_path()` and `git_config_get_path()`
+ respectively.
+
### API removals
### Breaking API changes
diff --git a/include/git2/config.h b/include/git2/config.h
index e32c614ea..1ed8d2441 100644
--- a/include/git2/config.h
+++ b/include/git2/config.h
@@ -320,6 +320,24 @@ GIT_EXTERN(int) git_config_get_int64(int64_t *out, const git_config *cfg, const
GIT_EXTERN(int) git_config_get_bool(int *out, const git_config *cfg, const char *name);
/**
+ * Get the value of a path config variable.
+ *
+ * A leading '~' will be expanded to the global search path (which
+ * defaults to the user's home directory but can be overridden via
+ * `git_libgit2_opts()`.
+ *
+ * All config files will be looked into, in the order of their
+ * defined level. A higher level means a higher priority. The
+ * first occurrence of the variable will be returned here.
+ *
+ * @param out the buffer in which to store the result
+ * @param cfg where to look for the variable
+ * @param name the variable's name
+ * @param 0 or an error code
+ */
+GIT_EXTERN(int) git_config_get_path(git_buf *out, const git_config *cfg, const char *name);
+
+/**
* Get the value of a string config variable.
*
* The string is owned by the variable and should not be freed by the
@@ -615,6 +633,20 @@ GIT_EXTERN(int) git_config_parse_int32(int32_t *out, const char *value);
*/
GIT_EXTERN(int) git_config_parse_int64(int64_t *out, const char *value);
+/**
+ * Parse a string value as a path.
+ *
+ * A leading '~' will be expanded to the global search path (which
+ * defaults to the user's home directory but can be overridden via
+ * `git_libgit2_opts()`.
+ *
+ * If the value does not begin with a tilde, the input will be
+ * returned.
+ *
+ * @param out placae to store the result of parsing
+ * @param value the path to evaluate
+ */
+GIT_EXTERN(int) git_config_parse_path(git_buf *out, const char *value);
/**
* Perform an operation on each config variable in given config backend
diff --git a/src/config.c b/src/config.c
index 0f8c24465..f80770138 100644
--- a/src/config.c
+++ b/src/config.c
@@ -785,6 +785,17 @@ int git_config_get_bool(int *out, const git_config *cfg, const char *name)
return git_config_parse_bool(out, entry->value);
}
+int git_config_get_path(git_buf *out, const git_config *cfg, const char *name)
+{
+ const git_config_entry *entry;
+ int error;
+
+ if ((error = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
+ return error;
+
+ return git_config_parse_path(out, entry->value);
+}
+
int git_config_get_string(
const char **out, const git_config *cfg, const char *name)
{
@@ -1184,6 +1195,36 @@ fail_parse:
return -1;
}
+int git_config_parse_path(git_buf *out, const char *value)
+{
+ int error = 0;
+ const git_buf *home;
+
+ assert(out && value);
+
+ git_buf_sanitize(out);
+
+ if (value[0] == '~') {
+ if (value[1] != '\0' && value[1] != '/') {
+ giterr_set(GITERR_CONFIG, "retrieving a homedir by name is not supported");
+ return -1;
+ }
+
+ if ((error = git_sysdir_get(&home, GIT_SYSDIR_GLOBAL)) < 0)
+ return error;
+
+ git_buf_sets(out, home->ptr);
+ git_buf_puts(out, value + 1);
+
+ if (git_buf_oom(out))
+ return -1;
+
+ return 0;
+ }
+
+ return git_buf_sets(out, value);
+}
+
/* Take something the user gave us and make it nice for our hash function */
int git_config__normalize_name(const char *in, char **out)
{
diff --git a/tests/config/read.c b/tests/config/read.c
index 25672729f..1799970fb 100644
--- a/tests/config/read.c
+++ b/tests/config/read.c
@@ -1,4 +1,6 @@
#include "clar_libgit2.h"
+#include "buffer.h"
+#include "path.h"
void test_config_read__simple_read(void)
{
@@ -567,3 +569,47 @@ void test_config_read__override_variable(void)
git_config_free(cfg);
}
+
+void test_config_read__path(void)
+{
+ git_config *cfg;
+ git_buf path = GIT_BUF_INIT;
+ git_buf old_path = GIT_BUF_INIT;
+ git_buf home_path = GIT_BUF_INIT;
+ git_buf expected_path = GIT_BUF_INIT;
+
+ cl_git_pass(p_mkdir("fakehome", 0777));
+ cl_git_pass(git_path_prettify(&home_path, "fakehome", NULL));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &old_path));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, home_path.ptr));
+ cl_git_mkfile("./testconfig", "[some]\n path = ~/somefile");
+ cl_git_pass(git_path_join_unrooted(&expected_path, "somefile", home_path.ptr, NULL));
+
+ cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
+ cl_git_pass(git_config_get_path(&path, cfg, "some.path"));
+ cl_assert_equal_s(expected_path.ptr, path.ptr);
+ git_buf_free(&path);
+
+ cl_git_mkfile("./testconfig", "[some]\n path = ~/");
+ cl_git_pass(git_path_join_unrooted(&expected_path, "", home_path.ptr, NULL));
+
+ cl_git_pass(git_config_get_path(&path, cfg, "some.path"));
+ cl_assert_equal_s(expected_path.ptr, path.ptr);
+ git_buf_free(&path);
+
+ cl_git_mkfile("./testconfig", "[some]\n path = ~");
+ cl_git_pass(git_buf_sets(&expected_path, home_path.ptr));
+
+ cl_git_pass(git_config_get_path(&path, cfg, "some.path"));
+ cl_assert_equal_s(expected_path.ptr, path.ptr);
+ git_buf_free(&path);
+
+ cl_git_mkfile("./testconfig", "[some]\n path = ~user/foo");
+ cl_git_fail(git_config_get_path(&path, cfg, "some.path"));
+
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, old_path.ptr));
+ git_buf_free(&old_path);
+ git_buf_free(&home_path);
+ git_buf_free(&expected_path);
+ git_config_free(cfg);
+}