Commit f2c25d1893cfa897b0d36005604c134a731e402d

Vicent Martí 2012-03-02T20:08:00

config: Implement a proper cvar cache

diff --git a/src/crlf.c b/src/crlf.c
index e74f8e8..404156d 100644
--- a/src/crlf.c
+++ b/src/crlf.c
@@ -223,8 +223,16 @@ int git_filter_add__crlf_to_odb(git_vector *filters, git_repository *repo, const
 	if (ca.crlf_action == GIT_CRLF_BINARY)
 		return 0;
 
-	if (ca.crlf_action == GIT_CRLF_GUESS && repo->filter_options.auto_crlf == GIT_AUTO_CRLF_FALSE)
-		return 0;
+	if (ca.crlf_action == GIT_CRLF_GUESS) {
+		int auto_crlf;
+
+		if ((error = git_repository__cvar(
+			&auto_crlf, repo, GIT_CVAR_AUTO_CRLF)) < GIT_SUCCESS)
+			return error;
+
+		if (auto_crlf == GIT_AUTO_CRLF_FALSE)
+			return 0;
+	}
 
 	/* If we're good, we create a new filter object and push it
 	 * into the filters array */
diff --git a/src/filter.c b/src/filter.c
index 92b3566..f93730a 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -84,60 +84,10 @@ int git_text_is_binary(git_text_stats *stats)
 	return 0;
 }
 
-static int load_repository_settings(git_repository *repo)
-{
-	static git_cvar_map map_eol[] = {
-		{GIT_CVAR_FALSE, NULL, GIT_EOL_UNSET},
-		{GIT_CVAR_STRING, "lf", GIT_EOL_LF},
-		{GIT_CVAR_STRING, "crlf", GIT_EOL_CRLF},
-		{GIT_CVAR_STRING, "native", GIT_EOL_NATIVE}
-	};
-
-	static git_cvar_map map_crlf[] = {
-		{GIT_CVAR_FALSE, NULL, GIT_AUTO_CRLF_FALSE},
-		{GIT_CVAR_TRUE, NULL, GIT_AUTO_CRLF_TRUE},
-		{GIT_CVAR_STRING, "input", GIT_AUTO_CRLF_INPUT}
-	};
-
-	git_config *config;
-	int error;
-
-	if (repo->filter_options.loaded)
-		return GIT_SUCCESS;
-
-	repo->filter_options.eol = GIT_EOL_DEFAULT;
-	repo->filter_options.auto_crlf = GIT_AUTO_CRLF_DEFAULT;
-
-	error = git_repository_config__weakptr(&config, repo);
-	if (error < GIT_SUCCESS)
-		return error;
-
-	error = git_config_get_mapped(
-		config, "core.eol", map_eol, ARRAY_SIZE(map_eol), &repo->filter_options.eol);
-
-	if (error < GIT_SUCCESS && error != GIT_ENOTFOUND)
-		return error;
-
-	error = git_config_get_mapped(
-		config, "core.auto_crlf", map_crlf, ARRAY_SIZE(map_crlf), &repo->filter_options.auto_crlf);
-
-	if (error < GIT_SUCCESS && error != GIT_ENOTFOUND)
-		return error;
-
-	repo->filter_options.loaded = 1;
-	return 0;
-}
-
 int git_filters_load(git_vector *filters, git_repository *repo, const char *path, int mode)
 {
 	int error;
 
-	/* Make sure that the relevant settings from `gitconfig` have been
-	 * cached on the repository struct to speed things up */
-	error = load_repository_settings(repo);
-	if (error < GIT_SUCCESS)
-		return error;
-
 	if (mode == GIT_FILTER_TO_ODB) {
 		/* Load the CRLF cleanup filter when writing to the ODB */
 		error = git_filter_add__crlf_to_odb(filters, repo, path);
diff --git a/src/filter.h b/src/filter.h
index 601be18..5a77f25 100644
--- a/src/filter.h
+++ b/src/filter.h
@@ -29,29 +29,8 @@ typedef enum {
 	GIT_CRLF_INPUT,
 	GIT_CRLF_CRLF,
 	GIT_CRLF_AUTO,
-
-	GIT_SAFE_CRLF_FALSE = 0,
-	GIT_SAFE_CRLF_FAIL = 1,
-	GIT_SAFE_CRLF_WARN = 2,
-
-	GIT_AUTO_CRLF_FALSE = 0,
-	GIT_AUTO_CRLF_TRUE = 1,
-	GIT_AUTO_CRLF_INPUT = -1,
-	GIT_AUTO_CRLF_DEFAULT = GIT_AUTO_CRLF_FALSE,
 } git_crlf_t;
 
-typedef enum {
-	GIT_EOL_UNSET,
-	GIT_EOL_CRLF,
-	GIT_EOL_LF,
-#ifdef GIT_WIN32
-	GIT_EOL_NATIVE = GIT_EOL_CRLF,
-#else
-	GIT_EOL_NATIVE = GIT_EOL_LF,
-#endif
-	GIT_EOL_DEFAULT = GIT_EOL_NATIVE
-} git_eol_t;
-
 typedef struct {
 	/* NUL, CR, LF and CRLF counts */
 	unsigned int nul, cr, lf, crlf;
diff --git a/src/repository.c b/src/repository.c
index c46dd9d..1f83069 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -43,6 +43,8 @@ static void drop_config(git_repository *repo)
 		git_config_free(repo->_config);
 		repo->_config = NULL;
 	}
+
+	git_repository__cvar_cache_clear(repo);
 }
 
 static void drop_index(git_repository *repo)
@@ -111,6 +113,9 @@ static git_repository *repository_alloc(void)
 		return NULL;
 	}
 
