diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2015-01-26 11:28:59 -0600 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2015-01-26 11:28:59 -0600 |
commit | 1ac5acdc695b837a921897a9d42acc75649cfd4f (patch) | |
tree | 6c5972270209a8cfe17f45534c28d211c8a3db71 | |
parent | 2724219918abeb51b8a5cb8f92cb09acfd447c57 (diff) | |
parent | eac773d92bccc7d3fc7ce1b18578d374873e0d7a (diff) | |
download | libgit2-1ac5acdc695b837a921897a9d42acc75649cfd4f.tar.gz |
Merge pull request #2819 from libgit2/cmn/config-get-path
config: add parsing and getter for paths
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | include/git2/config.h | 32 | ||||
-rw-r--r-- | src/config.c | 41 | ||||
-rw-r--r-- | tests/config/read.c | 46 |
4 files changed, 123 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index e1c02f965..bffcb2561 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,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); +} |