]>
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" | |
eae0bfdc | 9 | |
6105d597 VM |
10 | #include "git2/object.h" |
11 | #include "git2/sys/odb_backend.h" | |
eae0bfdc | 12 | #include "git2/sys/mempack.h" |
0c9c969a | 13 | #include "futils.h" |
6105d597 VM |
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 | ||
6105d597 VM |
23 | struct memobject { |
24 | git_oid oid; | |
25 | size_t len; | |
ac3d33df | 26 | git_object_t type; |
8468a440 | 27 | char data[GIT_FLEX_ARRAY]; |
6105d597 VM |
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 | ||
ac3d33df | 36 | static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void *data, size_t len, git_object_t type) |
6105d597 VM |
37 | { |
38 | struct memory_packer_db *db = (struct memory_packer_db *)_backend; | |
ac3d33df | 39 | struct memobject *obj = NULL; |
f1453c59 | 40 | size_t alloc_len; |
6105d597 | 41 | |
0c9c969a | 42 | if (git_oidmap_exists(db->objects, oid)) |
6105d597 VM |
43 | return 0; |
44 | ||
ac3d33df | 45 | GIT_ERROR_CHECK_ALLOC_ADD(&alloc_len, sizeof(struct memobject), len); |
f1453c59 | 46 | obj = git__malloc(alloc_len); |
ac3d33df | 47 | GIT_ERROR_CHECK_ALLOC(obj); |
6105d597 VM |
48 | |
49 | memcpy(obj->data, data, len); | |
50 | git_oid_cpy(&obj->oid, oid); | |
51 | obj->len = len; | |
52 | obj->type = type; | |
53 | ||
0c9c969a UG |
54 | if (git_oidmap_set(db->objects, &obj->oid, obj) < 0) |
55 | return -1; | |
6105d597 | 56 | |
ac3d33df | 57 | if (type == GIT_OBJECT_COMMIT) { |
6105d597 | 58 | struct memobject **store = git_array_alloc(db->commits); |
ac3d33df | 59 | GIT_ERROR_CHECK_ALLOC(store); |
6105d597 VM |
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; | |
6105d597 | 69 | |
036daa59 | 70 | return git_oidmap_exists(db->objects, oid); |
6105d597 VM |
71 | } |
72 | ||
ac3d33df | 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) |
6105d597 VM |
74 | { |
75 | struct memory_packer_db *db = (struct memory_packer_db *)backend; | |
0c9c969a | 76 | struct memobject *obj; |
6105d597 | 77 | |
0c9c969a | 78 | if ((obj = git_oidmap_get(db->objects, oid)) == NULL) |
6105d597 VM |
79 | return GIT_ENOTFOUND; |
80 | ||
6105d597 VM |
81 | *len_p = obj->len; |
82 | *type_p = obj->type; | |
83 | *buffer_p = git__malloc(obj->len); | |
ac3d33df | 84 | GIT_ERROR_CHECK_ALLOC(*buffer_p); |
6105d597 VM |
85 | |
86 | memcpy(*buffer_p, obj->data, obj->len); | |
87 | return 0; | |
88 | } | |
89 | ||
ac3d33df | 90 | static int impl__read_header(size_t *len_p, git_object_t *type_p, git_odb_backend *backend, const git_oid *oid) |
6105d597 VM |
91 | { |
92 | struct memory_packer_db *db = (struct memory_packer_db *)backend; | |
0c9c969a | 93 | struct memobject *obj; |
6105d597 | 94 | |
0c9c969a | 95 | if ((obj = git_oidmap_get(db->objects, oid)) == NULL) |
6105d597 VM |
96 | return GIT_ENOTFOUND; |
97 | ||
6105d597 VM |
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 | for (i = 0; i < db->commits.size; ++i) { | |
114 | struct memobject *commit = db->commits.ptr[i]; | |
115 | ||
116 | err = git_packbuilder_insert_commit(packbuilder, &commit->oid); | |
117 | if (err < 0) | |
118 | goto cleanup; | |
119 | } | |
120 | ||
121 | err = git_packbuilder_write_buf(pack, packbuilder); | |
122 | ||
123 | cleanup: | |
124 | git_packbuilder_free(packbuilder); | |
125 | return err; | |
126 | } | |
127 | ||
0c9c969a | 128 | int git_mempack_reset(git_odb_backend *_backend) |
6105d597 VM |
129 | { |
130 | struct memory_packer_db *db = (struct memory_packer_db *)_backend; | |
131 | struct memobject *object = NULL; | |
132 | ||
9694d9ba | 133 | git_oidmap_foreach_value(db->objects, object, { |
6105d597 VM |
134 | git__free(object); |
135 | }); | |
136 | ||
137 | git_array_clear(db->commits); | |
8e177b2b | 138 | |
220d6f8a | 139 | git_oidmap_clear(db->objects); |
0c9c969a UG |
140 | |
141 | return 0; | |
6105d597 VM |
142 | } |
143 | ||
144 | static void impl__free(git_odb_backend *_backend) | |
145 | { | |
707f6537 BW |
146 | struct memory_packer_db *db = (struct memory_packer_db *)_backend; |
147 | ||
4b3ec53c | 148 | git_mempack_reset(_backend); |
707f6537 | 149 | git_oidmap_free(db->objects); |
707f6537 | 150 | git__free(db); |
6105d597 VM |
151 | } |
152 | ||
153 | int git_mempack_new(git_odb_backend **out) | |
154 | { | |
155 | struct memory_packer_db *db; | |
156 | ||
157 | assert(out); | |
158 | ||
159 | db = git__calloc(1, sizeof(struct memory_packer_db)); | |
ac3d33df | 160 | GIT_ERROR_CHECK_ALLOC(db); |
6105d597 | 161 | |
0c9c969a UG |
162 | if (git_oidmap_new(&db->objects) < 0) |
163 | return -1; | |
6105d597 | 164 | |
6a8127d7 | 165 | db->parent.version = GIT_ODB_BACKEND_VERSION; |
6105d597 VM |
166 | db->parent.read = &impl__read; |
167 | db->parent.write = &impl__write; | |
168 | db->parent.read_header = &impl__read_header; | |
169 | db->parent.exists = &impl__exists; | |
170 | db->parent.free = &impl__free; | |
171 | ||
172 | *out = (git_odb_backend *)db; | |
173 | return 0; | |
174 | } |