]> git.proxmox.com Git - libgit2.git/blob - src/odb_mempack.c
d9b3a1824ddfec97e52e9e4e5514bcec910f0eab
[libgit2.git] / src / odb_mempack.c
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7
8 #include "common.h"
9 #include "git2/object.h"
10 #include "git2/sys/odb_backend.h"
11 #include "fileops.h"
12 #include "hash.h"
13 #include "odb.h"
14 #include "array.h"
15 #include "oidmap.h"
16
17 #include "git2/odb_backend.h"
18 #include "git2/types.h"
19 #include "git2/pack.h"
20
21 GIT__USE_OIDMAP;
22
23 struct memobject {
24 git_oid oid;
25 size_t len;
26 git_otype type;
27 char data[];
28 };
29
30 struct memory_packer_db {
31 git_odb_backend parent;
32 git_oidmap *objects;
33 git_array_t(struct memobject *) commits;
34 };
35
36 static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void *data, size_t len, git_otype type)
37 {
38 struct memory_packer_db *db = (struct memory_packer_db *)_backend;
39 struct memobject *obj = NULL;
40 khiter_t pos;
41 int rval;
42
43 pos = kh_put(oid, db->objects, oid, &rval);
44 if (rval < 0)
45 return -1;
46
47 if (rval == 0)
48 return 0;
49
50 obj = git__malloc(sizeof(struct memobject) + len);
51 GITERR_CHECK_ALLOC(obj);
52
53 memcpy(obj->data, data, len);
54 git_oid_cpy(&obj->oid, oid);
55 obj->len = len;
56 obj->type = type;
57
58 kh_key(db->objects, pos) = &obj->oid;
59 kh_val(db->objects, pos) = obj;
60
61 if (type == GIT_OBJ_COMMIT) {
62 struct memobject **store = git_array_alloc(db->commits);
63 GITERR_CHECK_ALLOC(store);
64 *store = obj;
65 }
66
67 return 0;
68 }
69
70 static int impl__exists(git_odb_backend *backend, const git_oid *oid)
71 {
72 struct memory_packer_db *db = (struct memory_packer_db *)backend;
73 khiter_t pos;
74
75 pos = kh_get(oid, db->objects, oid);
76 if (pos != kh_end(db->objects))
77 return 1;
78
79 return 0;
80 }
81
82 static int impl__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid)
83 {
84 struct memory_packer_db *db = (struct memory_packer_db *)backend;
85 struct memobject *obj = NULL;
86 khiter_t pos;
87
88 pos = kh_get(oid, db->objects, oid);
89 if (pos == kh_end(db->objects))
90 return GIT_ENOTFOUND;
91
92 obj = kh_val(db->objects, pos);
93
94 *len_p = obj->len;
95 *type_p = obj->type;
96 *buffer_p = git__malloc(obj->len);
97 GITERR_CHECK_ALLOC(*buffer_p);
98
99 memcpy(*buffer_p, obj->data, obj->len);
100 return 0;
101 }
102
103 static int impl__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid)
104 {
105 struct memory_packer_db *db = (struct memory_packer_db *)backend;
106 struct memobject *obj = NULL;
107 khiter_t pos;
108
109 pos = kh_get(oid, db->objects, oid);
110 if (pos == kh_end(db->objects))
111 return GIT_ENOTFOUND;
112
113 obj = kh_val(db->objects, pos);
114
115 *len_p = obj->len;
116 *type_p = obj->type;
117 return 0;
118 }
119
120 int git_mempack_dump(git_buf *pack, git_repository *repo, git_odb_backend *_backend)
121 {
122 struct memory_packer_db *db = (struct memory_packer_db *)_backend;
123 git_packbuilder *packbuilder;
124 uint32_t i;
125 int err = -1;
126
127 if (git_packbuilder_new(&packbuilder, repo) < 0)
128 return -1;
129
130 for (i = 0; i < db->commits.size; ++i) {
131 struct memobject *commit = db->commits.ptr[i];
132
133 err = git_packbuilder_insert_commit(packbuilder, &commit->oid);
134 if (err < 0)
135 goto cleanup;
136 }
137
138 err = git_packbuilder_write_buf(pack, packbuilder);
139
140 cleanup:
141 git_packbuilder_free(packbuilder);
142 return err;
143 }
144
145 void git_mempack_reset(git_odb_backend *_backend)
146 {
147 struct memory_packer_db *db = (struct memory_packer_db *)_backend;
148 struct memobject *object = NULL;
149
150 kh_foreach_value(db->objects, object, {
151 git__free(object);
152 });
153
154 git_array_clear(db->commits);
155 }
156
157 static void impl__free(git_odb_backend *_backend)
158 {
159 git_mempack_reset(_backend);
160 git__free(_backend);
161 }
162
163 int git_mempack_new(git_odb_backend **out)
164 {
165 struct memory_packer_db *db;
166
167 assert(out);
168
169 db = git__calloc(1, sizeof(struct memory_packer_db));
170 GITERR_CHECK_ALLOC(db);
171
172 db->objects = git_oidmap_alloc();
173
174 db->parent.read = &impl__read;
175 db->parent.write = &impl__write;
176 db->parent.read_header = &impl__read_header;
177 db->parent.exists = &impl__exists;
178 db->parent.free = &impl__free;
179
180 *out = (git_odb_backend *)db;
181 return 0;
182 }