From 047fe29c4f8cd3f9554673570266b1bb9add3f46 Mon Sep 17 00:00:00 2001 From: Sim Domingo Date: Mon, 20 Jun 2016 13:05:48 +0800 Subject: [PATCH 1/6] add failing test to include a missing config file relative to home dir --- tests/config/include.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/config/include.c b/tests/config/include.c index 882b89b16..e46978b44 100644 --- a/tests/config/include.c +++ b/tests/config/include.c @@ -108,6 +108,23 @@ void test_config_include__missing(void) git_config_free(cfg); } +void test_config_include__missing_homedir(void) +{ + git_config *cfg; + git_buf buf = GIT_BUF_INIT; + + cl_git_mkfile("including", "[include]\npath = ~/.nonexistentfile\n[foo]\nbar = baz"); + + giterr_clear(); + cl_git_pass(git_config_open_ondisk(&cfg, "including")); + cl_assert(giterr_last() == NULL); + cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar")); + cl_assert_equal_s("baz", git_buf_cstr(&buf)); + + git_buf_free(&buf); + git_config_free(cfg); +} + #define replicate10(s) s s s s s s s s s s void test_config_include__depth2(void) { From 301dc26a5a426870dc8f0728670c1c59ca42d300 Mon Sep 17 00:00:00 2001 From: Sim Domingo Date: Mon, 20 Jun 2016 13:15:35 +0800 Subject: [PATCH 2/6] fix error when including a missing config file relative to the home directory --- src/config_file.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/config_file.c b/src/config_file.c index 50c5a3d82..6ef80660a 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -1254,8 +1254,16 @@ static int strip_comments(char *line, int in_quotes) static int included_path(git_buf *out, const char *dir, const char *path) { /* From the user's home */ - if (path[0] == '~' && path[1] == '/') - return git_sysdir_find_global_file(out, &path[1]); + int result; + if (path[0] == '~' && path[1] == '/') { + result = git_sysdir_find_global_file(out, &path[1]); + if (result == GIT_ENOTFOUND) { + git_buf_sets(out, &path[1]); + return 0; + } + + return result; + } return git_path_join_unrooted(out, path, dir, NULL); } From 5135ddaac6710cc0b4373764835dc6c519812bc4 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 23 Mar 2017 11:48:41 +0000 Subject: [PATCH 3/6] Introduce `git_sysdir_expand_global_file` Provide a mechanism for callers to expand the full path of a file in the global configuration directory (that is to say, the home directory) even if the file doesn't necessarily exist. This lets callers use their own logic for building paths separate from handling file existence. --- src/sysdir.c | 11 +++++++++++ src/sysdir.h | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/sysdir.c b/src/sysdir.c index ed11221a3..9312a7edb 100644 --- a/src/sysdir.c +++ b/src/sysdir.c @@ -275,3 +275,14 @@ int git_sysdir_find_template_dir(git_buf *path) path, NULL, GIT_SYSDIR_TEMPLATE, "template"); } +int git_sysdir_expand_global_file(git_buf *path, const char *filename) +{ + int error; + + if ((error = git_sysdir_find_global_file(path, NULL)) == 0) { + if (filename) + error = git_buf_joinpath(path, path->ptr, filename); + } + + return error; +} diff --git a/src/sysdir.h b/src/sysdir.h index 11878981c..79f23818a 100644 --- a/src/sysdir.h +++ b/src/sysdir.h @@ -55,6 +55,18 @@ extern int git_sysdir_find_programdata_file(git_buf *path, const char *filename) */ extern int git_sysdir_find_template_dir(git_buf *path); +/** + * Expand the name of a "global" file (i.e. one in a user's home + * directory). Unlike `find_global_file` (above), this makes no + * attempt to check for the existence of the file, and is useful if + * you want the full path regardless of existence. + * + * @param path buffer to write the full path into + * @param filename name of file in the home directory + * @return 0 on success or -1 on error + */ +extern int git_sysdir_expand_global_file(git_buf *path, const char *filename); + typedef enum { GIT_SYSDIR_SYSTEM = 0, GIT_SYSDIR_GLOBAL = 1, From 29aef94830edb6231a0737cfca35233f9a95463f Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 23 Mar 2017 11:59:06 +0000 Subject: [PATCH 4/6] config, attrcache: don't fallback to dirs literally named `~` The config and attrcache file reading code would attempt to load a file in a home directory by expanding the `~` and looking for the file, using `git_sysdir_find_global_file`. If the file was not found, the error handling would look for the literal path, eg `~/filename.txt`. Use the new `git_config_expand_global_file` instead, which allows us to get the path to the file separately, when the path is prefixed with `~/`, and fail with a not found error without falling back to looking for the literal path. --- src/attrcache.c | 12 +++++++----- src/config_file.c | 12 ++---------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/attrcache.c b/src/attrcache.c index 4df14ee2c..54161894b 100644 --- a/src/attrcache.c +++ b/src/attrcache.c @@ -290,14 +290,16 @@ static int attr_cache__lookup_path( const char *cfgval = entry->value; /* expand leading ~/ as needed */ - if (cfgval && cfgval[0] == '~' && cfgval[1] == '/' && - !git_sysdir_find_global_file(&buf, &cfgval[2])) - *out = git_buf_detach(&buf); - else if (cfgval) + if (cfgval && cfgval[0] == '~' && cfgval[1] == '/') { + if (! (error = git_sysdir_expand_global_file(&buf, &cfgval[2]))) + *out = git_buf_detach(&buf); + } else if (cfgval) { *out = git__strdup(cfgval); + } } - else if (!git_sysdir_find_xdg_file(&buf, fallback)) + else if (!git_sysdir_find_xdg_file(&buf, fallback)) { *out = git_buf_detach(&buf); + } git_config_entry_free(entry); git_buf_free(&buf); diff --git a/src/config_file.c b/src/config_file.c index 6ef80660a..5153f57d2 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -1254,16 +1254,8 @@ static int strip_comments(char *line, int in_quotes) static int included_path(git_buf *out, const char *dir, const char *path) { /* From the user's home */ - int result; - if (path[0] == '~' && path[1] == '/') { - result = git_sysdir_find_global_file(out, &path[1]); - if (result == GIT_ENOTFOUND) { - git_buf_sets(out, &path[1]); - return 0; - } - - return result; - } + if (path[0] == '~' && path[1] == '/') + return git_sysdir_expand_global_file(out, &path[1]); return git_path_join_unrooted(out, path, dir, NULL); } From ed812ee725dc73536e5a963655ccdd8be8dec028 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 23 Mar 2017 12:03:29 +0000 Subject: [PATCH 5/6] config::include: sanitize homedir Sanitize the home directory to ensure that we do not accidentally locate a file called `~/.nonexistentfile`. --- tests/config/include.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/config/include.c b/tests/config/include.c index e46978b44..0a07c9b85 100644 --- a/tests/config/include.c +++ b/tests/config/include.c @@ -113,6 +113,7 @@ void test_config_include__missing_homedir(void) git_config *cfg; git_buf buf = GIT_BUF_INIT; + cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, cl_fixture("config"))); cl_git_mkfile("including", "[include]\npath = ~/.nonexistentfile\n[foo]\nbar = baz"); giterr_clear(); @@ -123,6 +124,8 @@ void test_config_include__missing_homedir(void) git_buf_free(&buf); git_config_free(cfg); + + cl_sandbox_set_search_path_defaults(); } #define replicate10(s) s s s s s s s s s s From e65b5e960d23113854712ded8fcabd143b14377b Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Thu, 23 Mar 2017 12:11:31 +0000 Subject: [PATCH 6/6] config: expand paths with `git_sysdir_expand...` --- src/config.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/config.c b/src/config.c index 0d73ad2cc..0893febfa 100644 --- a/src/config.c +++ b/src/config.c @@ -1339,9 +1339,6 @@ fail_parse: 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); @@ -1352,16 +1349,7 @@ int git_config_parse_path(git_buf *out, const char *value) 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_sysdir_expand_global_file(out, value[1] ? &value[2] : NULL); } return git_buf_sets(out, value);