Commit ecd6fdf1f70b785f24e2d17bec516ac88be0cf2c

Marc Pegon 2011-05-27T18:49:09

Added a read_unique_short_oid method to backends, to make it possible to find objects from sha1 prefixes in the future. Default implementations throw GIT_ENOTIMPLEMENTED for strict prefixes (i.e. length < GIT_OID_HEXSZ).

diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h
index ba41f72..44049b6 100644
--- a/include/git2/odb_backend.h
+++ b/include/git2/odb_backend.h
@@ -49,6 +49,19 @@ struct git_odb_backend {
 			struct git_odb_backend *,
 			const git_oid *);
 
+	/* To find a unique object given a prefix
+	 * of its oid.
+	 * The oid given must be so that the
+	 * remaining (GIT_OID_HEXSZ - len)*4 bits
+	 * are 0s.
+	 */
+	int (* read_unique_short_oid)(
+			git_oid *,
+			void **, size_t *, git_otype *,
+			struct git_odb_backend *,
+			const git_oid *,
+			unsigned int len);
+
 	int (* read_header)(
 			size_t *, git_otype *,
 			struct git_odb_backend *,
diff --git a/src/backends/hiredis.c b/src/backends/hiredis.c
index f0c5da2..739e3bb 100644
--- a/src/backends/hiredis.c
+++ b/src/backends/hiredis.c
@@ -107,6 +107,21 @@ int hiredis_backend__read(void **data_p, size_t *len_p, git_otype *type_p, git_o
     return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to read backend");
 }
 
+int hiredis_backend__read_unique_short_oid(git_oid *out_oid, void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend,
+					const git_oid *short_oid, unsigned int len) {
+	if (len >= GIT_OID_HEXSZ) {
+		/* Just match the full identifier */
+		int error = hiredis_backend__read(data_p, len_p, type_p, backend, short_oid);
+		if (error == GIT_SUCCESS)
+			git_oid_cpy(out_oid, short_oid);
+
+		return error;
+	} else if (len < GIT_OID_HEXSZ) {
+		/* TODO */
+		return git__throw(GIT_ENOTIMPLEMENTED, "Hiredis backend cannot search objects from short oid");
+	}
+}
+
 int hiredis_backend__exists(git_odb_backend *_backend, const git_oid *oid) {
     hiredis_backend *backend;
     int found;
@@ -174,6 +189,7 @@ int git_odb_backend_hiredis(git_odb_backend **backend_out, const char *host, int
         goto cleanup;
 
     backend->parent.read = &hiredis_backend__read;
+    backend->parent.read_unique_short_oid = &hiredis_backend__read_unique_short_oid;
     backend->parent.read_header = &hiredis_backend__read_header;
     backend->parent.write = &hiredis_backend__write;
     backend->parent.exists = &hiredis_backend__exists;
diff --git a/src/backends/sqlite.c b/src/backends/sqlite.c
index abf14f1..c9c3b80 100644
--- a/src/backends/sqlite.c
+++ b/src/backends/sqlite.c
@@ -103,6 +103,21 @@ int sqlite_backend__read(void **data_p, size_t *len_p, git_otype *type_p, git_od
 	return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "SQLite backend: Failed to read");
 }
 
+int sqlite_backend__read_unique_short_oid(git_oid *out_oid, void **data_p, size_t *len_p, git_otype *type_p, git_odb_backend *_backend,
+					const git_oid *short_oid, unsigned int len) {
+	if (len >= GIT_OID_HEXSZ) {
+		/* Just match the full identifier */
+		int error = sqlite_backend__read(data_p, len_p, type_p, _backend, short_oid);
+		if (error == GIT_SUCCESS)
+			git_oid_cpy(out_oid, short_oid);
+
+		return error;
+	} else if (len < GIT_OID_HEXSZ) {
+		/* TODO */
+		return git__throw(GIT_ENOTIMPLEMENTED, "Sqlite backend cannot search objects from short oid");
+	}
+}
+
 int sqlite_backend__exists(git_odb_backend *_backend, const git_oid *oid)
 {
 	sqlite_backend *backend;
@@ -255,6 +270,7 @@ int git_odb_backend_sqlite(git_odb_backend **backend_out, const char *sqlite_db)
 		goto cleanup;
 
 	backend->parent.read = &sqlite_backend__read;
+	backend->parent.read_unique_short_oid = &sqlite_backend__read_unique_short_oid;
 	backend->parent.read_header = &sqlite_backend__read_header;
 	backend->parent.write = &sqlite_backend__write;
 	backend->parent.exists = &sqlite_backend__exists;
diff --git a/src/odb_loose.c b/src/odb_loose.c
index 9fb86f8..41b7f0b 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -524,6 +524,20 @@ int loose_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_o
 	return GIT_SUCCESS;
 }
 
+int loose_backend__read_unique_short_oid(git_oid *out_oid, void **buffer_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend,
+					const git_oid *short_oid, unsigned int len)
+{
+	if (len >= GIT_OID_HEXSZ) {
+		int error = loose_backend__read(buffer_p, len_p, type_p, backend, short_oid);
+		if (error == GIT_SUCCESS)
+			git_oid_cpy(out_oid, short_oid);
+
+		return error;
+	} else if (len < GIT_OID_HEXSZ) {
+		return git__throw(GIT_ENOTIMPLEMENTED, "Loose backend cannot search objects from short oid");
+	}
+}
+
 int loose_backend__exists(git_odb_backend *backend, const git_oid *oid)
 {
 	char object_path[GIT_PATH_MAX];
@@ -663,6 +677,7 @@ int git_odb_backend_loose(git_odb_backend **backend_out, const char *objects_dir
 	backend->fsync_object_files = 0;
 
 	backend->parent.read = &loose_backend__read;
+	backend->parent.read_unique_short_oid = &loose_backend__read_unique_short_oid;
 	backend->parent.read_header = &loose_backend__read_header;
 	backend->parent.writestream = &loose_backend__stream;
 	backend->parent.exists = &loose_backend__exists;
diff --git a/src/odb_pack.c b/src/odb_pack.c
index 574fbc6..3125a8c 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -1364,6 +1364,20 @@ int pack_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_od
 	return GIT_SUCCESS;
 }
 
+int pack_backend__read_unique_short_oid(git_oid *out_oid, void **buffer_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend,
+					const git_oid *short_oid, unsigned int len)
+{
+	if (len >= GIT_OID_HEXSZ) {
+		int error = pack_backend__read(buffer_p, len_p, type_p, backend, short_oid);
+		if (error == GIT_SUCCESS)
+			git_oid_cpy(out_oid, short_oid);
+
+		return error;
+	} else if (len < GIT_OID_HEXSZ) {
+		return git__throw(GIT_ENOTIMPLEMENTED, "Pack backend cannot search objects from short oid");
+	}
+}
+
 int pack_backend__exists(git_odb_backend *backend, const git_oid *oid)
 {
 	struct pack_entry e;
@@ -1418,6 +1432,7 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
 	}
 
 	backend->parent.read = &pack_backend__read;
+	backend->parent.read_unique_short_oid = &pack_backend__read_unique_short_oid;
 	backend->parent.read_header = NULL;
 	backend->parent.exists = &pack_backend__exists;
 	backend->parent.free = &pack_backend__free;