Implement some of the basic git_odb open and close API Far from being complete, but its a good start. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
diff --git a/include/git/odb.h b/include/git/odb.h
index 7c6be4f..0d65e19 100644
--- a/include/git/odb.h
+++ b/include/git/odb.h
@@ -54,9 +54,8 @@ GIT_EXTERN(int) git_odb_open(git_odb **out, const char *objects_dir);
/**
* Close an open object database.
* @param db database pointer to close. If NULL no action is taken.
- * The pointer is set to NULL when the close is completed.
*/
-GIT_EXTERN(void) git_odb_close(git_odb **db);
+GIT_EXTERN(void) git_odb_close(git_odb *db);
/** Basic type (loose or packed) of any Git object. */
typedef enum {
@@ -129,7 +128,11 @@ GIT_EXTERN(int) git_odb__read_loose(git_sobj *out, git_odb *db, const git_oid *i
*
* @param obj object descriptor to free.
*/
-GIT_EXTERN(void) git_sobj_close(git_sobj *obj);
+GIT_INLINE(void) git_sobj_close(git_sobj *obj)
+{
+ free(obj->data);
+ obj->data = NULL;
+}
/** @} */
GIT_END_DECL
diff --git a/src/odb.c b/src/odb.c
index 86dcfa9..0a42099 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -27,21 +27,71 @@
struct git_odb {
/** Path to the "objects" directory. */
- const char *path;
+ char *path;
/** Alternate databases to search. */
git_odb **alternates;
-
- /** Number of alternates available. */
- unsigned n_alternates;
};
+static int open_alternates(git_odb *db)
+{
+ unsigned n = 0;
+
+ db->alternates = malloc(sizeof(*db->alternates) * (n + 1));
+ if (!db->alternates)
+ return GIT_ERROR;
+
+ db->alternates[n] = NULL;
+ return GIT_SUCCESS;
+}
+
+int git_odb_open(git_odb **out, const char *objects_dir)
+{
+ git_odb *db = malloc(sizeof(*db));
+ if (!db)
+ return GIT_ERROR;
+
+ db->path = strdup(objects_dir);
+ if (!db->path) {
+ free(db);
+ return GIT_ERROR;
+ }
+
+ db->alternates = NULL;
+
+ *out = db;
+ return GIT_SUCCESS;
+}
+
+void git_odb_close(git_odb *db)
+{
+ if (!db)
+ return;
+
+ if (db->alternates) {
+ git_odb **alt;
+ for (alt = db->alternates; *alt; alt++)
+ git_odb_close(*alt);
+ free(db->alternates);
+ }
+
+ free(db->path);
+ free(db);
+}
+
int git_odb_read(
git_sobj *out,
git_odb *db,
const git_oid *id)
{
+attempt:
if (!git_odb__read_packed(out, db, id))
return GIT_SUCCESS;
- return git_odb__read_loose(out, db, id);
+ if (!git_odb__read_loose(out, db, id))
+ return GIT_SUCCESS;
+ if (!db->alternates && !open_alternates(db))
+ goto attempt;
+
+ out->data = NULL;
+ return GIT_ENOTFOUND;
}