Commit cd460522c516f18a12549626a356960370e3bcc7

Tony De La Nuez 2020-04-20T22:16:52

odb: Implement option for overriding of default odb backend priority Introduce GIT_OPT_SET_ODB_LOOSE_PRIORITY and GIT_OPT_SET_ODB_PACKED_PRIORITY to allow overriding the default priority values for the default ODB backends. Libgit2 has historically assumed that most objects for long- running operations will be packed, therefore GIT_LOOSE_PRIORITY is set to 1 by default, and GIT_PACKED_PRIORITY to 2. When a client allows libgit2 to set the default backends, they can specify an override for the two priority values in order to change the order in which each ODB backend is accessed.

diff --git a/include/git2/common.h b/include/git2/common.h
index dee260e..4402dfd 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -207,7 +207,9 @@ typedef enum {
 	GIT_OPT_DISABLE_PACK_KEEP_FILE_CHECKS,
 	GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE,
 	GIT_OPT_GET_MWINDOW_FILE_LIMIT,
-	GIT_OPT_SET_MWINDOW_FILE_LIMIT
+	GIT_OPT_SET_MWINDOW_FILE_LIMIT,
+	GIT_OPT_SET_ODB_PACKED_PRIORITY,
+	GIT_OPT_SET_ODB_LOOSE_PRIORITY
 } git_libgit2_opt_t;
 
 /**
@@ -421,6 +423,14 @@ typedef enum {
  *		> authentication, use expect/continue when POSTing data.
  *		> This option is not available on Windows.
  *
+ *   opts(GIT_OPT_SET_ODB_PACKED_PRIORITY, int priority)
+ *      > Override the default priority of the packed ODB backend which
+ *      > is added when default backends are assigned to a repository
+ *
+ *   opts(GIT_OPT_SET_ODB_LOOSE_PRIORITY, int priority)
+ *      > Override the default priority of the loose ODB backend which
+ *      > is added when default backends are assigned to a repository
+ *
  * @param option Option key
  * @param ... value to set the option
  * @return 0 on success, <0 on failure
diff --git a/src/libgit2.c b/src/libgit2.c
index f27c999..089c835 100644
--- a/src/libgit2.c
+++ b/src/libgit2.c
@@ -50,6 +50,8 @@ extern size_t git_mwindow__mapped_limit;
 extern size_t git_mwindow__file_limit;
 extern size_t git_indexer__max_objects;
 extern bool git_disable_pack_keep_file_checks;
+extern int git_odb__packed_priority;
+extern int git_odb__loose_priority;
 
 char *git__user_agent;
 char *git__ssl_ciphers;
@@ -368,6 +370,14 @@ int git_libgit2_opts(int key, ...)
 		git_http__expect_continue = (va_arg(ap, int) != 0);
 		break;
 
+	case GIT_OPT_SET_ODB_PACKED_PRIORITY:
+		git_odb__packed_priority = va_arg(ap, int);
+		break;
+
+	case GIT_OPT_SET_ODB_LOOSE_PRIORITY:
+		git_odb__loose_priority = va_arg(ap, int);
+		break;
+
 	default:
 		git_error_set(GIT_ERROR_INVALID, "invalid option key");
 		error = -1;
diff --git a/src/odb.c b/src/odb.c
index 05bdaf6..35e2259 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -23,14 +23,14 @@
 
 #define GIT_ALTERNATES_FILE "info/alternates"
 
+#define GIT_ALTERNATES_MAX_DEPTH 5
+
 /*
  * We work under the assumption that most objects for long-running
  * operations will be packed
  */
-#define GIT_LOOSE_PRIORITY 1
-#define GIT_PACKED_PRIORITY 2
-
-#define GIT_ALTERNATES_MAX_DEPTH 5
+int git_odb__loose_priority = 1;
+int git_odb__packed_priority = 2;
 
 bool git_odb__strict_hash_verification = true;
 
@@ -613,12 +613,12 @@ int git_odb__add_default_backends(
 
 	/* add the loose object backend */
 	if (git_odb_backend_loose(&loose, objects_dir, -1, db->do_fsync, 0, 0) < 0 ||
-		add_backend_internal(db, loose, GIT_LOOSE_PRIORITY, as_alternates, inode) < 0)
+		add_backend_internal(db, loose, git_odb__loose_priority, as_alternates, inode) < 0)
 		return -1;
 
 	/* add the packed file backend */
 	if (git_odb_backend_pack(&packed, objects_dir) < 0 ||
-		add_backend_internal(db, packed, GIT_PACKED_PRIORITY, as_alternates, inode) < 0)
+		add_backend_internal(db, packed, git_odb__packed_priority, as_alternates, inode) < 0)
 		return -1;
 
 	if (git_mutex_lock(&db->lock) < 0) {
diff --git a/tests/odb/sorting.c b/tests/odb/sorting.c
index 6af8b0d..dc87a85 100644
--- a/tests/odb/sorting.c
+++ b/tests/odb/sorting.c
@@ -68,3 +68,26 @@ void test_odb_sorting__alternate_backends_sorting(void)
 
 	check_backend_sorting(_odb);
 }
+
+void test_odb_sorting__override_default_backend_priority(void)
+{
+	git_odb *new_odb;
+	git_odb_backend *loose, *packed, *backend;
+	cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ODB_LOOSE_PRIORITY, 5));
+	cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ODB_PACKED_PRIORITY, 3));
+	git_odb_backend_pack(&packed, "./testrepo.git/objects");
+	git_odb_backend_loose(&loose, "./testrepo.git/objects", -1, 0, 0, 0);
+
+	cl_git_pass(git_odb_open(&new_odb, cl_fixture("testrepo.git/objects")));
+	cl_assert_equal_sz(2, git_odb_num_backends(new_odb));
+
+	cl_git_pass(git_odb_get_backend(&backend, new_odb, 0));
+	cl_assert_equal_p(loose->read, backend->read);
+
+	cl_git_pass(git_odb_get_backend(&backend, new_odb, 1));
+	cl_assert_equal_p(packed->read, backend->read);
+
+	git_odb_free(new_odb);
+	loose->free(loose);
+	packed->free(packed);
+}