Commit 82324ac1a5ec79069877ed5d807c87762a16ed9d

Ramsay Jones 2009-02-10T21:49:48

Add the git_odb_exists() object query function This function determines if the given object can be found in the object database. At present, only the local object database is searched. Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>

diff --git a/src/git/odb.h b/src/git/odb.h
index 0a7ee40..8a8cd3e 100644
--- a/src/git/odb.h
+++ b/src/git/odb.h
@@ -152,6 +152,17 @@ GIT_EXTERN(int) git_obj__loose_object_type(git_otype type);
  */
 GIT_EXTERN(int) git_obj_hash(git_oid *id, git_obj *obj);
 
+/**
+ * Determine if the given object can be found in the object database.
+ *
+ * @param db database to be searched for the given object.
+ * @param id the object to search for.
+ * @return
+ * - true, if the object was found
+ * - false, otherwise
+ */
+GIT_EXTERN(int) git_odb_exists(git_odb *db, const git_oid *id);
+
 /** @} */
 GIT_END_DECL
 #endif
diff --git a/src/odb.c b/src/odb.c
index fc58168..f34fd00 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -819,6 +819,66 @@ static git_packlist *packlist_get(git_odb *db)
 	return pl;
 }
 
+static int search_packs(git_pack **p, off_t *offset, git_odb *db, const git_oid *id)
+{
+	git_packlist *pl = packlist_get(db);
+	size_t j;
+
+	if (!pl)
+		return GIT_ENOTFOUND;
+
+	for (j = 0; j < pl->n_packs; j++) {
+
+		git_pack *pack = pl->packs[j];
+		off_t pos;
+		int res;
+
+		if (pack_openidx(pack))
+			continue;
+		res = pack->idx_search(&pos, pack, id);
+		pack_decidx(pack);
+
+		if (!res) {
+			packlist_dec(db,pl);
+			if (p)
+				*p = pack;
+			if (offset)
+				*offset = pos;
+			return GIT_SUCCESS;
+		}
+
+	}
+
+	packlist_dec(db,pl);
+	return GIT_ENOTFOUND;
+}
+
+static int exists_packed(git_odb *db, const git_oid *id)
+{
+	return !search_packs(NULL, NULL, db, id);
+}
+
+static int exists_loose(git_odb *db, const git_oid *id)
+{
+	char file[GIT_PATH_MAX];
+
+	if (object_file_name(file, sizeof(file), db->objects_dir, id) < 0)
+		return 0;
+
+	if (gitfo_exists(file) < 0)
+		return 0;
+
+	return 1;
+}
+
+int git_odb_exists(git_odb *db, const git_oid *id)
+{
+	/* TODO: extend to search alternate db's */
+	if (exists_packed(db, id))
+		return 1;
+	return exists_loose(db, id);
+}
+
 int git_odb_open(git_odb **out, const char *objects_dir)
 {
 	git_odb *db = git__calloc(1, sizeof(*db));