Commit 6c8ca697becd0cc8cc867f34f571b51247b142d7

Marc Pegon 2011-05-29T17:57:25

Fixed some error messages related to searching objects from a short oid. Fixed forgot to check that prefix length is greater than minimum prefix length in read_unique_short_oid method from pack backend.

diff --git a/src/odb.c b/src/odb.c
index ed600ff..f98f9f9 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 070bde6..dbb772a 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;
 }