diff options
author | Carlos Martín Nieto <cmn@dwim.me> | 2014-03-11 14:25:59 +0100 |
---|---|---|
committer | Carlos Martín Nieto <cmn@dwim.me> | 2014-03-11 14:42:52 +0100 |
commit | 2c9c8cdc100bc2e7fdb69eb9d4ad4312cffc460e (patch) | |
tree | aed9aa0816a756f4795b8b9bc6a3b2e3fc6df0dd | |
parent | 9af14886a94ca4d08c7af1ba84b21cba40fce34c (diff) | |
download | libgit2-2c9c8cdc100bc2e7fdb69eb9d4ad4312cffc460e.tar.gz |
config: let the on-disk backend fail to load gracefully
Failure to read certain paths can be a common misconfiguration on many
systems and we do not always want to fail in those cases.
Let the on-disk backend fail to load and create an empty one, as could
be the case for a privilege-dropping application which does not update
its $HOME from the privileged user.
-rw-r--r-- | include/git2/config.h | 12 | ||||
-rw-r--r-- | src/config.c | 34 | ||||
-rw-r--r-- | src/config.h | 3 | ||||
-rw-r--r-- | src/config_file.c | 10 | ||||
-rw-r--r-- | src/submodule.c | 2 | ||||
-rw-r--r-- | tests/config/new.c | 21 |
6 files changed, 66 insertions, 16 deletions
diff --git a/include/git2/config.h b/include/git2/config.h index 663b4f6ba..87c40519e 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -177,6 +177,18 @@ GIT_EXTERN(int) git_config_add_file_ondisk( int force); /** + * Add an on-disk config file instance to an existing config + * + * Behaves like git_config_add_file_ondisk but ignores errors when the + * path is not accessible. + */ +int git_config_add_file_ondisk_gently( + git_config *cfg, + const char *path, + git_config_level_t level, + int force); + +/** * Create a new config instance containing a single on-disk file * * This method is a simple utility wrapper for the following sequence diff --git a/src/config.c b/src/config.c index 1a205fe13..a013ea14c 100644 --- a/src/config.c +++ b/src/config.c @@ -86,25 +86,15 @@ int git_config_new(git_config **out) return 0; } -int git_config_add_file_ondisk( - git_config *cfg, - const char *path, - git_config_level_t level, - int force) +static int add_file_ondisk(git_config *cfg, const char *path, git_config_level_t level, + int force, int allow_fail) { git_config_backend *file = NULL; - struct stat st; int res; assert(cfg && path); - res = p_stat(path, &st); - if (res < 0 && errno != ENOENT) { - giterr_set(GITERR_CONFIG, "Error stat'ing config file '%s'", path); - return -1; - } - - if (git_config_file__ondisk(&file, path) < 0) + if (git_config_file__ondisk(&file, path, allow_fail) < 0) return -1; if ((res = git_config_add_backend(cfg, file, level, force)) < 0) { @@ -119,6 +109,24 @@ int git_config_add_file_ondisk( return 0; } +int git_config_add_file_ondisk( + git_config *cfg, + const char *path, + git_config_level_t level, + int force) +{ + return add_file_ondisk(cfg, path, level, force, 0); +} + +int git_config_add_file_ondisk_gently( + git_config *cfg, + const char *path, + git_config_level_t level, + int force) +{ + return add_file_ondisk(cfg, path, level, force, 1); +} + int git_config_open_ondisk(git_config **out, const char *path) { int error; diff --git a/src/config.h b/src/config.h index 03d910616..57ad22a0b 100644 --- a/src/config.h +++ b/src/config.h @@ -41,8 +41,9 @@ extern int git_config_rename_section( * * @param out the new backend * @param path where the config file is located + * @param allow_fail whether it's ok to fail to open the config file */ -extern int git_config_file__ondisk(git_config_backend **out, const char *path); +extern int git_config_file__ondisk(git_config_backend **out, const char *path, int allow_fail); extern int git_config__normalize_name(const char *in, char **out); diff --git a/src/config_file.c b/src/config_file.c index aedf2cb12..103e6900b 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -96,6 +96,8 @@ typedef struct { char *file_path; git_config_level_t level; + + int allow_fail; } diskfile_backend; static int config_parse(diskfile_backend *cfg_file, struct reader *reader, git_config_level_t level, int depth); @@ -197,6 +199,10 @@ static int config_open(git_config_backend *cfg, git_config_level_t level) /* It's fine if the file doesn't exist */ if (res == GIT_ENOTFOUND) return 0; + /* or if the user doesn't care about failing to open */ + if (res < 0 && b->allow_fail) + return 0; + if (res < 0 || (res = config_parse(b, reader, level, 0)) < 0) { free_vars(b->values); @@ -608,7 +614,7 @@ static int config_delete_multivar(git_config_backend *cfg, const char *name, con return result; } -int git_config_file__ondisk(git_config_backend **out, const char *path) +int git_config_file__ondisk(git_config_backend **out, const char *path, int allow_fail) { diskfile_backend *backend; @@ -620,6 +626,8 @@ int git_config_file__ondisk(git_config_backend **out, const char *path) backend->file_path = git__strdup(path); GITERR_CHECK_ALLOC(backend->file_path); + backend->allow_fail = allow_fail; + backend->parent.open = config_open; backend->parent.get = config_get; backend->parent.set = config_set; diff --git a/src/submodule.c b/src/submodule.c index 9eaf77dae..4618587a5 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -1372,7 +1372,7 @@ static git_config_backend *open_gitmodules( if (okay_to_create || git_path_isfile(path.ptr)) { /* git_config_file__ondisk should only fail if OOM */ - if (git_config_file__ondisk(&mods, path.ptr) < 0) + if (git_config_file__ondisk(&mods, path.ptr, 0) < 0) mods = NULL; /* open should only fail here if the file is malformed */ else if (git_config_file_open(mods, GIT_CONFIG_LEVEL_LOCAL) < 0) { diff --git a/tests/config/new.c b/tests/config/new.c index dd6dbca9e..3b38a4817 100644 --- a/tests/config/new.c +++ b/tests/config/new.c @@ -30,3 +30,24 @@ void test_config_new__write_new_config(void) p_unlink(TEST_CONFIG); } + +#define TEST_DIR "perm-dir" + +void test_config_new__maybe_fail_on_access(void) +{ + git_config *config; + + cl_git_mkfile(TEST_CONFIG, "[core]\nfoo = 4"); + + cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); + git_config_free(config); + + cl_git_pass(p_chmod(TEST_CONFIG, 0000)); + + cl_git_fail_with(-1, git_config_open_ondisk(&config, TEST_CONFIG)); + + cl_git_pass(git_config_new(&config)); + cl_git_pass(git_config_add_file_ondisk_gently(config, TEST_CONFIG, 1, 1)); + + git_config_free(config); +} |