diff options
Diffstat (limited to 'src/config.c')
-rw-r--r-- | src/config.c | 233 |
1 files changed, 128 insertions, 105 deletions
diff --git a/src/config.c b/src/config.c index 03473af8e..8d2e12f98 100644 --- a/src/config.c +++ b/src/config.c @@ -12,7 +12,7 @@ #include "git2/sys/config.h" #include "vector.h" #include "buf_text.h" -#include "config_file.h" +#include "config_backend.h" #include "transaction.h" #if GIT_WIN32 # include <windows.h> @@ -31,30 +31,30 @@ void git_config_entry_free(git_config_entry *entry) typedef struct { git_refcount rc; - git_config_backend *file; + git_config_backend *backend; git_config_level_t level; -} file_internal; +} backend_internal; -static void file_internal_free(file_internal *internal) +static void backend_internal_free(backend_internal *internal) { - git_config_backend *file; + git_config_backend *backend; - file = internal->file; - file->free(file); + backend = internal->backend; + backend->free(backend); git__free(internal); } static void config_free(git_config *cfg) { size_t i; - file_internal *internal; + backend_internal *internal; - for (i = 0; i < cfg->files.length; ++i) { - internal = git_vector_get(&cfg->files, i); - GIT_REFCOUNT_DEC(internal, file_internal_free); + for (i = 0; i < cfg->backends.length; ++i) { + internal = git_vector_get(&cfg->backends, i); + GIT_REFCOUNT_DEC(internal, backend_internal_free); } - git_vector_free(&cfg->files); + git_vector_free(&cfg->backends); git__memzero(cfg, sizeof(*cfg)); git__free(cfg); @@ -70,8 +70,8 @@ void git_config_free(git_config *cfg) static int config_backend_cmp(const void *a, const void *b) { - const file_internal *bk_a = (const file_internal *)(a); - const file_internal *bk_b = (const file_internal *)(b); + const backend_internal *bk_a = (const backend_internal *)(a); + const backend_internal *bk_b = (const backend_internal *)(b); return bk_b->level - bk_a->level; } @@ -85,7 +85,7 @@ int git_config_new(git_config **out) memset(cfg, 0x0, sizeof(git_config)); - if (git_vector_init(&cfg->files, 3, config_backend_cmp) < 0) { + if (git_vector_init(&cfg->backends, 3, config_backend_cmp) < 0) { git__free(cfg); return -1; } @@ -114,7 +114,7 @@ int git_config_add_file_ondisk( return -1; } - if (git_config_file__ondisk(&file, path) < 0) + if (git_config_backend_from_file(&file, path) < 0) return -1; if ((res = git_config_add_backend(cfg, file, level, repo, force)) < 0) { @@ -151,7 +151,7 @@ int git_config_snapshot(git_config **out, git_config *in) { int error = 0; size_t i; - file_internal *internal; + backend_internal *internal; git_config *config; *out = NULL; @@ -159,10 +159,10 @@ int git_config_snapshot(git_config **out, git_config *in) if (git_config_new(&config) < 0) return -1; - git_vector_foreach(&in->files, i, internal) { + git_vector_foreach(&in->backends, i, internal) { git_config_backend *b; - if ((error = internal->file->snapshot(&b, internal->file)) < 0) + if ((error = internal->backend->snapshot(&b, internal->backend)) < 0) break; if ((error = git_config_add_backend(config, b, internal->level, NULL, 0)) < 0) { @@ -179,24 +179,24 @@ int git_config_snapshot(git_config **out, git_config *in) return error; } -static int find_internal_file_by_level( - file_internal **internal_out, +static int find_backend_by_level( + backend_internal **out, const git_config *cfg, git_config_level_t level) { int pos = -1; - file_internal *internal; + backend_internal *internal; size_t i; - /* when passing GIT_CONFIG_HIGHEST_LEVEL, the idea is to get the config file - * which has the highest level. As config files are stored in a vector - * sorted by decreasing order of level, getting the file at position 0 + /* when passing GIT_CONFIG_HIGHEST_LEVEL, the idea is to get the config backend + * which has the highest level. As config backends are stored in a vector + * sorted by decreasing order of level, getting the backend at position 0 * will do the job. */ if (level == GIT_CONFIG_HIGHEST_LEVEL) { pos = 0; } else { - git_vector_foreach(&cfg->files, i, internal) { + git_vector_foreach(&cfg->backends, i, internal) { if (internal->level == level) pos = (int)i; } @@ -204,34 +204,34 @@ static int find_internal_file_by_level( if (pos == -1) { giterr_set(GITERR_CONFIG, - "no config file exists for the given level '%i'", (int)level); + "no configuration exists for the given level '%i'", (int)level); return GIT_ENOTFOUND; } - *internal_out = git_vector_get(&cfg->files, pos); + *out = git_vector_get(&cfg->backends, pos); return 0; } static int duplicate_level(void **old_raw, void *new_raw) { - file_internal **old = (file_internal **)old_raw; + backend_internal **old = (backend_internal **)old_raw; GIT_UNUSED(new_raw); - giterr_set(GITERR_CONFIG, "a file with the same level (%i) has already been added to the config", (int)(*old)->level); + giterr_set(GITERR_CONFIG, "there already exists a configuration for the given level (%i)", (int)(*old)->level); return GIT_EEXISTS; } -static void try_remove_existing_file_internal( +static void try_remove_existing_backend( git_config *cfg, git_config_level_t level) { int pos = -1; - file_internal *internal; + backend_internal *internal; size_t i; - git_vector_foreach(&cfg->files, i, internal) { + git_vector_foreach(&cfg->backends, i, internal) { if (internal->level == level) pos = (int)i; } @@ -239,32 +239,32 @@ static void try_remove_existing_file_internal( if (pos == -1) return; - internal = git_vector_get(&cfg->files, pos); + internal = git_vector_get(&cfg->backends, pos); - if (git_vector_remove(&cfg->files, pos) < 0) + if (git_vector_remove(&cfg->backends, pos) < 0) return; - GIT_REFCOUNT_DEC(internal, file_internal_free); + GIT_REFCOUNT_DEC(internal, backend_internal_free); } static int git_config__add_internal( git_config *cfg, - file_internal *internal, + backend_internal *internal, git_config_level_t level, int force) { int result; - /* delete existing config file for level if it exists */ + /* delete existing config backend for level if it exists */ if (force) - try_remove_existing_file_internal(cfg, level); + try_remove_existing_backend(cfg, level); - if ((result = git_vector_insert_sorted(&cfg->files, + if ((result = git_vector_insert_sorted(&cfg->backends, internal, &duplicate_level)) < 0) return result; - git_vector_sort(&cfg->files); - internal->file->cfg = cfg; + git_vector_sort(&cfg->backends); + internal->backend->cfg = cfg; GIT_REFCOUNT_INC(internal); @@ -285,10 +285,10 @@ int git_config_open_level( git_config_level_t level) { git_config *cfg; - file_internal *internal; + backend_internal *internal; int res; - if ((res = find_internal_file_by_level(&internal, cfg_parent, level)) < 0) + if ((res = find_backend_by_level(&internal, cfg_parent, level)) < 0) return res; if ((res = git_config_new(&cfg)) < 0) @@ -306,27 +306,27 @@ int git_config_open_level( int git_config_add_backend( git_config *cfg, - git_config_backend *file, + git_config_backend *backend, git_config_level_t level, const git_repository *repo, int force) { - file_internal *internal; + backend_internal *internal; int result; - assert(cfg && file); + assert(cfg && backend); - GITERR_CHECK_VERSION(file, GIT_CONFIG_BACKEND_VERSION, "git_config_backend"); + GITERR_CHECK_VERSION(backend, GIT_CONFIG_BACKEND_VERSION, "git_config_backend"); - if ((result = file->open(file, level, repo)) < 0) + if ((result = backend->open(backend, level, repo)) < 0) return result; - internal = git__malloc(sizeof(file_internal)); + internal = git__malloc(sizeof(backend_internal)); GITERR_CHECK_ALLOC(internal); - memset(internal, 0x0, sizeof(file_internal)); + memset(internal, 0x0, sizeof(backend_internal)); - internal->file = file; + internal->backend = backend; internal->level = level; if ((result = git_config__add_internal(cfg, internal, level, force)) < 0) { @@ -351,11 +351,11 @@ typedef struct { static int find_next_backend(size_t *out, const git_config *cfg, size_t i) { - file_internal *internal; + backend_internal *internal; for (; i > 0; --i) { - internal = git_vector_get(&cfg->files, i - 1); - if (!internal || !internal->file) + internal = git_vector_get(&cfg->backends, i - 1); + if (!internal || !internal->backend) continue; *out = i; @@ -368,7 +368,7 @@ static int find_next_backend(size_t *out, const git_config *cfg, size_t i) static int all_iter_next(git_config_entry **entry, git_config_iterator *_iter) { all_iter *iter = (all_iter *) _iter; - file_internal *internal; + backend_internal *internal; git_config_backend *backend; size_t i; int error = 0; @@ -385,8 +385,8 @@ static int all_iter_next(git_config_entry **entry, git_config_iterator *_iter) if (find_next_backend(&i, iter->cfg, iter->i) < 0) return GIT_ITEROVER; - internal = git_vector_get(&iter->cfg->files, i - 1); - backend = internal->file; + internal = git_vector_get(&iter->cfg->backends, i - 1); + backend = internal->backend; iter->i = i - 1; if (iter->current) @@ -461,7 +461,7 @@ int git_config_iterator_new(git_config_iterator **out, const git_config *cfg) iter->parent.free = all_iter_free; iter->parent.next = all_iter_next; - iter->i = cfg->files.length; + iter->i = cfg->backends.length; iter->cfg = cfg; *out = (git_config_iterator *) iter; @@ -488,7 +488,7 @@ int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cf iter->parent.next = all_iter_glob_next; iter->parent.free = all_iter_glob_free; - iter->i = cfg->files.length; + iter->i = cfg->backends.length; iter->cfg = cfg; *out = (git_config_iterator *) iter; @@ -592,38 +592,38 @@ static int get_backend_for_use(git_config_backend **out, git_config *cfg, const char *name, backend_use use) { size_t i; - file_internal *f; + backend_internal *backend; *out = NULL; - if (git_vector_length(&cfg->files) == 0) { + if (git_vector_length(&cfg->backends) == 0) { giterr_set(GITERR_CONFIG, - "cannot %s value for '%s' when no config files exist", + "cannot %s value for '%s' when no config backends exist", uses[use], name); return GIT_ENOTFOUND; } - git_vector_foreach(&cfg->files, i, f) { - if (!f->file->readonly) { - *out = f->file; + git_vector_foreach(&cfg->backends, i, backend) { + if (!backend->backend->readonly) { + *out = backend->backend; return 0; } } giterr_set(GITERR_CONFIG, - "cannot %s value for '%s' when all config files are readonly", + "cannot %s value for '%s' when all config backends are readonly", uses[use], name); return GIT_ENOTFOUND; } int git_config_delete_entry(git_config *cfg, const char *name) { - git_config_backend *file; + git_config_backend *backend; - if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0) + if (get_backend_for_use(&backend, cfg, name, BACKEND_USE_DELETE) < 0) return GIT_ENOTFOUND; - return file->del(file, name); + return backend->del(backend, name); } int git_config_set_int64(git_config *cfg, const char *name, int64_t value) @@ -646,17 +646,17 @@ int git_config_set_bool(git_config *cfg, const char *name, int value) int git_config_set_string(git_config *cfg, const char *name, const char *value) { int error; - git_config_backend *file; + git_config_backend *backend; if (!value) { giterr_set(GITERR_CONFIG, "the value to set cannot be NULL"); return -1; } - if (get_backend_for_use(&file, cfg, name, BACKEND_USE_SET) < 0) + if (get_backend_for_use(&backend, cfg, name, BACKEND_USE_SET) < 0) return GIT_ENOTFOUND; - error = file->set(file, name, value); + error = backend->set(backend, name, value); if (!error && GIT_REFCOUNT_OWNER(cfg) != NULL) git_repository__cvar_cache_clear(GIT_REFCOUNT_OWNER(cfg)); @@ -722,7 +722,7 @@ static int get_entry( const char *key = name; char *normalized = NULL; size_t i; - file_internal *internal; + backend_internal *internal; *out = NULL; @@ -733,11 +733,11 @@ static int get_entry( } res = GIT_ENOTFOUND; - git_vector_foreach(&cfg->files, i, internal) { - if (!internal || !internal->file) + git_vector_foreach(&cfg->backends, i, internal) { + if (!internal || !internal->backend) continue; - res = internal->file->get(internal->file, key, out); + res = internal->backend->get(internal->backend, key, out); if (res != GIT_ENOTFOUND) break; } @@ -835,13 +835,13 @@ int git_config_get_bool(int *out, const git_config *cfg, const char *name) static int is_readonly(const git_config *cfg) { size_t i; - file_internal *internal; + backend_internal *internal; - git_vector_foreach(&cfg->files, i, internal) { - if (!internal || !internal->file) + git_vector_foreach(&cfg->backends, i, internal) { + if (!internal || !internal->backend) continue; - if (!internal->file->readonly) + if (!internal->backend->readonly) return 0; } @@ -1058,22 +1058,22 @@ on_error: int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value) { - git_config_backend *file; + git_config_backend *backend; - if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0) + if (get_backend_for_use(&backend, cfg, name, BACKEND_USE_DELETE) < 0) return GIT_ENOTFOUND; - return file->set_multivar(file, name, regexp, value); + return backend->set_multivar(backend, name, regexp, value); } int git_config_delete_multivar(git_config *cfg, const char *name, const char *regexp) { - git_config_backend *file; + git_config_backend *backend; - if (get_backend_for_use(&file, cfg, name, BACKEND_USE_DELETE) < 0) + if (get_backend_for_use(&backend, cfg, name, BACKEND_USE_DELETE) < 0) return GIT_ENOTFOUND; - return file->del_multivar(file, name, regexp); + return backend->del_multivar(backend, name, regexp); } int git_config_next(git_config_entry **entry, git_config_iterator *iter) @@ -1179,17 +1179,17 @@ int git_config_open_default(git_config **out) int git_config_lock(git_transaction **out, git_config *cfg) { int error; - git_config_backend *file; - file_internal *internal; + git_config_backend *backend; + backend_internal *internal; - internal = git_vector_get(&cfg->files, 0); - if (!internal || !internal->file) { - giterr_set(GITERR_CONFIG, "cannot lock; the config has no backends/files"); + internal = git_vector_get(&cfg->backends, 0); + if (!internal || !internal->backend) { + giterr_set(GITERR_CONFIG, "cannot lock; the config has no backends"); return -1; } - file = internal->file; + backend = internal->backend; - if ((error = file->lock(file)) < 0) + if ((error = backend->lock(backend)) < 0) return error; return git_transaction_config_new(out, cfg); @@ -1197,18 +1197,18 @@ int git_config_lock(git_transaction **out, git_config *cfg) int git_config_unlock(git_config *cfg, int commit) { - git_config_backend *file; - file_internal *internal; + git_config_backend *backend; + backend_internal *internal; - internal = git_vector_get(&cfg->files, 0); - if (!internal || !internal->file) { - giterr_set(GITERR_CONFIG, "cannot lock; the config has no backends/files"); + internal = git_vector_get(&cfg->backends, 0); + if (!internal || !internal->backend) { + giterr_set(GITERR_CONFIG, "cannot lock; the config has no backends"); return -1; } - file = internal->file; + backend = internal->backend; - return file->unlock(file, commit); + return backend->unlock(backend, commit); } /*********** @@ -1376,6 +1376,30 @@ int git_config_parse_path(git_buf *out, const char *value) return git_buf_sets(out, value); } +static int normalize_section(char *start, char *end) +{ + char *scan; + + if (start == end) + return GIT_EINVALIDSPEC; + + /* Validate and downcase range */ + for (scan = start; *scan; ++scan) { + if (end && scan >= end) + break; + if (isalnum(*scan)) + *scan = (char)git__tolower(*scan); + else if (*scan != '-' || scan == start) + return GIT_EINVALIDSPEC; + } + + if (scan == start) + return GIT_EINVALIDSPEC; + + return 0; +} + + /* Take something the user gave us and make it nice for our hash function */ int git_config__normalize_name(const char *in, char **out) { @@ -1393,8 +1417,8 @@ int git_config__normalize_name(const char *in, char **out) goto invalid; /* Validate and downcase up to first dot and after last dot */ - if (git_config_file_normalize_section(name, fdot) < 0 || - git_config_file_normalize_section(ldot + 1, NULL) < 0) + if (normalize_section(name, fdot) < 0 || + normalize_section(ldot + 1, NULL) < 0) goto invalid; /* If there is a middle range, make sure it doesn't have newlines */ @@ -1466,8 +1490,7 @@ int git_config_rename_section( goto cleanup; if (new_section_name != NULL && - (error = git_config_file_normalize_section( - replace.ptr, strchr(replace.ptr, '.'))) < 0) + (error = normalize_section(replace.ptr, strchr(replace.ptr, '.'))) < 0) { giterr_set( GITERR_CONFIG, "invalid config section '%s'", new_section_name); |