diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2021-11-14 08:47:40 -0500 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2022-02-22 22:07:44 -0500 |
commit | ef4ab2988320005cbcb3db920e6b41f10b3c60cf (patch) | |
tree | 6609f213ad9d607e8df1f543919d3154c056c3ef /src/libgit2/config_mem.c | |
parent | 49e180c862dc7c6d1f62a53bf8756e25b3417968 (diff) | |
download | libgit2-ef4ab2988320005cbcb3db920e6b41f10b3c60cf.tar.gz |
refactor: `src` is now `src/libgit2`
Diffstat (limited to 'src/libgit2/config_mem.c')
-rw-r--r-- | src/libgit2/config_mem.c | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/src/libgit2/config_mem.c b/src/libgit2/config_mem.c new file mode 100644 index 000000000..560229cf5 --- /dev/null +++ b/src/libgit2/config_mem.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "config.h" + +#include "config_backend.h" +#include "config_parse.h" +#include "config_entries.h" + +typedef struct { + git_config_backend parent; + git_config_entries *entries; + git_str cfg; +} config_memory_backend; + +typedef struct { + git_config_entries *entries; + git_config_level_t level; +} config_memory_parse_data; + +static int config_error_readonly(void) +{ + git_error_set(GIT_ERROR_CONFIG, "this backend is read-only"); + return -1; +} + +static int read_variable_cb( + git_config_parser *reader, + const char *current_section, + const char *var_name, + const char *var_value, + const char *line, + size_t line_len, + void *payload) +{ + config_memory_parse_data *parse_data = (config_memory_parse_data *) payload; + git_str buf = GIT_STR_INIT; + git_config_entry *entry; + const char *c; + int result; + + GIT_UNUSED(reader); + GIT_UNUSED(line); + GIT_UNUSED(line_len); + + if (current_section) { + /* TODO: Once warnings land, we should likely warn + * here. Git appears to warn in most cases if it sees + * un-namespaced config options. + */ + git_str_puts(&buf, current_section); + git_str_putc(&buf, '.'); + } + + for (c = var_name; *c; c++) + git_str_putc(&buf, git__tolower(*c)); + + if (git_str_oom(&buf)) + return -1; + + entry = git__calloc(1, sizeof(git_config_entry)); + GIT_ERROR_CHECK_ALLOC(entry); + entry->name = git_str_detach(&buf); + entry->value = var_value ? git__strdup(var_value) : NULL; + entry->level = parse_data->level; + entry->include_depth = 0; + + if ((result = git_config_entries_append(parse_data->entries, entry)) < 0) + return result; + + return result; +} + +static int config_memory_open(git_config_backend *backend, git_config_level_t level, const git_repository *repo) +{ + config_memory_backend *memory_backend = (config_memory_backend *) backend; + git_config_parser parser = GIT_PARSE_CTX_INIT; + config_memory_parse_data parse_data; + int error; + + GIT_UNUSED(repo); + + if ((error = git_config_parser_init(&parser, "in-memory", memory_backend->cfg.ptr, + memory_backend->cfg.size)) < 0) + goto out; + parse_data.entries = memory_backend->entries; + parse_data.level = level; + + if ((error = git_config_parse(&parser, NULL, read_variable_cb, NULL, NULL, &parse_data)) < 0) + goto out; + +out: + git_config_parser_dispose(&parser); + return error; +} + +static int config_memory_get(git_config_backend *backend, const char *key, git_config_entry **out) +{ + config_memory_backend *memory_backend = (config_memory_backend *) backend; + return git_config_entries_get(out, memory_backend->entries, key); +} + +static int config_memory_iterator( + git_config_iterator **iter, + git_config_backend *backend) +{ + config_memory_backend *memory_backend = (config_memory_backend *) backend; + git_config_entries *entries; + int error; + + if ((error = git_config_entries_dup(&entries, memory_backend->entries)) < 0) + goto out; + + if ((error = git_config_entries_iterator_new(iter, entries)) < 0) + goto out; + +out: + /* Let iterator delete duplicated entries when it's done */ + git_config_entries_free(entries); + return error; +} + +static int config_memory_set(git_config_backend *backend, const char *name, const char *value) +{ + GIT_UNUSED(backend); + GIT_UNUSED(name); + GIT_UNUSED(value); + return config_error_readonly(); +} + +static int config_memory_set_multivar( + git_config_backend *backend, const char *name, const char *regexp, const char *value) +{ + GIT_UNUSED(backend); + GIT_UNUSED(name); + GIT_UNUSED(regexp); + GIT_UNUSED(value); + return config_error_readonly(); +} + +static int config_memory_delete(git_config_backend *backend, const char *name) +{ + GIT_UNUSED(backend); + GIT_UNUSED(name); + return config_error_readonly(); +} + +static int config_memory_delete_multivar(git_config_backend *backend, const char *name, const char *regexp) +{ + GIT_UNUSED(backend); + GIT_UNUSED(name); + GIT_UNUSED(regexp); + return config_error_readonly(); +} + +static int config_memory_lock(git_config_backend *backend) +{ + GIT_UNUSED(backend); + return config_error_readonly(); +} + +static int config_memory_unlock(git_config_backend *backend, int success) +{ + GIT_UNUSED(backend); + GIT_UNUSED(success); + return config_error_readonly(); +} + +static void config_memory_free(git_config_backend *_backend) +{ + config_memory_backend *backend = (config_memory_backend *)_backend; + + if (backend == NULL) + return; + + git_config_entries_free(backend->entries); + git_str_dispose(&backend->cfg); + git__free(backend); +} + +int git_config_backend_from_string(git_config_backend **out, const char *cfg, size_t len) +{ + config_memory_backend *backend; + + backend = git__calloc(1, sizeof(config_memory_backend)); + GIT_ERROR_CHECK_ALLOC(backend); + + if (git_config_entries_new(&backend->entries) < 0) { + git__free(backend); + return -1; + } + + if (git_str_set(&backend->cfg, cfg, len) < 0) { + git_config_entries_free(backend->entries); + git__free(backend); + return -1; + } + + backend->parent.version = GIT_CONFIG_BACKEND_VERSION; + backend->parent.readonly = 1; + backend->parent.open = config_memory_open; + backend->parent.get = config_memory_get; + backend->parent.set = config_memory_set; + backend->parent.set_multivar = config_memory_set_multivar; + backend->parent.del = config_memory_delete; + backend->parent.del_multivar = config_memory_delete_multivar; + backend->parent.iterator = config_memory_iterator; + backend->parent.lock = config_memory_lock; + backend->parent.unlock = config_memory_unlock; + backend->parent.snapshot = git_config_backend_snapshot; + backend->parent.free = config_memory_free; + + *out = (git_config_backend *)backend; + + return 0; +} |