diff --git a/src/odb.c b/src/odb.c index ed600ffab..f98f9f92a 100644 --- a/src/odb.c +++ b/src/odb.c @@ -495,8 +495,10 @@ int git_odb_read_unique_short_oid(git_oid *out_oid, git_odb_object **out, git_od git_rawobj raw; int found = 0; - assert(out && db && id && len > 0); + assert(out && db && id); + if (len < GIT_OID_MINPREFIXLEN) + return git__throw(GIT_EAMBIGUOUSOIDPREFIX, "Failed to lookup object. Prefix length is lower than %d.", GIT_OID_MINPREFIXLEN); if (len > GIT_OID_HEXSZ) len = GIT_OID_HEXSZ; @@ -514,17 +516,26 @@ int git_odb_read_unique_short_oid(git_oid *out_oid, git_odb_object **out, git_od if (b->read != NULL) { error = b->read_unique_short_oid(out_oid, &raw.data, &raw.len, &raw.type, b, short_id, len); - if (error == GIT_SUCCESS) + switch (error) { + case GIT_SUCCESS: found++; + break; + case GIT_ENOTFOUND: + break; + case GIT_EAMBIGUOUSOIDPREFIX: + return git__rethrow(error, "Failed to read object. Ambiguous sha1 prefix"); + default: + return git__rethrow(error, "Failed to read object"); + } } } if (found == 1) { *out = git_cache_try_store(&db->cache, new_odb_object(out_oid, &raw)); } else if (found > 1) { - return git__rethrow(GIT_EAMBIGUOUSOIDPREFIX, "Ambiguous sha1"); + return git__throw(GIT_EAMBIGUOUSOIDPREFIX, "Failed to read object. Ambiguous sha1 prefix"); } else { - return git__rethrow(GIT_ENOTFOUND, "Failed to read object"); + return git__throw(GIT_ENOTFOUND, "Failed to read object. Object not found"); } return GIT_SUCCESS; diff --git a/src/odb_pack.c b/src/odb_pack.c index 070bde6e2..dbb772a4c 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -1011,7 +1011,7 @@ static int pack_entry_find_offset( if (pos < p->num_objects) { current = index + pos * stride; - if (git_oid_match_raw(len, short_oid->id, current)) { + if (!git_oid_match_raw(len, short_oid->id, current)) { found = 1; } } @@ -1020,7 +1020,7 @@ static int pack_entry_find_offset( /* Check for ambiguousity */ const unsigned char *next = current + stride; - if (git_oid_match_raw(len, short_oid->id, next)) { + if (!git_oid_match_raw(len, short_oid->id, next)) { found = 2; } } @@ -1465,21 +1465,32 @@ int pack_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_od 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) { - struct pack_entry e; - git_rawobj raw; - int error; + if (len < GIT_OID_MINPREFIXLEN) + return git__throw(GIT_EAMBIGUOUSOIDPREFIX, "Failed to read pack backend. Prefix length is lower than %d.", GIT_OID_MINPREFIXLEN); - if ((error = pack_entry_find_unique_short_oid(&e, (struct pack_backend *)backend, short_oid, len)) < GIT_SUCCESS) - return git__rethrow(error, "Failed to read pack backend"); + if (len >= GIT_OID_HEXSZ) { + /* We can fall back to regular read method */ + 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); - if ((error = packfile_unpack(&raw, (struct pack_backend *)backend, e.p, e.offset)) < GIT_SUCCESS) - return git__rethrow(error, "Failed to read pack backend"); + return error; + } else { + struct pack_entry e; + git_rawobj raw; + int error; - *buffer_p = raw.data; - *len_p = raw.len; - *type_p = raw.type; - git_oid_cpy(out_oid, &e.sha1); + if ((error = pack_entry_find_unique_short_oid(&e, (struct pack_backend *)backend, short_oid, len)) < GIT_SUCCESS) + return git__rethrow(error, "Failed to read pack backend"); + if ((error = packfile_unpack(&raw, (struct pack_backend *)backend, e.p, e.offset)) < GIT_SUCCESS) + return git__rethrow(error, "Failed to read pack backend"); + + *buffer_p = raw.data; + *len_p = raw.len; + *type_p = raw.type; + git_oid_cpy(out_oid, &e.sha1); + } return GIT_SUCCESS; }