]> git.proxmox.com Git - libgit2.git/blobdiff - src/libgit2/config_cache.c
Merge https://salsa.debian.org/debian/libgit2 into proxmox/bullseye
[libgit2.git] / src / libgit2 / config_cache.c
diff --git a/src/libgit2/config_cache.c b/src/libgit2/config_cache.c
new file mode 100644 (file)
index 0000000..4bb91f5
--- /dev/null
@@ -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;
+}
+