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_cache.c | |
parent | 49e180c862dc7c6d1f62a53bf8756e25b3417968 (diff) | |
download | libgit2-ef4ab2988320005cbcb3db920e6b41f10b3c60cf.tar.gz |
refactor: `src` is now `src/libgit2`
Diffstat (limited to 'src/libgit2/config_cache.c')
-rw-r--r-- | src/libgit2/config_cache.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/src/libgit2/config_cache.c b/src/libgit2/config_cache.c new file mode 100644 index 000000000..4bb91f52b --- /dev/null +++ b/src/libgit2/config_cache.c @@ -0,0 +1,142 @@ +/* + * 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 "common.h" + +#include "futils.h" +#include "repository.h" +#include "config.h" +#include "git2/config.h" +#include "vector.h" +#include "filter.h" + +struct map_data { + const char *name; + git_configmap *maps; + size_t map_count; + int default_value; +}; + +/* + * core.eol + * Sets the line ending type to use in the working directory for + * files that have the text property set. Alternatives are lf, crlf + * and native, which uses the platform's native line ending. The default + * value is native. See gitattributes(5) for more information on + * end-of-line conversion. + */ +static git_configmap _configmap_eol[] = { + {GIT_CONFIGMAP_FALSE, NULL, GIT_EOL_UNSET}, + {GIT_CONFIGMAP_STRING, "lf", GIT_EOL_LF}, + {GIT_CONFIGMAP_STRING, "crlf", GIT_EOL_CRLF}, + {GIT_CONFIGMAP_STRING, "native", GIT_EOL_NATIVE} +}; + +/* + * core.autocrlf + * Setting this variable to "true" is almost the same as setting + * the text attribute to "auto" on all files except that text files are + * not guaranteed to be normalized: files that contain CRLF in the + * repository will not be touched. Use this setting if you want to have + * CRLF line endings in your working directory even though the repository + * does not have normalized line endings. This variable can be set to input, + * in which case no output conversion is performed. + */ +static git_configmap _configmap_autocrlf[] = { + {GIT_CONFIGMAP_FALSE, NULL, GIT_AUTO_CRLF_FALSE}, + {GIT_CONFIGMAP_TRUE, NULL, GIT_AUTO_CRLF_TRUE}, + {GIT_CONFIGMAP_STRING, "input", GIT_AUTO_CRLF_INPUT} +}; + +static git_configmap _configmap_safecrlf[] = { + {GIT_CONFIGMAP_FALSE, NULL, GIT_SAFE_CRLF_FALSE}, + {GIT_CONFIGMAP_TRUE, NULL, GIT_SAFE_CRLF_FAIL}, + {GIT_CONFIGMAP_STRING, "warn", GIT_SAFE_CRLF_WARN} +}; + +static git_configmap _configmap_logallrefupdates[] = { + {GIT_CONFIGMAP_FALSE, NULL, GIT_LOGALLREFUPDATES_FALSE}, + {GIT_CONFIGMAP_TRUE, NULL, GIT_LOGALLREFUPDATES_TRUE}, + {GIT_CONFIGMAP_STRING, "always", GIT_LOGALLREFUPDATES_ALWAYS}, +}; + +/* + * Generic map for integer values + */ +static git_configmap _configmap_int[] = { + {GIT_CONFIGMAP_INT32, NULL, 0}, +}; + +static struct map_data _configmaps[] = { + {"core.autocrlf", _configmap_autocrlf, ARRAY_SIZE(_configmap_autocrlf), GIT_AUTO_CRLF_DEFAULT}, + {"core.eol", _configmap_eol, ARRAY_SIZE(_configmap_eol), GIT_EOL_DEFAULT}, + {"core.symlinks", NULL, 0, GIT_SYMLINKS_DEFAULT }, + {"core.ignorecase", NULL, 0, GIT_IGNORECASE_DEFAULT }, + {"core.filemode", NULL, 0, GIT_FILEMODE_DEFAULT }, + {"core.ignorestat", NULL, 0, GIT_IGNORESTAT_DEFAULT }, + {"core.trustctime", NULL, 0, GIT_TRUSTCTIME_DEFAULT }, + {"core.abbrev", _configmap_int, 1, GIT_ABBREV_DEFAULT }, + {"core.precomposeunicode", NULL, 0, GIT_PRECOMPOSE_DEFAULT }, + {"core.safecrlf", _configmap_safecrlf, ARRAY_SIZE(_configmap_safecrlf), GIT_SAFE_CRLF_DEFAULT}, + {"core.logallrefupdates", _configmap_logallrefupdates, ARRAY_SIZE(_configmap_logallrefupdates), GIT_LOGALLREFUPDATES_DEFAULT}, + {"core.protecthfs", NULL, 0, GIT_PROTECTHFS_DEFAULT }, + {"core.protectntfs", NULL, 0, GIT_PROTECTNTFS_DEFAULT }, + {"core.fsyncobjectfiles", NULL, 0, GIT_FSYNCOBJECTFILES_DEFAULT }, + {"core.longpaths", NULL, 0, GIT_LONGPATHS_DEFAULT }, +}; + +int git_config__configmap_lookup(int *out, git_config *config, git_configmap_item item) +{ + int error = 0; + struct map_data *data = &_configmaps[(int)item]; + git_config_entry *entry; + + if ((error = git_config__lookup_entry(&entry, config, data->name, false)) < 0) + return error; + + if (!entry) + *out = data->default_value; + else if (data->maps) + error = git_config_lookup_map_value( + out, data->maps, data->map_count, entry->value); + else + error = git_config_parse_bool(out, entry->value); + + git_config_entry_free(entry); + return error; +} + +int git_repository__configmap_lookup(int *out, git_repository *repo, git_configmap_item item) +{ + intptr_t value = (intptr_t)git_atomic_load(repo->configmap_cache[(int)item]); + + *out = (int)value; + + if (value == GIT_CONFIGMAP_NOT_CACHED) { + git_config *config; + intptr_t oldval = value; + int error; + + if ((error = git_repository_config__weakptr(&config, repo)) < 0 || + (error = git_config__configmap_lookup(out, config, item)) < 0) + return error; + + value = *out; + git_atomic_compare_and_swap(&repo->configmap_cache[(int)item], (void *)oldval, (void *)value); + } + + return 0; +} + +void git_repository__configmap_lookup_cache_clear(git_repository *repo) +{ + int i; + + for (i = 0; i < GIT_CONFIGMAP_CACHE_MAX; ++i) + repo->configmap_cache[i] = GIT_CONFIGMAP_NOT_CACHED; +} + |