]> git.proxmox.com Git - libgit2.git/blob - src/odb_mempack.c
New upstream version 1.4.3+dfsg.1
[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
10 #include "buf.h"
11 #include "futils.h"
12 #include "hash.h"
13 #include "odb.h"
14 #include "array.h"
15 #include "oidmap.h"
16 #include "pack-objects.h"
17
18 #include "git2/odb_backend.h"
19 #include "git2/object.h"
20 #include "git2/types.h"
21 #include "git2/pack.h"
22 #include "git2/sys/odb_backend.h"
23 #include "git2/sys/mempack.h"
24
25 struct memobject {
26 git_oid oid;
27 size_t len;
28 git_object_t type;
29 char data[GIT_FLEX_ARRAY];
30 };
31
32 struct memory_packer_db {
33 git_odb_backend parent;
34 git_oidmap *objects;
35 git_array_t(struct memobject *) commits;
36 };
37
38 static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void *data, size_t len, git_object_t type)
39 {
40 struct memory_packer_db *db = (struct memory_packer_db *)_backend;
41 struct memobject *obj = NULL;
42 size_t alloc_len;
43
44 if (git_oidmap_exists(db->objects, oid))
45 return 0;
46
47 GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, sizeof(struct memobject), len);
48 obj = git__malloc(alloc_len);
49 GIT_ERROR_CHECK_ALLOC(obj);
50
51 memcpy(obj->data, data, len);
52 git_oid_cpy(&obj->oid, oid);
53 obj->len = len;
54 obj->type = type;
55
56 if (git_oidmap_set(db->objects, &obj->oid, obj) < 0)
57 return -1;
58
59 if (type == GIT_OBJECT_COMMIT) {
60 struct memobject **store = git_array_alloc(db->commits);
61 GIT_ERROR_CHECK_ALLOC(store);
62 *store = obj;
63 }
64
65 return 0;
66 }
67
68 static int impl__exists(git_odb_backend *backend, const git_oid *oid)
69 {
70 struct memory_packer_db *db = (struct memory_packer_db *)backend;
71
72 return git_oidmap_exists(db->objects, oid);
73 }
74
75 static int impl__read(void **buffer_p, size_t *len_p, git_object_t *type_p, git_odb_backend *backend, const git_oid *oid)
76 {
77 struct memory_packer_db *db = (struct memory_packer_db *)backend;
78 struct memobject *obj;
79
80 if ((obj = git_oidmap_get(db->objects, oid)) == NULL)
81 return GIT_ENOTFOUND;
82
83 *len_p = obj->len;
84 *type_p = obj->type;
85 *buffer_p = git__malloc(obj->len);
86 GIT_ERROR_CHECK_ALLOC(*buffer_p);
87
88 memcpy(*buffer_p, obj->data, obj->len);
89 return 0;
90 }
91
92 static int impl__read_header(size_t *len_p, git_object_t *type_p, git_odb_backend *backend, const git_oid *oid)
93 {
94 struct memory_packer_db *db = (struct memory_packer_db *)backend;
95 struct memobject *obj;
96
97 if ((obj = git_oidmap_get(db->objects, oid)) == NULL)
98 return GIT_ENOTFOUND;
99
100 *len_p = obj->len;
101 *type_p = obj->type;
102 return 0;
103 }
104
105 static int git_mempack__dump(
106 git_str *pack,
107 git_repository *repo,
108 git_odb_backend *_backend)
109 {
110 struct memory_packer_db *db = (struct memory_packer_db *)_backend;
111 git_packbuilder *packbuilder;
112 uint32_t i;
113 int err = -1;
114
115 if (git_packbuilder_new(&packbuilder, repo) < 0)
116 return -1;
117
118 git_packbuilder_set_threads(packbuilder, 0);
119
120 for (i = 0; i < db->commits.size; ++i) {
121 struct memobject *commit = db->commits.ptr[i];
122
123 err = git_packbuilder_insert_commit(packbuilder, &commit->oid);
124 if (err < 0)
125 goto cleanup;
126 }
127
128 err = git_packbuilder__write_buf(pack, packbuilder);
129
130 cleanup:
131 git_packbuilder_free(packbuilder);
132 return err;
133 }
134
135 int git_mempack_dump(
136 git_buf *pack,
137 git_repository *repo,
138 git_odb_backend *_backend)
139 {
140 GIT_BUF_WRAP_PRIVATE(pack, git_mempack__dump, repo, _backend);
141 }
142
143 int git_mempack_reset(git_odb_backend *_backend)
144 {
145 struct memory_packer_db *db = (struct memory_packer_db *)_backend;
146 struct memobject *object = NULL;
147
148 git_oidmap_foreach_value(db->objects, object, {
149 git__free(object);
150 });
151
152 git_array_clear(db->commits);
153
154 git_oidmap_clear(db->objects);
155
156 return 0;
157 }
158
159 static void impl__free(git_odb_backend *_backend)
160 {
161 struct memory_packer_db *db = (struct memory_packer_db *)_backend;
162
163 git_mempack_reset(_backend);
164 git_oidmap_free(db->objects);
165 git__free(db);
166 }
167
168 int git_mempack_new(git_odb_backend **out)
169 {
170 struct memory_packer_db *db;
171
172 GIT_ASSERT_ARG(out);
173
174 db = git__calloc(1, sizeof(struct memory_packer_db));
175 GIT_ERROR_CHECK_ALLOC(db);
176
177 if (git_oidmap_new(&db->objects) < 0)
178 return -1;
179
180 db->parent.version = GIT_ODB_BACKEND_VERSION;
181 db->parent.read = &impl__read;
182 db->parent.write = &impl__write;
183 db->parent.read_header = &impl__read_header;
184 db->parent.exists = &impl__exists;
185 db->parent.free = &impl__free;
186
187 *out = (git_odb_backend *)db;
188 return 0;
189 }