+	/* set all the entries in the cvar cache to `unset` */
+	git_repository__cvar_cache_clear(repo);
+
 	return repo;
 }
 
diff --git a/src/repository.h b/src/repository.h
index 83f0888..b5dcc13 100644
--- a/src/repository.h
+++ b/src/repository.h
@@ -26,6 +26,49 @@
 #define GIT_DIR_MODE 0755
 #define GIT_BARE_DIR_MODE 0777
 
+/** Cvar cache identifiers */
+typedef enum {
+	GIT_CVAR_AUTO_CRLF = 0, /* core.autocrlf */
+	GIT_CVAR_EOL, /* core.eol */
+	GIT_CVAR_CACHE_MAX
+} git_cvar_cached;
+
+/**
+ * CVAR value enumerations
+ *
+ * These are the values that are actually stored in the cvar cache, instead
+ * of their string equivalents. These values are internal and symbolic;
+ * make sure that none of them is set to `-1`, since that is the unique
+ * identifier for "not cached"
+ */
+typedef enum {
+	/* The value hasn't been loaded from the cache yet */
+	GIT_CVAR_NOT_CACHED = -1,
+
+	/* core.safecrlf: false, 'fail', 'warn' */
+	GIT_SAFE_CRLF_FALSE = 0,
+	GIT_SAFE_CRLF_FAIL = 1,
+	GIT_SAFE_CRLF_WARN = 2,
+
+	/* core.autocrlf: false, true, 'input; */
+	GIT_AUTO_CRLF_FALSE = 0,
+	GIT_AUTO_CRLF_TRUE = 1,
+	GIT_AUTO_CRLF_INPUT = 2,
+	GIT_AUTO_CRLF_DEFAULT = GIT_AUTO_CRLF_FALSE,
+
+	/* core.eol: unset, 'crlf', 'lf', 'native' */
+	GIT_EOL_UNSET = 0,
+	GIT_EOL_CRLF = 1,
+	GIT_EOL_LF = 2,
+#ifdef GIT_WIN32
+	GIT_EOL_NATIVE = GIT_EOL_CRLF,
+#else
+	GIT_EOL_NATIVE = GIT_EOL_LF,
+#endif
+	GIT_EOL_DEFAULT = GIT_EOL_NATIVE
+} git_cvar_value;
+
+/** Base git object for inheritance */
 struct git_object {
 	git_cached_obj cached;
 	git_repository *repo;
@@ -47,11 +90,7 @@ struct git_repository {
 	unsigned is_bare:1;
 	unsigned int lru_counter;
 
-	struct {
-		int loaded;
-		int eol;
-		int auto_crlf;
-	} filter_options;
+	git_cvar_value cvar_cache[GIT_CVAR_CACHE_MAX];
 };
 
 /* fully free the object; internal method, do not
@@ -61,8 +100,24 @@ void git_object__free(void *object);
 int git_oid__parse(git_oid *oid, const char **buffer_out, const char *buffer_end, const char *header);
 void git_oid__writebuf(git_buf *buf, const char *header, const git_oid *oid);
 
+/*
+ * Weak pointers to repository internals.
+ *
+ * The returned pointers do not need to be freed. Do not keep
+ * permanent references to these (i.e. between API calls), since they may
+ * become invalidated if the user replaces a repository internal.
+ */
 int git_repository_config__weakptr(git_config **out, git_repository *repo);
 int git_repository_odb__weakptr(git_odb **out, git_repository *repo);
 int git_repository_index__weakptr(git_index **out, git_repository *repo);
 
+/*
+ * CVAR cache 
+ *
+ * Efficient access to the most used config variables of a repository.
+ * The cache is cleared everytime the config backend is replaced.
+ */
+int git_repository__cvar(int *out, git_repository *repo, git_cvar_cached cvar);
+void git_repository__cvar_cache_clear(git_repository *repo);
+
 #endif