]>
Commit | Line | Data |
---|---|---|
6105d597 VM |
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 | ||
c8e02b87 | 21 | GIT__USE_OIDMAP |
6105d597 VM |
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; | |
f1453c59 | 41 | size_t alloc_len; |
6105d597 VM |
42 | int rval; |
43 | ||
44 | pos = kh_put(oid, db->objects, oid, &rval); | |
45 | if (rval < 0) | |
46 | return -1; | |
47 | ||
48 | if (rval == 0) | |
49 | return 0; | |
50 | ||
f1453c59 ET |
51 | GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(struct memobject), len); |
52 | obj = git__malloc(alloc_len); | |
6105d597 VM |
53 | GITERR_CHECK_ALLOC(obj); |
54 | ||
55 | memcpy(obj->data, data, len); | |
56 | git_oid_cpy(&obj->oid, oid); | |
57 | obj->len = len; | |
58 | obj->type = type; | |
59 | ||
60 | kh_key(db->objects, pos) = &obj->oid; | |
61 | kh_val(db->objects, pos) = obj; | |
62 | ||
63 | if (type == GIT_OBJ_COMMIT) { | |
64 | struct memobject **store = git_array_alloc(db->commits); | |
65 | GITERR_CHECK_ALLOC(store); | |
66 | *store = obj; | |
67 | } | |
68 | ||
69 | return 0; | |
70 | } | |
71 | ||
72 | static int impl__exists(git_odb_backend *backend, const git_oid *oid) | |
73 | { | |
74 | struct memory_packer_db *db = (struct memory_packer_db *)backend; | |
75 | khiter_t pos; | |
76 | ||
77 | pos = kh_get(oid, db->objects, oid); | |
78 | if (pos != kh_end(db->objects)) | |
79 | return 1; | |
80 | ||
81 | return 0; | |
82 | } | |
83 | ||
84 | static int impl__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid) | |
85 | { | |
86 | struct memory_packer_db *db = (struct memory_packer_db *)backend; | |
87 | struct memobject *obj = NULL; | |
88 | khiter_t pos; | |
89 | ||
90 | pos = kh_get(oid, db->objects, oid); | |
91 | if (pos == kh_end(db->objects)) | |
92 | return GIT_ENOTFOUND; | |
93 | ||
94 | obj = kh_val(db->objects, pos); | |
95 | ||
96 | *len_p = obj->len; | |
97 | *type_p = obj->type; | |
98 | *buffer_p = git__malloc(obj->len); | |
99 | GITERR_CHECK_ALLOC(*buffer_p); | |
100 | ||
101 | memcpy(*buffer_p, obj->data, obj->len); | |
102 | return 0; | |
103 | } | |
104 | ||
105 | static int impl__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid) | |
106 | { | |
107 | struct memory_packer_db *db = (struct memory_packer_db *)backend; | |
108 | struct memobject *obj = NULL; | |
109 | khiter_t pos; | |
110 | ||
111 | pos = kh_get(oid, db->objects, oid); | |
112 | if (pos == kh_end(db->objects)) | |
113 | return GIT_ENOTFOUND; | |
114 | ||
115 | obj = kh_val(db->objects, pos); | |
116 | ||
117 | *len_p = obj->len; | |
118 | *type_p = obj->type; | |
119 | return 0; | |
120 | } | |
121 | ||
122 | int git_mempack_dump(git_buf *pack, git_repository *repo, git_odb_backend *_backend) | |
123 | { | |
124 | struct memory_packer_db *db = (struct memory_packer_db *)_backend; | |
125 | git_packbuilder *packbuilder; | |
126 | uint32_t i; | |
127 | int err = -1; | |
128 | ||
129 | if (git_packbuilder_new(&packbuilder, repo) < 0) | |
130 | return -1; | |
131 | ||
132 | for (i = 0; i < db->commits.size; ++i) { | |
133 | struct memobject *commit = db->commits.ptr[i]; | |
134 | ||
135 | err = git_packbuilder_insert_commit(packbuilder, &commit->oid); | |
136 | if (err < 0) | |
137 | goto cleanup; | |
138 | } | |
139 | ||
140 | err = git_packbuilder_write_buf(pack, packbuilder); | |
141 | ||
142 | cleanup: | |
143 | git_packbuilder_free(packbuilder); | |
144 | return err; | |
145 | } | |
146 | ||
147 | void git_mempack_reset(git_odb_backend *_backend) | |
148 | { | |
149 | struct memory_packer_db *db = (struct memory_packer_db *)_backend; | |
150 | struct memobject *object = NULL; | |
151 | ||
152 | kh_foreach_value(db->objects, object, { | |
153 | git__free(object); | |
154 | }); | |
155 | ||
156 | git_array_clear(db->commits); | |
157 | } | |
158 | ||
159 | static void impl__free(git_odb_backend *_backend) | |
160 | { | |
161 | git_mempack_reset(_backend); | |
162 | git__free(_backend); | |
163 | } | |
164 | ||
165 | int git_mempack_new(git_odb_backend **out) | |
166 | { | |
167 | struct memory_packer_db *db; | |
168 | ||
169 | assert(out); | |
170 | ||
171 | db = git__calloc(1, sizeof(struct memory_packer_db)); | |
172 | GITERR_CHECK_ALLOC(db); | |
173 | ||
174 | db->objects = git_oidmap_alloc(); | |
175 | ||
176 | db->parent.read = &impl__read; | |
177 | db->parent.write = &impl__write; | |
178 | db->parent.read_header = &impl__read_header; | |
179 | db->parent.exists = &impl__exists; | |
180 | db->parent.free = &impl__free; | |
181 | ||
182 | *out = (git_odb_backend *)db; | |
183 | return 0; | |
184 | } |