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