Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/odb.c
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2013-01-03 23:36:26 +0400
committerVicent Marti <tanoku@gmail.com>2013-01-10 18:34:56 +0400
commit4a863c06662053a8530a0dcb24e0a2daa33e05cf (patch)
tree7cf411ca542687c7bda92d17809be88efd28a2e7 /src/odb.c
parenta22ad9fd1f1f938fb9b8ac77939dda8a3b81a00e (diff)
Sane refresh logic
All the ODB backends have a specific refresh interface. When reading an object, first we attempt every single backend: if the read fails, then we refresh all the backends and retry the read one more time to see if the object has appeared.
Diffstat (limited to 'src/odb.c')
-rw-r--r--src/odb.c55
1 files changed, 49 insertions, 6 deletions
diff --git a/src/odb.c b/src/odb.c
index 216715afa..d0b23230c 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -609,14 +609,22 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
{
unsigned int i;
int error = GIT_ENOTFOUND;
+ bool refreshed = false;
git_rawobj raw;
assert(out && db && id);
+ if (db->backends.length == 0) {
+ giterr_set(GITERR_ODB, "Failed to lookup object: no backends loaded");
+ return GIT_ENOTFOUND;
+ }
+
*out = git_cache_get(&db->cache, id);
if (*out != NULL)
return 0;
+attempt_lookup:
+
for (i = 0; i < db->backends.length && error < 0; ++i) {
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *b = internal->backend;
@@ -625,9 +633,13 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
error = b->read(&raw.data, &raw.len, &raw.type, b, id);
}
- /* TODO: If no backends are configured, this returns GIT_ENOTFOUND but
- * will never have called giterr_set().
- */
+ if (error == GIT_ENOTFOUND && !refreshed) {
+ if ((error = git_odb_refresh(db)) < 0)
+ return error;
+
+ refreshed = true;
+ goto attempt_lookup;
+ }
if (error && error != GIT_PASSTHROUGH)
return error;
@@ -644,7 +656,7 @@ int git_odb_read_prefix(
git_oid found_full_oid = {{0}};
git_rawobj raw;
void *data = NULL;
- bool found = false;
+ bool found = false, refreshed = false;
assert(out && db);
@@ -660,11 +672,13 @@ int git_odb_read_prefix(
return 0;
}
+attempt_lookup:
+
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->read != NULL) {
+ if (b->read_prefix != NULL) {
git_oid full_oid;
error = b->read_prefix(&full_oid, &raw.data, &raw.len, &raw.type, b, short_id, len);
if (error == GIT_ENOTFOUND || error == GIT_PASSTHROUGH)
@@ -675,13 +689,23 @@ int git_odb_read_prefix(
git__free(data);
data = raw.data;
+
if (found && git_oid_cmp(&full_oid, &found_full_oid))
return git_odb__error_ambiguous("multiple matches for prefix");
+
found_full_oid = full_oid;
found = true;
}
}
+ if (!found && !refreshed) {
+ if ((error = git_odb_refresh(db)) < 0)
+ return error;
+
+ refreshed = true;
+ goto attempt_lookup;
+ }
+
if (!found)
return git_odb__error_notfound("no match for prefix", short_id);
@@ -820,12 +844,31 @@ int git_odb_write_pack(struct git_odb_writepack **out, git_odb *db, git_transfer
return error;
}
-void * git_odb_backend_malloc(git_odb_backend *backend, size_t len)
+void *git_odb_backend_malloc(git_odb_backend *backend, size_t len)
{
GIT_UNUSED(backend);
return git__malloc(len);
}
+int git_odb_refresh(struct git_odb *db)
+{
+ unsigned int i;
+ assert(db);
+
+ 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->refresh != NULL) {
+ int error = b->refresh(b);
+ if (error < 0)
+ return error;
+ }
+ }
+
+ return 0;
+}
+
int git_odb__error_notfound(const char *message, const git_oid *oid)
{
if (oid != NULL) {