summaryrefslogtreecommitdiff
path: root/src/odb.c
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@github.com>2016-07-14 16:23:24 -0400
committerEdward Thomson <ethomson@github.com>2016-08-04 15:12:04 -0400
commit8f09a98e1809dcdfd9d25b8268657bac4d942e6a (patch)
tree25f4b977d9a9055569d95a5ba5b038dfbfb01d6a /src/odb.c
parentd2794b0e37e98206b991ba4c8639ddf53c03bdb9 (diff)
downloadlibgit2-8f09a98e1809dcdfd9d25b8268657bac4d942e6a.tar.gz
odb: freshen existing objects when writing
When writing an object, we calculate its OID and see if it exists in the object database. If it does, we need to freshen the file that contains it.
Diffstat (limited to 'src/odb.c')
-rw-r--r--src/odb.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/src/odb.c b/src/odb.c
index 02391c4ac..253023ce1 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -654,7 +654,10 @@ void git_odb_free(git_odb *db)
GIT_REFCOUNT_DEC(db, odb_free);
}
-static int odb_exists_1(git_odb *db, const git_oid *id, bool only_refreshed)
+static int odb_exists_1(
+ git_odb *db,
+ const git_oid *id,
+ bool only_refreshed)
{
size_t i;
bool found = false;
@@ -673,6 +676,44 @@ static int odb_exists_1(git_odb *db, const git_oid *id, bool only_refreshed)
return (int)found;
}
+static int odb_freshen_1(
+ git_odb *db,
+ const git_oid *id,
+ bool only_refreshed)
+{
+ size_t i;
+ bool found = false;
+
+ for (i = 0; i < db->backends.length && !found; ++i) {
+ backend_internal *internal = git_vector_get(&db->backends, i);
+ git_odb_backend *b = internal->backend;
+
+ if (only_refreshed && !b->refresh)
+ continue;
+
+ if (b->freshen != NULL)
+ found = !b->freshen(b, id);
+ else if (b->exists != NULL)
+ found = b->exists(b, id);
+ }
+
+ return (int)found;
+}
+
+static int odb_freshen(git_odb *db, const git_oid *id)
+{
+ assert(db && id);
+
+ if (odb_freshen_1(db, id, false))
+ return 1;
+
+ if (!git_odb_refresh(db))
+ return odb_freshen_1(db, id, true);
+
+ /* Failed to refresh, hence not found */
+ return 0;
+}
+
int git_odb_exists(git_odb *db, const git_oid *id)
{
git_odb_object *object;
@@ -1131,7 +1172,7 @@ int git_odb_write(
assert(oid && db);
git_odb_hash(oid, data, len, type);
- if (git_odb_exists(db, oid))
+ if (odb_freshen(db, oid))
return 0;
for (i = 0; i < db->backends.length && error < 0; ++i) {
@@ -1257,7 +1298,7 @@ int git_odb_stream_finalize_write(git_oid *out, git_odb_stream *stream)
git_hash_final(out, stream->hash_ctx);
- if (git_odb_exists(stream->backend->odb, out))
+ if (odb_freshen(stream->backend->odb, out))
return 0;
return stream->finalize_write(stream, out);