]> git.proxmox.com Git - libgit2.git/blame - tests/refs/create.c
New upstream version 1.1.0+dfsg.1
[libgit2.git] / tests / refs / create.c
CommitLineData
00a48934
BS
1#include "clar_libgit2.h"
2
3#include "repository.h"
4#include "git2/reflog.h"
5#include "reflog.h"
d00d5464 6#include "ref_helpers.h"
00a48934 7
3e026f1b 8static const char *current_master_tip = "099fabac3a9ea935598528c27f866e34089c2eff";
00a48934
BS
9static const char *current_head_target = "refs/heads/master";
10
11static git_repository *g_repo;
12
471bb8b1 13void test_refs_create__initialize(void)
00a48934 14{
b84e58f4 15 g_repo = cl_git_sandbox_init("testrepo");
af3dcb0e 16 p_fsync__cnt = 0;
00a48934
BS
17}
18
471bb8b1 19void test_refs_create__cleanup(void)
00a48934 20{
b84e58f4 21 cl_git_sandbox_cleanup();
98c34149 22
d22a8b95 23 cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, 1));
d2b3a21f 24 cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, 1));
6c23704d 25 cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_FSYNC_GITDIR, 0));
00a48934
BS
26}
27
471bb8b1 28void test_refs_create__symbolic(void)
00a48934 29{
b84e58f4 30 /* create a new symbolic reference */
00a48934
BS
31 git_reference *new_reference, *looked_up_ref, *resolved_ref;
32 git_repository *repo2;
33 git_oid id;
00a48934 34
77e06d7e 35 const char *new_head_tracker = "ANOTHER_HEAD_TRACKER";
00a48934
BS
36
37 git_oid_fromstr(&id, current_master_tip);
38
00a48934 39 /* Create and write the new symbolic reference */
659cf202 40 cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, current_head_target, 0, NULL));
00a48934
BS
41
42 /* Ensure the reference can be looked-up... */
43 cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head_tracker));
ac3d33df 44 cl_assert(git_reference_type(looked_up_ref) & GIT_REFERENCE_SYMBOLIC);
d00d5464 45 cl_assert(reference_is_packed(looked_up_ref) == 0);
946a6dc4 46 cl_assert_equal_s(looked_up_ref->name, new_head_tracker);
00a48934
BS
47
48 /* ...peeled.. */
49 cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
ac3d33df 50 cl_assert(git_reference_type(resolved_ref) == GIT_REFERENCE_DIRECT);
00a48934
BS
51
52 /* ...and that it points to the current master tip */
0cee70eb 53 cl_assert_equal_oid(&id, git_reference_target(resolved_ref));
00a48934
BS
54 git_reference_free(looked_up_ref);
55 git_reference_free(resolved_ref);
56
57 /* Similar test with a fresh new repository */
58 cl_git_pass(git_repository_open(&repo2, "testrepo"));
59
60 cl_git_pass(git_reference_lookup(&looked_up_ref, repo2, new_head_tracker));
61 cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
0cee70eb 62 cl_assert_equal_oid(&id, git_reference_target(resolved_ref));
00a48934
BS
63
64 git_repository_free(repo2);
65
66 git_reference_free(new_reference);
67 git_reference_free(looked_up_ref);
68 git_reference_free(resolved_ref);
69}
70
d2b3a21f
RI
71void test_refs_create__symbolic_with_arbitrary_content(void)
72{
73 git_reference *new_reference, *looked_up_ref;
74 git_repository *repo2;
75 git_oid id;
76
77 const char *new_head_tracker = "ANOTHER_HEAD_TRACKER";
78 const char *arbitrary_target = "ARBITRARY DATA";
79
80 git_oid_fromstr(&id, current_master_tip);
81
82 /* Attempt to create symbolic ref with arbitrary data in target
83 * fails by default
84 */
85 cl_git_fail(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, arbitrary_target, 0, NULL));
86
87 git_libgit2_opts(GIT_OPT_ENABLE_STRICT_SYMBOLIC_REF_CREATION, 0);
88
89 /* With strict target validation disabled, ref creation succeeds */
90 cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, arbitrary_target, 0, NULL));
91
92 /* Ensure the reference can be looked-up... */
93 cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head_tracker));
ac3d33df 94 cl_assert(git_reference_type(looked_up_ref) & GIT_REFERENCE_SYMBOLIC);
d2b3a21f
RI
95 cl_assert(reference_is_packed(looked_up_ref) == 0);
96 cl_assert_equal_s(looked_up_ref->name, new_head_tracker);
5aa1f12a 97 git_reference_free(looked_up_ref);
d2b3a21f
RI
98
99 /* Ensure the target is what we expect it to be */
100 cl_assert_equal_s(git_reference_symbolic_target(new_reference), arbitrary_target);
101
102 /* Similar test with a fresh new repository object */
103 cl_git_pass(git_repository_open(&repo2, "testrepo"));
104
105 /* Ensure the reference can be looked-up... */
106 cl_git_pass(git_reference_lookup(&looked_up_ref, repo2, new_head_tracker));
ac3d33df 107 cl_assert(git_reference_type(looked_up_ref) & GIT_REFERENCE_SYMBOLIC);
d2b3a21f
RI
108 cl_assert(reference_is_packed(looked_up_ref) == 0);
109 cl_assert_equal_s(looked_up_ref->name, new_head_tracker);
110
111 /* Ensure the target is what we expect it to be */
112 cl_assert_equal_s(git_reference_symbolic_target(new_reference), arbitrary_target);
113
114 git_repository_free(repo2);
115 git_reference_free(new_reference);
116 git_reference_free(looked_up_ref);
d2b3a21f
RI
117}
118
471bb8b1 119void test_refs_create__deep_symbolic(void)
00a48934 120{
b84e58f4 121 /* create a deep symbolic reference */
00a48934
BS
122 git_reference *new_reference, *looked_up_ref, *resolved_ref;
123 git_oid id;
00a48934
BS
124
125 const char *new_head_tracker = "deep/rooted/tracker";
126
127 git_oid_fromstr(&id, current_master_tip);
128
659cf202 129 cl_git_pass(git_reference_symbolic_create(&new_reference, g_repo, new_head_tracker, current_head_target, 0, NULL));
00a48934
BS
130 cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head_tracker));
131 cl_git_pass(git_reference_resolve(&resolved_ref, looked_up_ref));
0cee70eb 132 cl_assert_equal_oid(&id, git_reference_target(resolved_ref));
00a48934
BS
133
134 git_reference_free(new_reference);
135 git_reference_free(looked_up_ref);
136 git_reference_free(resolved_ref);
00a48934
BS
137}
138
471bb8b1 139void test_refs_create__oid(void)
00a48934 140{
b84e58f4 141 /* create a new OID reference */
00a48934
BS
142 git_reference *new_reference, *looked_up_ref;
143 git_repository *repo2;
144 git_oid id;
00a48934
BS
145
146 const char *new_head = "refs/heads/new-head";
147
148 git_oid_fromstr(&id, current_master_tip);
149
00a48934 150 /* Create and write the new object id reference */
659cf202 151 cl_git_pass(git_reference_create(&new_reference, g_repo, new_head, &id, 0, NULL));
00a48934
BS
152
153 /* Ensure the reference can be looked-up... */
154 cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head));
ac3d33df 155 cl_assert(git_reference_type(looked_up_ref) & GIT_REFERENCE_DIRECT);
d00d5464 156 cl_assert(reference_is_packed(looked_up_ref) == 0);
946a6dc4 157 cl_assert_equal_s(looked_up_ref->name, new_head);
00a48934
BS
158
159 /* ...and that it points to the current master tip */
0cee70eb 160 cl_assert_equal_oid(&id, git_reference_target(looked_up_ref));
00a48934
BS
161 git_reference_free(looked_up_ref);
162
163 /* Similar test with a fresh new repository */
164 cl_git_pass(git_repository_open(&repo2, "testrepo"));
165
166 cl_git_pass(git_reference_lookup(&looked_up_ref, repo2, new_head));
0cee70eb 167 cl_assert_equal_oid(&id, git_reference_target(looked_up_ref));
00a48934
BS
168
169 git_repository_free(repo2);
170
171 git_reference_free(new_reference);
172 git_reference_free(looked_up_ref);
00a48934
BS
173}
174
98c34149 175/* Can by default create a reference that targets at an unknown id */
d22a8b95 176void test_refs_create__oid_unknown_succeeds_without_strict(void)
98c34149
ET
177{
178 git_reference *new_reference, *looked_up_ref;
179 git_oid id;
180
181 const char *new_head = "refs/heads/new-head";
182
183 git_oid_fromstr(&id, "deadbeef3f795b2b4353bcce3a527ad0a4f7f644");
184
d22a8b95
ET
185 cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, 0));
186
98c34149
ET
187 /* Create and write the new object id reference */
188 cl_git_pass(git_reference_create(&new_reference, g_repo, new_head, &id, 0, NULL));
9b3fc895 189 git_reference_free(new_reference);
98c34149
ET
190
191 /* Ensure the reference can't be looked-up... */
192 cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, new_head));
193 git_reference_free(looked_up_ref);
194}
195
196/* Strict object enforcement enforces valid object id */
d22a8b95 197void test_refs_create__oid_unknown_fails_by_default(void)
00a48934 198{
00a48934
BS
199 git_reference *new_reference, *looked_up_ref;
200 git_oid id;
201
202 const char *new_head = "refs/heads/new-head";
203
204 git_oid_fromstr(&id, "deadbeef3f795b2b4353bcce3a527ad0a4f7f644");
205
206 /* Create and write the new object id reference */
659cf202 207 cl_git_fail(git_reference_create(&new_reference, g_repo, new_head, &id, 0, NULL));
00a48934
BS
208
209 /* Ensure the reference can't be looked-up... */
210 cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, new_head));
211}
c1281493
CMN
212
213void test_refs_create__propagate_eexists(void)
214{
c1281493 215 git_oid oid;
c1281493
CMN
216
217 /* Make sure it works for oid and for symbolic both */
22a2d3d5
UG
218 cl_git_pass(git_oid_fromstr(&oid, current_master_tip));
219 cl_git_fail_with(GIT_EEXISTS, git_reference_create(NULL, g_repo, current_head_target, &oid, false, NULL));
220 cl_git_fail_with(GIT_EEXISTS, git_reference_symbolic_create(NULL, g_repo, "HEAD", current_head_target, false, NULL));
c1281493 221}
80d9d1df 222
b46c7ee5
ET
223void test_refs_create__existing_dir_propagates_edirectory(void)
224{
225 git_reference *new_reference, *fail_reference;
226 git_oid id;
227 const char *dir_head = "refs/heads/new-dir/new-head",
228 *fail_head = "refs/heads/new-dir";
229
230 git_oid_fromstr(&id, current_master_tip);
231
232 /* Create and write the new object id reference */
233 cl_git_pass(git_reference_create(&new_reference, g_repo, dir_head, &id, 1, NULL));
234 cl_git_fail_with(GIT_EDIRECTORY,
235 git_reference_create(&fail_reference, g_repo, fail_head, &id, false, NULL));
236
237 git_reference_free(new_reference);
238}
239
ee5da720 240static void test_invalid_name(const char *name)
80d9d1df 241{
242 git_reference *new_reference;
243 git_oid id;
244
80d9d1df 245 git_oid_fromstr(&id, current_master_tip);
246
247 cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_create(
659cf202 248 &new_reference, g_repo, name, &id, 0, NULL));
80d9d1df 249
250 cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_symbolic_create(
659cf202 251 &new_reference, g_repo, name, current_head_target, 0, NULL));
80d9d1df 252}
ee5da720
ET
253
254void test_refs_create__creating_a_reference_with_an_invalid_name_returns_EINVALIDSPEC(void)
255{
256 test_invalid_name("refs/heads/inv@{id");
257 test_invalid_name("refs/heads/back\\slash");
258
259 test_invalid_name("refs/heads/foo ");
260 test_invalid_name("refs/heads/foo /bar");
261 test_invalid_name("refs/heads/com1:bar/foo");
262
263 test_invalid_name("refs/heads/e:");
264 test_invalid_name("refs/heads/c:/foo");
265
266 test_invalid_name("refs/heads/foo.");
267}
268
269static void test_win32_name(const char *name)
270{
271 git_reference *new_reference = NULL;
272 git_oid id;
273 int ret;
274
275 git_oid_fromstr(&id, current_master_tip);
276
659cf202 277 ret = git_reference_create(&new_reference, g_repo, name, &id, 0, NULL);
ee5da720
ET
278
279#ifdef GIT_WIN32
280 cl_assert_equal_i(GIT_EINVALIDSPEC, ret);
281#else
282 cl_git_pass(ret);
283#endif
284
285 git_reference_free(new_reference);
286}
287
288void test_refs_create__creating_a_loose_ref_with_invalid_windows_name(void)
289{
290 test_win32_name("refs/heads/foo./bar");
291
292 test_win32_name("refs/heads/aux");
293 test_win32_name("refs/heads/aux.foo/bar");
294
295 test_win32_name("refs/heads/com1");
296}
af3dcb0e 297
1c04a96b
ET
298/* Creating a loose ref involves fsync'ing the reference, the
299 * reflog and (on non-Windows) the containing directories.
300 * Creating a packed ref involves fsync'ing the packed ref file
301 * and (on non-Windows) the containing directory.
302 */
303#ifdef GIT_WIN32
304static int expected_fsyncs_create = 2, expected_fsyncs_compress = 1;
305#else
306static int expected_fsyncs_create = 4, expected_fsyncs_compress = 2;
307#endif
308
309static void count_fsyncs(size_t *create_count, size_t *compress_count)
af3dcb0e
ET
310{
311 git_reference *ref = NULL;
eb56ed81 312 git_refdb *refdb;
af3dcb0e
ET
313 git_oid id;
314
1c04a96b
ET
315 p_fsync__cnt = 0;
316
af3dcb0e
ET
317 git_oid_fromstr(&id, current_master_tip);
318 cl_git_pass(git_reference_create(&ref, g_repo, "refs/heads/fsync_test", &id, 0, "log message"));
319 git_reference_free(ref);
eb56ed81 320
1c04a96b
ET
321 *create_count = p_fsync__cnt;
322 p_fsync__cnt = 0;
323
eb56ed81
ET
324 cl_git_pass(git_repository_refdb(&refdb, g_repo));
325 cl_git_pass(git_refdb_compress(refdb));
326 git_refdb_free(refdb);
327
1c04a96b
ET
328 *compress_count = p_fsync__cnt;
329 p_fsync__cnt = 0;
af3dcb0e
ET
330}
331
1c04a96b 332void test_refs_create__does_not_fsync_by_default(void)
af3dcb0e 333{
1c04a96b
ET
334 size_t create_count, compress_count;
335 count_fsyncs(&create_count, &compress_count);
af3dcb0e 336
1c04a96b
ET
337 cl_assert_equal_i(0, create_count);
338 cl_assert_equal_i(0, compress_count);
339}
340
341void test_refs_create__fsyncs_when_global_opt_set(void)
342{
343 size_t create_count, compress_count;
3ac05d11 344
6c23704d 345 cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_FSYNC_GITDIR, 1));
1c04a96b 346 count_fsyncs(&create_count, &compress_count);
af3dcb0e 347
1c04a96b
ET
348 cl_assert_equal_i(expected_fsyncs_create, create_count);
349 cl_assert_equal_i(expected_fsyncs_compress, compress_count);
350}
eb56ed81 351
1c04a96b
ET
352void test_refs_create__fsyncs_when_repo_config_set(void)
353{
354 size_t create_count, compress_count;
eb56ed81 355
1c04a96b
ET
356 cl_repo_set_bool(g_repo, "core.fsyncObjectFiles", true);
357
358 count_fsyncs(&create_count, &compress_count);
eb56ed81 359
1c04a96b
ET
360 cl_assert_equal_i(expected_fsyncs_create, create_count);
361 cl_assert_equal_i(expected_fsyncs_compress, compress_count);
af3dcb0e 362}