Commit b12b72ea82776bbbd4296eeac1376055b0487edf

Russell Belfer 2013-04-12T12:44:51

Add range checking around cache opts Add a git_cache_set_max_object_size method that does more checking around setting the max object size. Also add a git_cache_size to read the number of objects currently in the cache. This makes it easier to write tests.

diff --git a/src/cache.c b/src/cache.c
index f8cddea..263f736 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -19,17 +19,28 @@ GIT__USE_OIDMAP
 
 bool git_cache__enabled = true;
 
-size_t git_cache__max_object_size[8] = {
-	0, /* GIT_OBJ__EXT1 */
+static size_t git_cache__max_object_size[8] = {
+	0,     /* GIT_OBJ__EXT1 */
 	4096,  /* GIT_OBJ_COMMIT */
 	4096,  /* GIT_OBJ_TREE */
-	0, /* GIT_OBJ_BLOB */
+	0,     /* GIT_OBJ_BLOB */
 	4096,  /* GIT_OBJ_TAG */
-	0, /* GIT_OBJ__EXT2 */
-	0, /* GIT_OBJ_OFS_DELTA */
-	0 /* GIT_OBJ_REF_DELTA */
+	0,     /* GIT_OBJ__EXT2 */
+	0,     /* GIT_OBJ_OFS_DELTA */
+	0      /* GIT_OBJ_REF_DELTA */
 };
 
+int git_cache_set_max_object_size(git_otype type, size_t size)
+{
+	if (type < 0 || (size_t)type >= ARRAY_SIZE(git_cache__max_object_size)) {
+		giterr_set(GITERR_INVALID, "type out of range");
+		return -1;
+	}
+
+	git_cache__max_object_size[type] = size;
+	return 0;
+}
+
 void git_cache_dump_stats(git_cache *cache)
 {
 	git_cached_obj *object;
diff --git a/src/cache.h b/src/cache.h
index 8b2aa1f..13b630e 100644
--- a/src/cache.h
+++ b/src/cache.h
@@ -20,9 +20,6 @@ enum {
 	GIT_CACHE_STORE_PARSED = 2
 };
 
-extern bool git_cache__enabled;
-extern size_t git_cache__max_object_size[8];
-
 typedef struct {
 	git_oid oid;
 	int16_t type;
@@ -37,6 +34,10 @@ typedef struct {
 	size_t used_memory;
 } git_cache;
 
+extern bool git_cache__enabled;
+
+int git_cache_set_max_object_size(git_otype type, size_t size);
+
 int git_cache_init(git_cache *cache);
 void git_cache_free(git_cache *cache);
 
@@ -47,6 +48,11 @@ git_odb_object *git_cache_get_raw(git_cache *cache, const git_oid *oid);
 git_object *git_cache_get_parsed(git_cache *cache, const git_oid *oid);
 void *git_cache_get_any(git_cache *cache, const git_oid *oid);
 
+GIT_INLINE(size_t) git_cache_size(git_cache *cache)
+{
+	return (size_t)kh_size(cache->map);
+}
+
 GIT_INLINE(void) git_cached_obj_incref(void *_obj)
 {
 	git_cached_obj *obj = _obj;
diff --git a/src/util.c b/src/util.c
index 0b5fbdc..1ed5d5d 100644
--- a/src/util.c
+++ b/src/util.c
@@ -95,14 +95,16 @@ int git_libgit2_opts(int key, ...)
 			error = git_futils_dirs_set(error, va_arg(ap, const char *));
 		break;
 
-	case GIT_OPT_SET_CACHE_LIMIT: {
+	case GIT_OPT_SET_CACHE_LIMIT:
+		{
 			git_otype type = (git_otype)va_arg(ap, int);
-			git_cache__max_object_size[type] = va_arg(ap, size_t);
+			size_t size = va_arg(ap, size_t);
+			error = git_cache_set_max_object_size(type, size);
 			break;
 		}
 
 	case GIT_OPT_ENABLE_CACHING:
-		git_cache__enabled = va_arg(ap, int);
+		git_cache__enabled = (va_arg(ap, int) != 0);
 		break;
 	}