odb: allow creating an ODB backend from a packfile index git_odb_backend_one_packfile() allows us to create an ODB backend out of an .idx file.
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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h
index 3f67202..b93ef20 100644
--- a/include/git2/odb_backend.h
+++ b/include/git2/odb_backend.h
@@ -100,6 +100,7 @@ struct git_odb_stream {
GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir);
GIT_EXTERN(int) git_odb_backend_loose(git_odb_backend **backend_out, const char *objects_dir, int compression_level, int do_fsync);
+GIT_EXTERN(int) git_odb_backend_one_pack(git_odb_backend **backend_out, const char *index_file);
GIT_END_DECL
diff --git a/src/odb_pack.c b/src/odb_pack.c
index 4b860e8..0f34ebd 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -458,6 +458,41 @@ static void pack_backend__free(git_odb_backend *_backend)
git__free(backend);
}
+int git_odb_backend_one_pack(git_odb_backend **backend_out, const char *idx)
+{
+ struct pack_backend *backend = NULL;
+ struct git_pack_file *packfile = NULL;
+
+ if (git_packfile_check(&packfile, idx) < 0)
+ return -1;
+
+ backend = git__calloc(1, sizeof(struct pack_backend));
+ GITERR_CHECK_ALLOC(backend);
+
+ if (git_vector_init(&backend->packs, 1, NULL) < 0)
+ goto on_error;
+
+ if (git_vector_insert(&backend->packs, packfile) < 0)
+ goto on_error;
+
+ backend->parent.read = &pack_backend__read;
+ backend->parent.read_prefix = &pack_backend__read_prefix;
+ backend->parent.read_header = NULL;
+ backend->parent.exists = &pack_backend__exists;
+ backend->parent.foreach = &pack_backend__foreach;
+ backend->parent.free = &pack_backend__free;
+
+ *backend_out = (git_odb_backend *)backend;
+
+ return 0;
+
+on_error:
+ git_vector_free(&backend->packs);
+ git__free(backend);
+ git__free(packfile);
+ return -1;
+}
+
int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir)
{
struct pack_backend *backend = NULL;
diff --git a/tests-clar/odb/foreach.c b/tests-clar/odb/foreach.c
index 525c70c..9b90aff 100644
--- a/tests-clar/odb/foreach.c
+++ b/tests-clar/odb/foreach.c
@@ -7,12 +7,6 @@ static git_odb *_odb;
static git_repository *_repo;
static int nobj;
-void test_odb_foreach__initialize(void)
-{
- cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git")));
- git_repository_odb(&_odb, _repo);
-}
-
void test_odb_foreach__cleanup(void)
{
git_odb_free(_odb);
@@ -31,6 +25,23 @@ static int foreach_cb(git_oid *oid, void *data)
void test_odb_foreach__foreach(void)
{
+ cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git")));
+ git_repository_odb(&_odb, _repo);
+
cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL));
cl_assert(nobj == 1683);
}
+
+void test_odb_foreach__one_pack(void)
+{
+ git_odb_backend *backend = NULL;
+
+ cl_git_pass(git_odb_new(&_odb));
+ cl_git_pass(git_odb_backend_one_pack(&backend, cl_fixture("testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx")));
+ cl_git_pass(git_odb_add_backend(_odb, backend, 1));
+ _repo = NULL;
+
+ nobj = 0;
+ cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL));
+ cl_assert(nobj == 1628);
+}
diff --git a/tests-clar/odb/pack_data_one.h b/tests-clar/odb/pack_data_one.h
new file mode 100644
index 0000000..13570ba
--- /dev/null
+++ b/tests-clar/odb/pack_data_one.h
@@ -0,0 +1,19 @@
+/* Just a few to make sure it's working, the rest is tested already */
+static const char *packed_objects_one[] = {
+ "9fcf811e00fa469688943a9152c16d4ee90fb9a9",
+ "a93f42a5b5e9de40fa645a9ff1e276a021c9542b",
+ "12bf5f3e3470d90db177ccf1b5e8126409377fc6",
+ "ed1ea164cdbe3c4b200fb4fa19861ea90eaee222",
+ "dfae6ed8f6dd8acc3b40a31811ea316239223559",
+ "aefe66d192771201e369fde830530f4475beec30",
+ "775e4b4c1296e9e3104f2a36ca9cf9356a130959",
+ "412ec4e4a6a7419bc1be00561fe474e54cb499fe",
+ "236e7579fed7763be77209efb8708960982f3cb3",
+ "09fe9364461cf60dd1c46b0e9545b1e47bb1a297",
+ "d76d8a6390d1cf32138d98a91b1eb7e0275a12f5",
+ "d0fdf2dcff2f548952eec536ccc6d266550041bc",
+ "a20d733a9fa79fa5b4cbb9639864f93325ec27a6",
+ "785d3fe8e7db5ade2c2242fecd46c32a7f4dc59f",
+ "4d8d0fd9cb6045075385701c3f933ec13345e9c4",
+ "0cfd861bd547b6520d1fc2e190e8359e0a9c9b90"
+};
diff --git a/tests-clar/odb/packed_one.c b/tests-clar/odb/packed_one.c
new file mode 100644
index 0000000..a064829
--- /dev/null
+++ b/tests-clar/odb/packed_one.c
@@ -0,0 +1,58 @@
+#include "clar_libgit2.h"
+#include "odb.h"
+#include "pack_data_one.h"
+#include "pack.h"
+
+static git_odb *_odb;
+
+void test_odb_packed_one__initialize(void)
+{
+ git_odb_backend *backend = NULL;
+
+ cl_git_pass(git_odb_new(&_odb));
+ cl_git_pass(git_odb_backend_one_pack(&backend, cl_fixture("testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx")));
+ cl_git_pass(git_odb_add_backend(_odb, backend, 1));
+}
+
+void test_odb_packed_one__cleanup(void)
+{
+ git_odb_free(_odb);
+}
+
+void test_odb_packed_one__mass_read(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(packed_objects_one); ++i) {
+ git_oid id;
+ git_odb_object *obj;
+
+ cl_git_pass(git_oid_fromstr(&id, packed_objects_one[i]));
+ cl_assert(git_odb_exists(_odb, &id) == 1);
+ cl_git_pass(git_odb_read(&obj, _odb, &id));
+
+ git_odb_object_free(obj);
+ }
+}
+
+void test_odb_packed_one__read_header_0(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(packed_objects_one); ++i) {
+ git_oid id;
+ git_odb_object *obj;
+ size_t len;
+ git_otype type;
+
+ cl_git_pass(git_oid_fromstr(&id, packed_objects_one[i]));
+
+ cl_git_pass(git_odb_read(&obj, _odb, &id));
+ cl_git_pass(git_odb_read_header(&len, &type, _odb, &id));
+
+ cl_assert(obj->raw.len == len);
+ cl_assert(obj->raw.type == type);
+
+ git_odb_object_free(obj);
+ }
+}