summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVicent Marti <vicent@github.com>2016-03-08 21:17:38 +0100
committerVicent Marti <vicent@github.com>2016-03-08 21:17:38 +0100
commitc68044a8797d6eac5c8468dd5bec53d07b3ad66c (patch)
tree885a445b9dd85346107adc5b1325d368f6a5581b /src
parentb7809b84692b4df7f11d603cc5da0860609e0555 (diff)
parent62484f52d1d4dbbfd83a11f54a3a742c75de5032 (diff)
downloadlibgit2-c68044a8797d6eac5c8468dd5bec53d07b3ad66c.tar.gz
Merge pull request #3656 from ethomson/exists_prefixes
Introduce `git_odb_expand_ids`
Diffstat (limited to 'src')
-rw-r--r--src/odb.c90
-rw-r--r--src/odb.h3
-rw-r--r--src/odb_loose.c20
-rw-r--r--src/odb_pack.c8
-rw-r--r--src/oid.h9
-rw-r--r--src/pack.c10
6 files changed, 104 insertions, 36 deletions
diff --git a/src/odb.c b/src/odb.c
index 1c877c9fc..90336c082 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -18,6 +18,7 @@
#include "git2/odb_backend.h"
#include "git2/oid.h"
+#include "git2/oidarray.h"
#define GIT_ALTERNATES_FILE "info/alternates"
@@ -651,7 +652,7 @@ int git_odb_exists(git_odb *db, const git_oid *id)
if ((object = git_cache_get_raw(odb_cache(db), id)) != NULL) {
git_odb_object_free(object);
- return (int)true;
+ return 1;
}
if (odb_exists_1(db, id, false))
@@ -716,23 +717,19 @@ int git_odb_exists_prefix(
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 (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);
+ return git_odb__error_notfound(
+ "no match for id prefix", short_id, len);
}
}
- /* just copy valid part of short_id */
- memcpy(&key.id, short_id->id, (len + 1) / 2);
- if (len & 1)
- key.id[len / 2] &= 0xF0;
+ git_oid__cpy_prefix(&key, short_id, len);
error = odb_exists_prefix_1(out, db, &key, len, false);
@@ -740,7 +737,63 @@ int git_odb_exists_prefix(
error = odb_exists_prefix_1(out, db, &key, len, true);
if (error == GIT_ENOTFOUND)
- return git_odb__error_notfound("no match for id prefix", &key);
+ return git_odb__error_notfound("no match for id prefix", &key, len);
+
+ return error;
+}
+
+int git_odb_expand_ids(
+ git_odb *db,
+ git_odb_expand_id *ids,
+ size_t count)
+{
+ size_t len, i;
+ int error;
+
+ assert(db && ids);
+
+ for (i = 0; i < count; i++) {
+ git_odb_expand_id *query = &ids[i];
+ git_oid *actual_id = NULL, tmp;
+ git_otype query_type = (query->type == GIT_OBJ_ANY) ? 0 : query->type;
+ git_otype actual_type = 0;
+
+ /* if we were given a full object ID, simply look it up */
+ if (query->length >= GIT_OID_HEXSZ) {
+ error = git_odb_read_header(&len, &actual_type, db, &query->id);
+ }
+
+ /* otherwise, resolve the short id to full, then (optionally)
+ * read the header.
+ */
+ else if (query->length >= GIT_OID_MINPREFIXLEN) {
+ error = odb_exists_prefix_1(&tmp,
+ db, &query->id, query->length, false);
+
+ if (!error) {
+ actual_id = &tmp;
+ error = git_odb_read_header(&len, &actual_type, db, &tmp);
+ }
+ }
+
+ if (error < 0 && error != GIT_ENOTFOUND && error != GIT_EAMBIGUOUS)
+ break;
+
+ if (error == 0 && (query_type == actual_type || !query_type)) {
+ if (actual_id)
+ git_oid_cpy(&query->id, actual_id);
+
+ query->length = GIT_OID_HEXSZ;
+ query->type = actual_type;
+ } else {
+ memset(&query->id, 0, sizeof(git_oid));
+ query->length = 0;
+ query->type = 0;
+ }
+ }
+
+ if (!error)
+ giterr_clear();
return error;
}
@@ -881,7 +934,7 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
error = odb_read_1(out, db, id, true);
if (error == GIT_ENOTFOUND)
- return git_odb__error_notfound("no match for id", id);
+ return git_odb__error_notfound("no match for id", id, GIT_OID_HEXSZ);
return error;
}
@@ -956,10 +1009,7 @@ int git_odb_read_prefix(
return 0;
}
- /* just copy valid part of short_id */
- memcpy(&key.id, short_id->id, (len + 1) / 2);
- if (len & 1)
- key.id[len / 2] &= 0xF0;
+ git_oid__cpy_prefix(&key, short_id, len);
error = read_prefix_1(out, db, &key, len, false);
@@ -967,7 +1017,7 @@ int git_odb_read_prefix(
error = read_prefix_1(out, db, &key, len, true);
if (error == GIT_ENOTFOUND)
- return git_odb__error_notfound("no match for prefix", &key);
+ return git_odb__error_notfound("no match for prefix", &key, len);
return error;
}
@@ -1223,12 +1273,14 @@ int git_odb_refresh(struct git_odb *db)
return 0;
}
-int git_odb__error_notfound(const char *message, const git_oid *oid)
+int git_odb__error_notfound(
+ const char *message, const git_oid *oid, size_t oid_len)
{
if (oid != NULL) {
char oid_str[GIT_OID_HEXSZ + 1];
- git_oid_tostr(oid_str, sizeof(oid_str), oid);
- giterr_set(GITERR_ODB, "Object not found - %s (%s)", message, oid_str);
+ git_oid_tostr(oid_str, oid_len, oid);
+ giterr_set(GITERR_ODB, "Object not found - %s (%.*s)",
+ message, oid_len, oid_str);
} else
giterr_set(GITERR_ODB, "Object not found - %s", message);
diff --git a/src/odb.h b/src/odb.h
index 281bd3a4d..31a9fd1b9 100644
--- a/src/odb.h
+++ b/src/odb.h
@@ -82,7 +82,8 @@ int git_odb__hashlink(git_oid *out, const char *path);
/*
* Generate a GIT_ENOTFOUND error for the ODB.
*/
-int git_odb__error_notfound(const char *message, const git_oid *oid);
+int git_odb__error_notfound(
+ const char *message, const git_oid *oid, size_t oid_len);
/*
* Generate a GIT_EAMBIGUOUS error for the ODB.
diff --git a/src/odb_loose.c b/src/odb_loose.c
index 730c4b1e1..9d9bffd21 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -547,7 +547,8 @@ static int locate_object_short_oid(
/* Check that directory exists */
if (git_path_isdir(object_location->ptr) == false)
- return git_odb__error_notfound("no matching loose object for prefix", short_oid);
+ return git_odb__error_notfound("no matching loose object for prefix",
+ short_oid, len);
state.dir_len = git_buf_len(object_location);
state.short_oid_len = len;
@@ -560,7 +561,8 @@ static int locate_object_short_oid(
return error;
if (!state.found)
- return git_odb__error_notfound("no matching loose object for prefix", short_oid);
+ return git_odb__error_notfound("no matching loose object for prefix",
+ short_oid, len);
if (state.found > 1)
return git_odb__error_ambiguous("multiple matches in loose objects");
@@ -613,9 +615,10 @@ static int loose_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_
raw.len = 0;
raw.type = GIT_OBJ_BAD;
- if (locate_object(&object_path, (loose_backend *)backend, oid) < 0)
- error = git_odb__error_notfound("no matching loose object", oid);
- else if ((error = read_header_loose(&raw, &object_path)) == 0) {
+ if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) {
+ error = git_odb__error_notfound("no matching loose object",
+ oid, GIT_OID_HEXSZ);
+ } else if ((error = read_header_loose(&raw, &object_path)) == 0) {
*len_p = raw.len;
*type_p = raw.type;
}
@@ -633,9 +636,10 @@ static int loose_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p
assert(backend && oid);
- if (locate_object(&object_path, (loose_backend *)backend, oid) < 0)
- error = git_odb__error_notfound("no matching loose object", oid);
- else if ((error = read_loose(&raw, &object_path)) == 0) {
+ if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) {
+ error = git_odb__error_notfound("no matching loose object",
+ oid, GIT_OID_HEXSZ);
+ } else if ((error = read_loose(&raw, &object_path)) == 0) {
*buffer_p = raw.data;
*len_p = raw.len;
*type_p = raw.type;
diff --git a/src/odb_pack.c b/src/odb_pack.c
index 77d2c75b9..5a57864ad 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -264,7 +264,8 @@ static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backen
if (!pack_entry_find_inner(e, backend, oid, last_found))
return 0;
- return git_odb__error_notfound("failed to find pack entry", oid);
+ return git_odb__error_notfound(
+ "failed to find pack entry", oid, GIT_OID_HEXSZ);
}
static int pack_entry_find_prefix(
@@ -309,7 +310,8 @@ static int pack_entry_find_prefix(
}
if (!found)
- return git_odb__error_notfound("no matching pack entry for prefix", short_oid);
+ return git_odb__error_notfound("no matching pack entry for prefix",
+ short_oid, len);
else
return 0;
}
@@ -333,7 +335,7 @@ static int pack_backend__refresh(git_odb_backend *backend_)
return 0;
if (p_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode))
- return git_odb__error_notfound("failed to refresh packfiles", NULL);
+ return git_odb__error_notfound("failed to refresh packfiles", NULL, 0);
git_buf_sets(&path, backend->pack_folder);
diff --git a/src/oid.h b/src/oid.h
index aa1f0bfdc..922a2a347 100644
--- a/src/oid.h
+++ b/src/oid.h
@@ -44,4 +44,13 @@ GIT_INLINE(int) git_oid__cmp(const git_oid *a, const git_oid *b)
return git_oid__hashcmp(a->id, b->id);
}
+GIT_INLINE(void) git_oid__cpy_prefix(
+ git_oid *out, const git_oid *id, size_t len)
+{
+ memcpy(&out->id, id->id, (len + 1) / 2);
+
+ if (len & 1)
+ out->id[len / 2] &= 0xF0;
+}
+
#endif
diff --git a/src/pack.c b/src/pack.c
index 52c652178..e8bde71f3 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -1018,7 +1018,7 @@ static int packfile_open(struct git_pack_file *p)
unsigned char *idx_sha1;
if (p->index_version == -1 && pack_index_open(p) < 0)
- return git_odb__error_notfound("failed to open packfile", NULL);
+ return git_odb__error_notfound("failed to open packfile", NULL, 0);
/* if mwf opened by another thread, return now */
if (git_mutex_lock(&p->lock) < 0)
@@ -1099,7 +1099,7 @@ int git_packfile__name(char **out, const char *path)
path_len = strlen(path);
if (path_len < strlen(".idx"))
- return git_odb__error_notfound("invalid packfile path", NULL);
+ return git_odb__error_notfound("invalid packfile path", NULL, 0);
if (git_buf_printf(&buf, "%.*s.pack", (int)(path_len - strlen(".idx")), path) < 0)
return -1;
@@ -1117,7 +1117,7 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
*pack_out = NULL;
if (path_len < strlen(".idx"))
- return git_odb__error_notfound("invalid packfile path", NULL);
+ return git_odb__error_notfound("invalid packfile path", NULL, 0);
GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(*p), path_len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
@@ -1143,7 +1143,7 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
if (p_stat(p->pack_name, &st) < 0 || !S_ISREG(st.st_mode)) {
git__free(p);
- return git_odb__error_notfound("packfile not found", NULL);
+ return git_odb__error_notfound("packfile not found", NULL, 0);
}
/* ok, it looks sane as far as we can check without
@@ -1344,7 +1344,7 @@ static int pack_entry_find_offset(
}
if (!found)
- return git_odb__error_notfound("failed to find offset for pack entry", short_oid);
+ return git_odb__error_notfound("failed to find offset for pack entry", short_oid, len);
if (found > 1)
return git_odb__error_ambiguous("found multiple offsets for pack entry");