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