]> git.proxmox.com Git - libgit2.git/blob - tests/pack/packbuilder.c
6859001fe23fe8b47042abe79e9560bc069f0cb6
[libgit2.git] / tests / pack / packbuilder.c
1 #include "clar_libgit2.h"
2 #include "fileops.h"
3 #include "pack.h"
4 #include "hash.h"
5 #include "iterator.h"
6 #include "vector.h"
7 #include "posix.h"
8
9 static git_repository *_repo;
10 static git_revwalk *_revwalker;
11 static git_packbuilder *_packbuilder;
12 static git_indexer *_indexer;
13 static git_vector _commits;
14 static int _commits_is_initialized;
15 static git_transfer_progress _stats;
16
17 void test_pack_packbuilder__initialize(void)
18 {
19 _repo = cl_git_sandbox_init("testrepo.git");
20 cl_git_pass(p_chdir("testrepo.git"));
21 cl_git_pass(git_revwalk_new(&_revwalker, _repo));
22 cl_git_pass(git_packbuilder_new(&_packbuilder, _repo));
23 cl_git_pass(git_vector_init(&_commits, 0, NULL));
24 _commits_is_initialized = 1;
25 memset(&_stats, 0, sizeof(_stats));
26 p_fsync__cnt = 0;
27 }
28
29 void test_pack_packbuilder__cleanup(void)
30 {
31 git_oid *o;
32 unsigned int i;
33
34 cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_FSYNC_GITDIR, 0));
35
36 if (_commits_is_initialized) {
37 _commits_is_initialized = 0;
38 git_vector_foreach(&_commits, i, o) {
39 git__free(o);
40 }
41 git_vector_free(&_commits);
42 }
43
44 git_packbuilder_free(_packbuilder);
45 _packbuilder = NULL;
46
47 git_revwalk_free(_revwalker);
48 _revwalker = NULL;
49
50 git_indexer_free(_indexer);
51 _indexer = NULL;
52
53 cl_git_pass(p_chdir(".."));
54 cl_git_sandbox_cleanup();
55 _repo = NULL;
56 }
57
58 static void seed_packbuilder(void)
59 {
60 git_oid oid, *o;
61 unsigned int i;
62
63 git_revwalk_sorting(_revwalker, GIT_SORT_TIME);
64 cl_git_pass(git_revwalk_push_ref(_revwalker, "HEAD"));
65
66 while (git_revwalk_next(&oid, _revwalker) == 0) {
67 o = git__malloc(GIT_OID_RAWSZ);
68 cl_assert(o != NULL);
69 git_oid_cpy(o, &oid);
70 cl_git_pass(git_vector_insert(&_commits, o));
71 }
72
73 git_vector_foreach(&_commits, i, o) {
74 cl_git_pass(git_packbuilder_insert(_packbuilder, o, NULL));
75 }
76
77 git_vector_foreach(&_commits, i, o) {
78 git_object *obj;
79 cl_git_pass(git_object_lookup(&obj, _repo, o, GIT_OBJECT_COMMIT));
80 cl_git_pass(git_packbuilder_insert_tree(_packbuilder,
81 git_commit_tree_id((git_commit *)obj)));
82 git_object_free(obj);
83 }
84 }
85
86 static int feed_indexer(void *ptr, size_t len, void *payload)
87 {
88 git_transfer_progress *stats = (git_transfer_progress *)payload;
89
90 return git_indexer_append(_indexer, ptr, len, stats);
91 }
92
93 void test_pack_packbuilder__create_pack(void)
94 {
95 git_transfer_progress stats;
96 git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
97 git_hash_ctx ctx;
98 git_oid hash;
99 char hex[GIT_OID_HEXSZ+1]; hex[GIT_OID_HEXSZ] = '\0';
100
101 seed_packbuilder();
102
103 cl_git_pass(git_indexer_new(&_indexer, ".", 0, NULL, NULL));
104 cl_git_pass(git_packbuilder_foreach(_packbuilder, feed_indexer, &stats));
105 cl_git_pass(git_indexer_commit(_indexer, &stats));
106
107 git_oid_fmt(hex, git_indexer_hash(_indexer));
108 git_buf_printf(&path, "pack-%s.pack", hex);
109
110 /*
111 * By default, packfiles are created with only one thread.
112 * Therefore we can predict the object ordering and make sure
113 * we create exactly the same pack as git.git does when *not*
114 * reusing existing deltas (as libgit2).
115 *
116 * $ cd tests/resources/testrepo.git
117 * $ git rev-list --objects HEAD | \
118 * git pack-objects -q --no-reuse-delta --threads=1 pack
119 * $ sha1sum pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.pack
120 * 5d410bdf97cf896f9007681b92868471d636954b
121 *
122 */
123
124 cl_git_pass(git_futils_readbuffer(&buf, git_buf_cstr(&path)));
125
126 cl_git_pass(git_hash_ctx_init(&ctx));
127 cl_git_pass(git_hash_update(&ctx, buf.ptr, buf.size));
128 cl_git_pass(git_hash_final(&hash, &ctx));
129 git_hash_ctx_cleanup(&ctx);
130
131 git_buf_dispose(&path);
132 git_buf_dispose(&buf);
133
134 git_oid_fmt(hex, &hash);
135
136 cl_assert_equal_s(hex, "5d410bdf97cf896f9007681b92868471d636954b");
137 }
138
139 void test_pack_packbuilder__get_hash(void)
140 {
141 char hex[GIT_OID_HEXSZ+1]; hex[GIT_OID_HEXSZ] = '\0';
142
143 seed_packbuilder();
144
145 git_packbuilder_write(_packbuilder, ".", 0, NULL, NULL);
146 git_oid_fmt(hex, git_packbuilder_hash(_packbuilder));
147
148 cl_assert_equal_s(hex, "7f5fa362c664d68ba7221259be1cbd187434b2f0");
149 }
150
151 static void test_write_pack_permission(mode_t given, mode_t expected)
152 {
153 struct stat statbuf;
154 mode_t mask, os_mask;
155
156 seed_packbuilder();
157
158 git_packbuilder_write(_packbuilder, ".", given, NULL, NULL);
159
160 /* Windows does not return group/user bits from stat,
161 * files are never executable.
162 */
163 #ifdef GIT_WIN32
164 os_mask = 0600;
165 #else
166 os_mask = 0777;
167 #endif
168
169 mask = p_umask(0);
170 p_umask(mask);
171
172 cl_git_pass(p_stat("pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.idx", &statbuf));
173 cl_assert_equal_i(statbuf.st_mode & os_mask, (expected & ~mask) & os_mask);
174
175 cl_git_pass(p_stat("pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.pack", &statbuf));
176 cl_assert_equal_i(statbuf.st_mode & os_mask, (expected & ~mask) & os_mask);
177 }
178
179 void test_pack_packbuilder__permissions_standard(void)
180 {
181 test_write_pack_permission(0, GIT_PACK_FILE_MODE);
182 }
183
184 void test_pack_packbuilder__permissions_readonly(void)
185 {
186 test_write_pack_permission(0444, 0444);
187 }
188
189 void test_pack_packbuilder__permissions_readwrite(void)
190 {
191 test_write_pack_permission(0666, 0666);
192 }
193
194 void test_pack_packbuilder__does_not_fsync_by_default(void)
195 {
196 seed_packbuilder();
197 git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL);
198 cl_assert_equal_sz(0, p_fsync__cnt);
199 }
200
201 /* We fsync the packfile and index. On non-Windows, we also fsync
202 * the parent directories.
203 */
204 #ifdef GIT_WIN32
205 static int expected_fsyncs = 2;
206 #else
207 static int expected_fsyncs = 4;
208 #endif
209
210 void test_pack_packbuilder__fsync_global_setting(void)
211 {
212 cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_FSYNC_GITDIR, 1));
213 p_fsync__cnt = 0;
214 seed_packbuilder();
215 git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL);
216 cl_assert_equal_sz(expected_fsyncs, p_fsync__cnt);
217 }
218
219 void test_pack_packbuilder__fsync_repo_setting(void)
220 {
221 cl_repo_set_bool(_repo, "core.fsyncObjectFiles", true);
222 p_fsync__cnt = 0;
223 seed_packbuilder();
224 git_packbuilder_write(_packbuilder, ".", 0666, NULL, NULL);
225 cl_assert_equal_sz(expected_fsyncs, p_fsync__cnt);
226 }
227
228 static int foreach_cb(void *buf, size_t len, void *payload)
229 {
230 git_indexer *idx = (git_indexer *) payload;
231 cl_git_pass(git_indexer_append(idx, buf, len, &_stats));
232 return 0;
233 }
234
235 void test_pack_packbuilder__foreach(void)
236 {
237 git_indexer *idx;
238
239 seed_packbuilder();
240 cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL));
241 cl_git_pass(git_packbuilder_foreach(_packbuilder, foreach_cb, idx));
242 cl_git_pass(git_indexer_commit(idx, &_stats));
243 git_indexer_free(idx);
244 }
245
246 static int foreach_cancel_cb(void *buf, size_t len, void *payload)
247 {
248 git_indexer *idx = (git_indexer *)payload;
249 cl_git_pass(git_indexer_append(idx, buf, len, &_stats));
250 return (_stats.total_objects > 2) ? -1111 : 0;
251 }
252
253 void test_pack_packbuilder__foreach_with_cancel(void)
254 {
255 git_indexer *idx;
256
257 seed_packbuilder();
258 cl_git_pass(git_indexer_new(&idx, ".", 0, NULL, NULL));
259 cl_git_fail_with(
260 git_packbuilder_foreach(_packbuilder, foreach_cancel_cb, idx), -1111);
261 git_indexer_free(idx);
262 }