Commit 81662d432c585df651a9f733670ac577f6b555a5

Josh Triplett 2021-11-08T14:48:45

Support checking for object existence without refresh Looking up a non-existent object currently always invokes `git_odb_refresh`. If looking up a large batch of objects, many of which may legitimately not exist, this will repeatedly refresh the ODB to no avail. Add a `git_odb_exists_ext` that accepts flags controlling the ODB lookup, and add a flag to suppress the refresh. This allows the user to control if and when they refresh (for instance, refreshing once before starting the batch).

diff --git a/include/git2/odb.h b/include/git2/odb.h
index dd48455..6c86cd6 100644
--- a/include/git2/odb.h
+++ b/include/git2/odb.h
@@ -22,6 +22,17 @@
  */
 GIT_BEGIN_DECL
 
+/** Flags controlling the behavior of ODB lookup operations */
+typedef enum {
+	/**
+	 * Don't call `git_odb_refresh` if the lookup fails. Useful when doing
+	 * a batch of lookup operations for objects that may legitimately not
+	 * exist. When using this flag, you may wish to manually call
+	 * `git_odb_refresh` before processing a batch of objects.
+	 */
+	GIT_ODB_LOOKUP_NO_REFRESH = (1 << 0),
+} git_odb_lookup_flags_t;
+
 /**
  * Function type for callbacks from git_odb_foreach.
  */
@@ -156,6 +167,17 @@ GIT_EXTERN(int) git_odb_read_header(size_t *len_out, git_object_t *type_out, git
 GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id);
 
 /**
+ * Determine if the given object can be found in the object database, with
+ * extended options.
+ *
+ * @param db database to be searched for the given object.
+ * @param id the object to search for.
+ * @param flags flags affecting the lookup (see `git_odb_lookup_flags_t`)
+ * @return 1 if the object was found, 0 otherwise
+ */
+GIT_EXTERN(int) git_odb_exists_ext(git_odb *db, const git_oid *id, unsigned int flags);
+
+/**
  * Determine if an object can be found in the object database by an
  * abbreviated object ID.
  *
diff --git a/src/odb.c b/src/odb.c
index 7bf5754..7932867 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -883,6 +883,11 @@ int git_odb__freshen(git_odb *db, const git_oid *id)
 
 int git_odb_exists(git_odb *db, const git_oid *id)
 {
+    return git_odb_exists_ext(db, id, 0);
+}
+
+int git_odb_exists_ext(git_odb *db, const git_oid *id, unsigned int flags)
+{
 	git_odb_object *object;
 
 	GIT_ASSERT_ARG(db);
@@ -899,7 +904,7 @@ int git_odb_exists(git_odb *db, const git_oid *id)
 	if (odb_exists_1(db, id, false))
 		return 1;
 
-	if (!git_odb_refresh(db))
+	if (!(flags & GIT_ODB_LOOKUP_NO_REFRESH) && !git_odb_refresh(db))
 		return odb_exists_1(db, id, true);
 
 	/* Failed to refresh, hence not found */