summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backends/sqlite.c2
-rw-r--r--src/git2.h4
-rw-r--r--src/git2/odb.h19
-rw-r--r--src/git2/odb_backend.h2
-rw-r--r--src/odb.c82
-rw-r--r--src/odb_loose.c2
-rw-r--r--src/odb_pack.c2
7 files changed, 84 insertions, 29 deletions
diff --git a/src/backends/sqlite.c b/src/backends/sqlite.c
index ad5b679f9..b4c941a59 100644
--- a/src/backends/sqlite.c
+++ b/src/backends/sqlite.c
@@ -264,8 +264,6 @@ int git_odb_backend_sqlite(git_odb_backend **backend_out, const char *sqlite_db)
backend->parent.exists = &sqlite_backend__exists;
backend->parent.free = &sqlite_backend__free;
- backend->parent.priority = 0;
-
*backend_out = (git_odb_backend *)backend;
return GIT_SUCCESS;
diff --git a/src/git2.h b/src/git2.h
index 70ab811f1..e6042d050 100644
--- a/src/git2.h
+++ b/src/git2.h
@@ -26,9 +26,9 @@
#ifndef INCLUDE_git_git_h__
#define INCLUDE_git_git_h__
-#define LIBGIT2_VERSION "0.3.0"
+#define LIBGIT2_VERSION "0.4.0"
#define LIBGIT2_VER_MAJOR 0
-#define LIBGIT2_VER_MINOR 3
+#define LIBGIT2_VER_MINOR 4
#define LIBGIT2_VER_REVISION 0
#include "git2/common.h"
diff --git a/src/git2/odb.h b/src/git2/odb.h
index 2f2741135..0d285897c 100644
--- a/src/git2/odb.h
+++ b/src/git2/odb.h
@@ -79,7 +79,24 @@ GIT_EXTERN(int) git_odb_open(git_odb **out, const char *objects_dir);
* @paramm backend pointer to a git_odb_backend instance
* @return 0 on sucess; error code otherwise
*/
-GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend);
+GIT_EXTERN(int) git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int priority);
+
+/**
+ * Add a custom backend to an existing Object DB; this
+ * backend will work as an alternate.
+ *
+ * Alternate backends are always checked for objects *after*
+ * all the main backends have been exhausted.
+ *
+ * Writing is disabled on alternate backends.
+ *
+ * Read <odb_backends.h> for more information.
+ *
+ * @param odb database to add the backend to
+ * @paramm backend pointer to a git_odb_backend instance
+ * @return 0 on sucess; error code otherwise
+ */
+GIT_EXTERN(int) git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority);
/**
* Close an open object database.
diff --git a/src/git2/odb_backend.h b/src/git2/odb_backend.h
index ee7e5dfde..9cdd358ee 100644
--- a/src/git2/odb_backend.h
+++ b/src/git2/odb_backend.h
@@ -42,8 +42,6 @@ GIT_BEGIN_DECL
struct git_odb_backend {
git_odb *odb;
- int priority;
-
int (* read)(
git_rawobj *,
struct git_odb_backend *,
diff --git a/src/odb.c b/src/odb.c
index b5996c826..4e54c749a 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -35,6 +35,17 @@
#define GIT_ALTERNATES_FILE "info/alternates"
+/* TODO: is this correct? */
+#define GIT_LOOSE_PRIORITY 2
+#define GIT_PACKED_PRIORITY 1
+
+typedef struct
+{
+ git_odb_backend *backend;
+ int priority;
+ int is_alternate;
+} backend_internal;
+
static int format_object_header(char *hdr, size_t n, git_rawobj *obj)
{
const char *type_str = git_object_type2string(obj->type);
@@ -136,10 +147,13 @@ int git_odb__inflate_buffer(void *in, size_t inlen, void *out, size_t outlen)
int backend_sort_cmp(const void *a, const void *b)
{
- const git_odb_backend *backend_a = *(const git_odb_backend **)(a);
- const git_odb_backend *backend_b = *(const git_odb_backend **)(b);
+ const backend_internal *backend_a = *(const backend_internal **)(a);
+ const backend_internal *backend_b = *(const backend_internal **)(b);
+
+ if (backend_a->is_alternate == backend_b->is_alternate)
+ return (backend_b->priority - backend_a->priority);
- return (backend_b->priority - backend_a->priority);
+ return backend_a->is_alternate ? 1 : -1;
}
int git_odb_new(git_odb **out)
@@ -157,23 +171,44 @@ int git_odb_new(git_odb **out)
return GIT_SUCCESS;
}
-int git_odb_add_backend(git_odb *odb, git_odb_backend *backend)
+static int add_backend_internal(git_odb *odb, git_odb_backend *backend, int priority, int is_alternate)
{
+ backend_internal *internal;
+
assert(odb && backend);
if (backend->odb != NULL && backend->odb != odb)
return GIT_EBUSY;
- backend->odb = odb;
+ internal = git__malloc(sizeof(backend_internal));
+ if (internal == NULL)
+ return GIT_ENOMEM;
+
+ internal->backend = backend;
+ internal->priority = priority;
+ internal->is_alternate = is_alternate;
- if (git_vector_insert(&odb->backends, backend) < 0)
+ if (git_vector_insert(&odb->backends, internal) < 0) {
+ free(internal);
return GIT_ENOMEM;
+ }
git_vector_sort(&odb->backends);
+ internal->backend->odb = odb;
return GIT_SUCCESS;
}
-static int add_default_backends(git_odb *db, const char *objects_dir)
+int git_odb_add_backend(git_odb *odb, git_odb_backend *backend, int priority)
+{
+ return add_backend_internal(odb, backend, priority, 0);
+}
+
+int git_odb_add_alternate(git_odb *odb, git_odb_backend *backend, int priority)
+{
+ return add_backend_internal(odb, backend, priority, 1);
+}
+
+static int add_default_backends(git_odb *db, const char *objects_dir, int as_alternates)
{
git_odb_backend *loose, *packed;
int error;
@@ -183,7 +218,7 @@ static int add_default_backends(git_odb *db, const char *objects_dir)
if (error < GIT_SUCCESS)
return error;
- error = git_odb_add_backend(db, loose);
+ error = add_backend_internal(db, loose, GIT_LOOSE_PRIORITY, as_alternates);
if (error < GIT_SUCCESS)
return error;
@@ -192,7 +227,7 @@ static int add_default_backends(git_odb *db, const char *objects_dir)
if (error < GIT_SUCCESS)
return error;
- error = git_odb_add_backend(db, packed);
+ error = add_backend_internal(db, packed, GIT_PACKED_PRIORITY, as_alternates);
if (error < GIT_SUCCESS)
return error;
@@ -221,7 +256,7 @@ static int load_alternates(git_odb *odb, const char *objects_dir)
/* add each alternate as a new backend; one alternate per line */
while ((error == GIT_SUCCESS) && (buffer = git__strtok(alternate, buffer, "\r\n")) != NULL)
- error = add_default_backends(odb, alternate);
+ error = add_default_backends(odb, alternate, 1);
gitfo_free_buf(&alternates_buf);
return error;
@@ -239,7 +274,7 @@ int git_odb_open(git_odb **out, const char *objects_dir)
if ((error = git_odb_new(&db)) < 0)
return error;
- if ((error = add_default_backends(db, objects_dir)) < GIT_SUCCESS)
+ if ((error = add_default_backends(db, objects_dir, 0)) < GIT_SUCCESS)
goto cleanup;
if ((error = load_alternates(db, objects_dir)) < GIT_SUCCESS)
@@ -261,10 +296,13 @@ void git_odb_close(git_odb *db)
return;
for (i = 0; i < db->backends.length; ++i) {
- git_odb_backend *b = git_vector_get(&db->backends, i);
+ backend_internal *internal = git_vector_get(&db->backends, i);
+ git_odb_backend *backend = internal->backend;
- if (b->free) b->free(b);
- else free(b);
+ if (backend->free) backend->free(backend);
+ else free(backend);
+
+ free(internal);
}
git_vector_free(&db->backends);
@@ -279,7 +317,8 @@ int git_odb_exists(git_odb *db, const git_oid *id)
assert(db && id);
for (i = 0; i < db->backends.length && !found; ++i) {
- git_odb_backend *b = git_vector_get(&db->backends, i);
+ backend_internal *internal = git_vector_get(&db->backends, i);
+ git_odb_backend *b = internal->backend;
if (b->exists != NULL)
found = b->exists(b, id);
@@ -296,7 +335,8 @@ int git_odb_read_header(git_rawobj *out, git_odb *db, const git_oid *id)
assert(out && db && id);
for (i = 0; i < db->backends.length && error < 0; ++i) {
- git_odb_backend *b = git_vector_get(&db->backends, i);
+ backend_internal *internal = git_vector_get(&db->backends, i);
+ git_odb_backend *b = internal->backend;
if (b->read_header != NULL)
error = b->read_header(out, b, id);
@@ -322,7 +362,8 @@ int git_odb_read(git_rawobj *out, git_odb *db, const git_oid *id)
assert(out && db && id);
for (i = 0; i < db->backends.length && error < 0; ++i) {
- git_odb_backend *b = git_vector_get(&db->backends, i);
+ backend_internal *internal = git_vector_get(&db->backends, i);
+ git_odb_backend *b = internal->backend;
if (b->read != NULL)
error = b->read(out, b, id);
@@ -339,7 +380,12 @@ int git_odb_write(git_oid *id, git_odb *db, git_rawobj *obj)
assert(obj && db && id);
for (i = 0; i < db->backends.length && error < 0; ++i) {
- git_odb_backend *b = git_vector_get(&db->backends, i);
+ backend_internal *internal = git_vector_get(&db->backends, i);
+ git_odb_backend *b = internal->backend;
+
+ /* we don't write in alternates! */
+ if (internal->is_alternate)
+ continue;
if (b->write != NULL)
error = b->write(id, b, obj);
diff --git a/src/odb_loose.c b/src/odb_loose.c
index f89eb71ff..735d9394f 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -653,8 +653,6 @@ int git_odb_backend_loose(git_odb_backend **backend_out, const char *objects_dir
backend->parent.exists = &loose_backend__exists;
backend->parent.free = &loose_backend__free;
- backend->parent.priority = 2; /* higher than packfiles */
-
*backend_out = (git_odb_backend *)backend;
return GIT_SUCCESS;
}
diff --git a/src/odb_pack.c b/src/odb_pack.c
index 6141c57ef..664b00139 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -1203,8 +1203,6 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
backend->parent.exists = &pack_backend__exists;
backend->parent.free = &pack_backend__free;
- backend->parent.priority = 1;
-
*backend_out = (git_odb_backend *)backend;
return GIT_SUCCESS;
}