summaryrefslogtreecommitdiff
path: root/src/odb.c
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2014-03-04 15:34:23 -0800
committerRussell Belfer <rb@github.com>2014-03-04 15:34:23 -0800
commitf5753999e4cac020c2dd3a4669fe9ba14df93cb5 (patch)
tree13e38551546181a59c0dae367192008c555e1fee /src/odb.c
parent0a62caf4e4927cbf74f40d8a2cb44b84267a30da (diff)
downloadlibgit2-f5753999e4cac020c2dd3a4669fe9ba14df93cb5.tar.gz
Add exists_prefix to ODB backend and ODB API
Diffstat (limited to 'src/odb.c')
-rw-r--r--src/odb.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/src/odb.c b/src/odb.c
index b413f83b4..d49ee30fd 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -635,6 +635,61 @@ int git_odb_exists(git_odb *db, const git_oid *id)
return (int)found;
}
+int git_odb_exists_prefix(
+ git_oid *out, git_odb *db, const git_oid *short_id, size_t len)
+{
+ int error = GIT_ENOTFOUND, num_found = 0;
+ size_t i;
+ git_oid last_found = {{0}}, found;
+
+ assert(db && short_id);
+
+ if (len < GIT_OID_MINPREFIXLEN)
+ return git_odb__error_ambiguous("prefix length too short");
+ if (len > GIT_OID_HEXSZ)
+ len = GIT_OID_HEXSZ;
+
+ if (len == GIT_OID_HEXSZ) {
+ if (git_odb_exists(db, short_id)) {
+ if (out)
+ git_oid_cpy(out, short_id);
+ return 0;
+ } else {
+ return git_odb__error_notfound("no match for id prefix", short_id);
+ }
+ }
+
+ for (i = 0; i < db->backends.length; ++i) {
+ backend_internal *internal = git_vector_get(&db->backends, i);
+ git_odb_backend *b = internal->backend;
+
+ if (!b->exists_prefix)
+ continue;
+
+ error = b->exists_prefix(&found, b, short_id, len);
+ if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH)
+ continue;
+ if (error)
+ return error;
+
+ /* make sure found item doesn't introduce ambiguity */
+ if (num_found) {
+ if (git_oid__cmp(&last_found, &found))
+ return git_odb__error_ambiguous("multiple matches for prefix");
+ } else {
+ git_oid_cpy(&last_found, &found);
+ num_found++;
+ }
+ }
+
+ if (!num_found)
+ return git_odb__error_notfound("no match for id prefix", short_id);
+ if (out)
+ git_oid_cpy(out, &last_found);
+
+ return error;
+}
+
int git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *db, const git_oid *id)
{
int error;