]> git.proxmox.com Git - libgit2.git/blob - tests/repo/init.c
Merge pull request #3432 from ethomson/mkdir
[libgit2.git] / tests / repo / init.c
1 #include "clar_libgit2.h"
2 #include "fileops.h"
3 #include "repository.h"
4 #include "config.h"
5 #include "path.h"
6 #include "config/config_helpers.h"
7
8 enum repo_mode {
9 STANDARD_REPOSITORY = 0,
10 BARE_REPOSITORY = 1
11 };
12
13 static git_repository *_repo = NULL;
14 static mode_t g_umask = 0;
15
16 void test_repo_init__initialize(void)
17 {
18 _repo = NULL;
19
20 /* load umask if not already loaded */
21 if (!g_umask) {
22 g_umask = p_umask(022);
23 (void)p_umask(g_umask);
24 }
25 }
26
27 static void cleanup_repository(void *path)
28 {
29 git_repository_free(_repo);
30 _repo = NULL;
31
32 cl_fixture_cleanup((const char *)path);
33 }
34
35 static void ensure_repository_init(
36 const char *working_directory,
37 int is_bare,
38 const char *expected_path_repository,
39 const char *expected_working_directory)
40 {
41 const char *workdir;
42
43 cl_assert(!git_path_isdir(working_directory));
44
45 cl_git_pass(git_repository_init(&_repo, working_directory, is_bare));
46
47 workdir = git_repository_workdir(_repo);
48 if (workdir != NULL || expected_working_directory != NULL) {
49 cl_assert(
50 git__suffixcmp(workdir, expected_working_directory) == 0
51 );
52 }
53
54 cl_assert(
55 git__suffixcmp(git_repository_path(_repo), expected_path_repository) == 0
56 );
57
58 cl_assert(git_repository_is_bare(_repo) == is_bare);
59
60 #ifdef GIT_WIN32
61 if (!is_bare) {
62 DWORD fattrs = GetFileAttributes(git_repository_path(_repo));
63 cl_assert((fattrs & FILE_ATTRIBUTE_HIDDEN) != 0);
64 }
65 #endif
66
67 cl_assert(git_repository_is_empty(_repo));
68 }
69
70 void test_repo_init__standard_repo(void)
71 {
72 cl_set_cleanup(&cleanup_repository, "testrepo");
73 ensure_repository_init("testrepo/", 0, "testrepo/.git/", "testrepo/");
74 }
75
76 void test_repo_init__standard_repo_noslash(void)
77 {
78 cl_set_cleanup(&cleanup_repository, "testrepo");
79 ensure_repository_init("testrepo", 0, "testrepo/.git/", "testrepo/");
80 }
81
82 void test_repo_init__bare_repo(void)
83 {
84 cl_set_cleanup(&cleanup_repository, "testrepo.git");
85 ensure_repository_init("testrepo.git/", 1, "testrepo.git/", NULL);
86 }
87
88 void test_repo_init__bare_repo_noslash(void)
89 {
90 cl_set_cleanup(&cleanup_repository, "testrepo.git");
91 ensure_repository_init("testrepo.git", 1, "testrepo.git/", NULL);
92 }
93
94 void test_repo_init__bare_repo_escaping_current_workdir(void)
95 {
96 git_buf path_repository = GIT_BUF_INIT;
97 git_buf path_current_workdir = GIT_BUF_INIT;
98
99 cl_git_pass(git_path_prettify_dir(&path_current_workdir, ".", NULL));
100
101 cl_git_pass(git_buf_joinpath(&path_repository, git_buf_cstr(&path_current_workdir), "a/b/c"));
102 cl_git_pass(git_futils_mkdir_r(git_buf_cstr(&path_repository), GIT_DIR_MODE));
103
104 /* Change the current working directory */
105 cl_git_pass(chdir(git_buf_cstr(&path_repository)));
106
107 /* Initialize a bare repo with a relative path escaping out of the current working directory */
108 cl_git_pass(git_repository_init(&_repo, "../d/e.git", 1));
109 cl_git_pass(git__suffixcmp(git_repository_path(_repo), "/a/b/d/e.git/"));
110
111 git_repository_free(_repo);
112
113 /* Open a bare repo with a relative path escaping out of the current working directory */
114 cl_git_pass(git_repository_open(&_repo, "../d/e.git"));
115
116 cl_git_pass(chdir(git_buf_cstr(&path_current_workdir)));
117
118 git_buf_free(&path_current_workdir);
119 git_buf_free(&path_repository);
120
121 cleanup_repository("a");
122 }
123
124 void test_repo_init__reinit_bare_repo(void)
125 {
126 cl_set_cleanup(&cleanup_repository, "reinit.git");
127
128 /* Initialize the repository */
129 cl_git_pass(git_repository_init(&_repo, "reinit.git", 1));
130 git_repository_free(_repo);
131
132 /* Reinitialize the repository */
133 cl_git_pass(git_repository_init(&_repo, "reinit.git", 1));
134 }
135
136 void test_repo_init__reinit_too_recent_bare_repo(void)
137 {
138 git_config *config;
139
140 /* Initialize the repository */
141 cl_git_pass(git_repository_init(&_repo, "reinit.git", 1));
142 git_repository_config(&config, _repo);
143
144 /*
145 * Hack the config of the repository to make it look like it has
146 * been created by a recenter version of git/libgit2
147 */
148 cl_git_pass(git_config_set_int32(config, "core.repositoryformatversion", 42));
149
150 git_config_free(config);
151 git_repository_free(_repo);
152
153 /* Try to reinitialize the repository */
154 cl_git_fail(git_repository_init(&_repo, "reinit.git", 1));
155
156 cl_fixture_cleanup("reinit.git");
157 }
158
159 void test_repo_init__additional_templates(void)
160 {
161 git_buf path = GIT_BUF_INIT;
162
163 cl_set_cleanup(&cleanup_repository, "tester");
164
165 ensure_repository_init("tester", 0, "tester/.git/", "tester/");
166
167 cl_git_pass(
168 git_buf_joinpath(&path, git_repository_path(_repo), "description"));
169 cl_assert(git_path_isfile(git_buf_cstr(&path)));
170
171 cl_git_pass(
172 git_buf_joinpath(&path, git_repository_path(_repo), "info/exclude"));
173 cl_assert(git_path_isfile(git_buf_cstr(&path)));
174
175 cl_git_pass(
176 git_buf_joinpath(&path, git_repository_path(_repo), "hooks"));
177 cl_assert(git_path_isdir(git_buf_cstr(&path)));
178 /* won't confirm specific contents of hooks dir since it may vary */
179
180 git_buf_free(&path);
181 }
182
183 static void assert_config_entry_on_init_bytype(
184 const char *config_key, int expected_value, bool is_bare)
185 {
186 git_config *config;
187 int error, current_value;
188 const char *repo_path = is_bare ?
189 "config_entry/test.bare.git" : "config_entry/test.non.bare.git";
190
191 cl_set_cleanup(&cleanup_repository, "config_entry");
192
193 cl_git_pass(git_repository_init(&_repo, repo_path, is_bare));
194
195 cl_git_pass(git_repository_config(&config, _repo));
196 error = git_config_get_bool(&current_value, config, config_key);
197 git_config_free(config);
198
199 if (expected_value >= 0) {
200 cl_assert_equal_i(0, error);
201 cl_assert_equal_i(expected_value, current_value);
202 } else {
203 cl_assert_equal_i(expected_value, error);
204 }
205 }
206
207 static void assert_config_entry_on_init(
208 const char *config_key, int expected_value)
209 {
210 assert_config_entry_on_init_bytype(config_key, expected_value, true);
211 git_repository_free(_repo);
212
213 assert_config_entry_on_init_bytype(config_key, expected_value, false);
214 }
215
216 void test_repo_init__detect_filemode(void)
217 {
218 assert_config_entry_on_init("core.filemode", cl_is_chmod_supported());
219 }
220
221 void test_repo_init__detect_ignorecase(void)
222 {
223 struct stat st;
224 bool found_without_match;
225
226 cl_git_write2file("testCAPS", "whatever\n", 0, O_CREAT | O_WRONLY, 0666);
227 found_without_match = (p_stat("Testcaps", &st) == 0);
228 cl_must_pass(p_unlink("testCAPS"));
229
230 assert_config_entry_on_init(
231 "core.ignorecase", found_without_match ? true : GIT_ENOTFOUND);
232 }
233
234 void test_repo_init__detect_precompose_unicode_required(void)
235 {
236 #ifdef GIT_USE_ICONV
237 char *composed = "ḱṷṓn", *decomposed = "ḱṷṓn";
238 struct stat st;
239 bool found_with_nfd;
240
241 cl_git_write2file(composed, "whatever\n", 0, O_CREAT | O_WRONLY, 0666);
242 found_with_nfd = (p_stat(decomposed, &st) == 0);
243 cl_must_pass(p_unlink(composed));
244
245 assert_config_entry_on_init("core.precomposeunicode", found_with_nfd);
246 #else
247 assert_config_entry_on_init("core.precomposeunicode", GIT_ENOTFOUND);
248 #endif
249 }
250
251 void test_repo_init__reinit_doesnot_overwrite_ignorecase(void)
252 {
253 git_config *config;
254 int current_value;
255
256 /* Init a new repo */
257 cl_set_cleanup(&cleanup_repository, "not.overwrite.git");
258 cl_git_pass(git_repository_init(&_repo, "not.overwrite.git", 1));
259
260 /* Change the "core.ignorecase" config value to something unlikely */
261 git_repository_config(&config, _repo);
262 git_config_set_int32(config, "core.ignorecase", 42);
263 git_config_free(config);
264 git_repository_free(_repo);
265 _repo = NULL;
266
267 /* Reinit the repository */
268 cl_git_pass(git_repository_init(&_repo, "not.overwrite.git", 1));
269 git_repository_config(&config, _repo);
270
271 /* Ensure the "core.ignorecase" config value hasn't been updated */
272 cl_git_pass(git_config_get_int32(&current_value, config, "core.ignorecase"));
273 cl_assert_equal_i(42, current_value);
274
275 git_config_free(config);
276 }
277
278 void test_repo_init__reinit_overwrites_filemode(void)
279 {
280 int expected = cl_is_chmod_supported(), current_value;
281
282 /* Init a new repo */
283 cl_set_cleanup(&cleanup_repository, "overwrite.git");
284 cl_git_pass(git_repository_init(&_repo, "overwrite.git", 1));
285
286 /* Change the "core.filemode" config value to something unlikely */
287 cl_repo_set_bool(_repo, "core.filemode", !expected);
288
289 git_repository_free(_repo);
290 _repo = NULL;
291
292 /* Reinit the repository */
293 cl_git_pass(git_repository_init(&_repo, "overwrite.git", 1));
294
295 /* Ensure the "core.filemode" config value has been reset */
296 current_value = cl_repo_get_bool(_repo, "core.filemode");
297 cl_assert_equal_i(expected, current_value);
298 }
299
300 void test_repo_init__sets_logAllRefUpdates_according_to_type_of_repository(void)
301 {
302 assert_config_entry_on_init_bytype("core.logallrefupdates", GIT_ENOTFOUND, true);
303 git_repository_free(_repo);
304 assert_config_entry_on_init_bytype("core.logallrefupdates", true, false);
305 }
306
307 void test_repo_init__extended_0(void)
308 {
309 git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
310
311 /* without MKDIR this should fail */
312 cl_git_fail(git_repository_init_ext(&_repo, "extended", &opts));
313
314 /* make the directory first, then it should succeed */
315 cl_git_pass(git_futils_mkdir("extended", 0775, 0));
316 cl_git_pass(git_repository_init_ext(&_repo, "extended", &opts));
317
318 cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "/extended/"));
319 cl_assert(!git__suffixcmp(git_repository_path(_repo), "/extended/.git/"));
320 cl_assert(!git_repository_is_bare(_repo));
321 cl_assert(git_repository_is_empty(_repo));
322
323 cleanup_repository("extended");
324 }
325
326 void test_repo_init__extended_1(void)
327 {
328 git_reference *ref;
329 git_remote *remote;
330 struct stat st;
331 git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
332
333 opts.flags = GIT_REPOSITORY_INIT_MKPATH |
334 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR;
335 opts.mode = GIT_REPOSITORY_INIT_SHARED_GROUP;
336 opts.workdir_path = "../c_wd";
337 opts.description = "Awesomest test repository evah";
338 opts.initial_head = "development";
339 opts.origin_url = "https://github.com/libgit2/libgit2.git";
340
341 cl_git_pass(git_repository_init_ext(&_repo, "root/b/c.git", &opts));
342
343 cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "/c_wd/"));
344 cl_assert(!git__suffixcmp(git_repository_path(_repo), "/c.git/"));
345 cl_assert(git_path_isfile("root/b/c_wd/.git"));
346 cl_assert(!git_repository_is_bare(_repo));
347 /* repo will not be counted as empty because we set head to "development" */
348 cl_assert(!git_repository_is_empty(_repo));
349
350 cl_git_pass(git_path_lstat(git_repository_path(_repo), &st));
351 cl_assert(S_ISDIR(st.st_mode));
352 if (cl_is_chmod_supported())
353 cl_assert((S_ISGID & st.st_mode) == S_ISGID);
354 else
355 cl_assert((S_ISGID & st.st_mode) == 0);
356
357 cl_git_pass(git_reference_lookup(&ref, _repo, "HEAD"));
358 cl_assert(git_reference_type(ref) == GIT_REF_SYMBOLIC);
359 cl_assert_equal_s("refs/heads/development", git_reference_symbolic_target(ref));
360 git_reference_free(ref);
361
362 cl_git_pass(git_remote_lookup(&remote, _repo, "origin"));
363 cl_assert_equal_s("origin", git_remote_name(remote));
364 cl_assert_equal_s(opts.origin_url, git_remote_url(remote));
365 git_remote_free(remote);
366
367 git_repository_free(_repo);
368 cl_fixture_cleanup("root");
369 }
370
371 void test_repo_init__relative_gitdir(void)
372 {
373 git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
374 git_buf dot_git_content = GIT_BUF_INIT;
375
376 opts.workdir_path = "../c_wd";
377 opts.flags =
378 GIT_REPOSITORY_INIT_MKPATH |
379 GIT_REPOSITORY_INIT_RELATIVE_GITLINK |
380 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR;
381
382 /* make the directory first, then it should succeed */
383 cl_git_pass(git_repository_init_ext(&_repo, "root/b/my_repository", &opts));
384
385 cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "root/b/c_wd/"));
386 cl_assert(!git__suffixcmp(git_repository_path(_repo), "root/b/my_repository/"));
387 cl_assert(!git_repository_is_bare(_repo));
388 cl_assert(git_repository_is_empty(_repo));
389
390 /* Verify that the gitlink and worktree entries are relative */
391
392 /* Verify worktree */
393 assert_config_entry_value(_repo, "core.worktree", "../c_wd/");
394
395 /* Verify gitlink */
396 cl_git_pass(git_futils_readbuffer(&dot_git_content, "root/b/c_wd/.git"));
397 cl_assert_equal_s("gitdir: ../my_repository/", dot_git_content.ptr);
398
399 git_buf_free(&dot_git_content);
400 cleanup_repository("root");
401 }
402
403 void test_repo_init__relative_gitdir_2(void)
404 {
405 git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
406 git_buf dot_git_content = GIT_BUF_INIT;
407 git_buf full_path = GIT_BUF_INIT;
408
409 cl_git_pass(git_path_prettify(&full_path, ".", NULL));
410 cl_git_pass(git_buf_joinpath(&full_path, full_path.ptr, "root/b/c_wd"));
411
412 opts.workdir_path = full_path.ptr;
413 opts.flags =
414 GIT_REPOSITORY_INIT_MKPATH |
415 GIT_REPOSITORY_INIT_RELATIVE_GITLINK |
416 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR;
417
418 /* make the directory first, then it should succeed */
419 cl_git_pass(git_repository_init_ext(&_repo, "root/b/my_repository", &opts));
420 git_buf_free(&full_path);
421
422 cl_assert(!git__suffixcmp(git_repository_workdir(_repo), "root/b/c_wd/"));
423 cl_assert(!git__suffixcmp(git_repository_path(_repo), "root/b/my_repository/"));
424 cl_assert(!git_repository_is_bare(_repo));
425 cl_assert(git_repository_is_empty(_repo));
426
427 /* Verify that the gitlink and worktree entries are relative */
428
429 /* Verify worktree */
430 assert_config_entry_value(_repo, "core.worktree", "../c_wd/");
431
432 /* Verify gitlink */
433 cl_git_pass(git_futils_readbuffer(&dot_git_content, "root/b/c_wd/.git"));
434 cl_assert_equal_s("gitdir: ../my_repository/", dot_git_content.ptr);
435
436 git_buf_free(&dot_git_content);
437 cleanup_repository("root");
438 }
439
440 #define CLEAR_FOR_CORE_FILEMODE(M) ((M) &= ~0177)
441
442 static void assert_hooks_match(
443 const char *template_dir,
444 const char *repo_dir,
445 const char *hook_path,
446 bool core_filemode)
447 {
448 git_buf expected = GIT_BUF_INIT;
449 git_buf actual = GIT_BUF_INIT;
450 struct stat expected_st, st;
451
452 cl_git_pass(git_buf_joinpath(&expected, template_dir, hook_path));
453 cl_git_pass(git_path_lstat(expected.ptr, &expected_st));
454
455 cl_git_pass(git_buf_joinpath(&actual, repo_dir, hook_path));
456 cl_git_pass(git_path_lstat(actual.ptr, &st));
457
458 cl_assert(expected_st.st_size == st.st_size);
459
460 if (GIT_MODE_TYPE(expected_st.st_mode) != GIT_FILEMODE_LINK) {
461 mode_t expected_mode =
462 GIT_MODE_TYPE(expected_st.st_mode) |
463 (GIT_PERMS_FOR_WRITE(expected_st.st_mode) & ~g_umask);
464
465 if (!core_filemode) {
466 CLEAR_FOR_CORE_FILEMODE(expected_mode);
467 CLEAR_FOR_CORE_FILEMODE(st.st_mode);
468 }
469
470 cl_assert_equal_i_fmt(expected_mode, st.st_mode, "%07o");
471 }
472
473 git_buf_free(&expected);
474 git_buf_free(&actual);
475 }
476
477 static void assert_mode_seems_okay(
478 const char *base, const char *path,
479 git_filemode_t expect_mode, bool expect_setgid, bool core_filemode)
480 {
481 git_buf full = GIT_BUF_INIT;
482 struct stat st;
483
484 cl_git_pass(git_buf_joinpath(&full, base, path));
485 cl_git_pass(git_path_lstat(full.ptr, &st));
486 git_buf_free(&full);
487
488 if (!core_filemode) {
489 CLEAR_FOR_CORE_FILEMODE(expect_mode);
490 CLEAR_FOR_CORE_FILEMODE(st.st_mode);
491 expect_setgid = false;
492 }
493
494 if (S_ISGID != 0)
495 cl_assert_equal_b(expect_setgid, (st.st_mode & S_ISGID) != 0);
496
497 cl_assert_equal_b(
498 GIT_PERMS_IS_EXEC(expect_mode), GIT_PERMS_IS_EXEC(st.st_mode));
499
500 cl_assert_equal_i_fmt(
501 GIT_MODE_TYPE(expect_mode), GIT_MODE_TYPE(st.st_mode), "%07o");
502 }
503
504 static const char *template_sandbox(const char *name)
505 {
506 git_buf hooks_path = GIT_BUF_INIT, link_path = GIT_BUF_INIT;
507 const char *path = cl_fixture(name);
508
509 cl_fixture_sandbox(name);
510
511 /* create a symlink from link.sample to update.sample if the filesystem
512 * supports it.
513 */
514
515 cl_git_pass(git_buf_joinpath(&hooks_path, name, "hooks"));
516 cl_git_pass(git_buf_joinpath(&link_path, hooks_path.ptr, "link.sample"));
517
518 #ifdef GIT_WIN32
519 cl_git_mkfile(link_path.ptr, "#!/bin/sh\necho hello, world\n");
520 #else
521 cl_must_pass(symlink("update.sample", link_path.ptr));
522 #endif
523
524 git_buf_free(&link_path);
525 git_buf_free(&hooks_path);
526
527 return path;
528 }
529
530 void test_repo_init__extended_with_template(void)
531 {
532 git_buf expected = GIT_BUF_INIT;
533 git_buf actual = GIT_BUF_INIT;
534 git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
535 int filemode;
536
537 cl_set_cleanup(&cleanup_repository, "templated.git");
538 template_sandbox("template");
539
540 opts.flags = GIT_REPOSITORY_INIT_MKPATH | GIT_REPOSITORY_INIT_BARE |
541 GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
542 opts.template_path = "template";
543
544 cl_git_pass(git_repository_init_ext(&_repo, "templated.git", &opts));
545
546 cl_assert(git_repository_is_bare(_repo));
547
548 cl_assert(!git__suffixcmp(git_repository_path(_repo), "/templated.git/"));
549
550 cl_git_pass(git_futils_readbuffer(&expected, "template/description"));
551 cl_git_pass(git_futils_readbuffer(
552 &actual, "templated.git/description"));
553
554 cl_assert_equal_s(expected.ptr, actual.ptr);
555
556 git_buf_free(&expected);
557 git_buf_free(&actual);
558
559 filemode = cl_repo_get_bool(_repo, "core.filemode");
560
561 assert_hooks_match(
562 "template", git_repository_path(_repo),
563 "hooks/update.sample", filemode);
564
565 assert_hooks_match(
566 "template", git_repository_path(_repo),
567 "hooks/link.sample", filemode);
568
569 cl_fixture_cleanup("template");
570 }
571
572 void test_repo_init__extended_with_template_and_shared_mode(void)
573 {
574 git_buf expected = GIT_BUF_INIT;
575 git_buf actual = GIT_BUF_INIT;
576 git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
577 int filemode = true;
578 const char *repo_path = NULL;
579
580 cl_set_cleanup(&cleanup_repository, "init_shared_from_tpl");
581 template_sandbox("template");
582
583 opts.flags = GIT_REPOSITORY_INIT_MKPATH |
584 GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE;
585 opts.template_path = "template";
586 opts.mode = GIT_REPOSITORY_INIT_SHARED_GROUP;
587
588 cl_git_pass(git_repository_init_ext(&_repo, "init_shared_from_tpl", &opts));
589
590 cl_assert(!git_repository_is_bare(_repo));
591 cl_assert(!git__suffixcmp(git_repository_path(_repo), "/init_shared_from_tpl/.git/"));
592
593 filemode = cl_repo_get_bool(_repo, "core.filemode");
594
595 cl_git_pass(git_futils_readbuffer(
596 &expected, "template/description"));
597 cl_git_pass(git_futils_readbuffer(
598 &actual, "init_shared_from_tpl/.git/description"));
599
600 cl_assert_equal_s(expected.ptr, actual.ptr);
601
602 git_buf_free(&expected);
603 git_buf_free(&actual);
604
605 repo_path = git_repository_path(_repo);
606 assert_mode_seems_okay(repo_path, "hooks",
607 GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode);
608 assert_mode_seems_okay(repo_path, "info",
609 GIT_FILEMODE_TREE | GIT_REPOSITORY_INIT_SHARED_GROUP, true, filemode);
610 assert_mode_seems_okay(repo_path, "description",
611 GIT_FILEMODE_BLOB, false, filemode);
612
613 /* for a non-symlinked hook, it should have shared permissions now */
614 assert_hooks_match(
615 "template", git_repository_path(_repo),
616 "hooks/update.sample", filemode);
617
618 /* for a symlinked hook, the permissions still should match the
619 * source link, not the GIT_REPOSITORY_INIT_SHARED_GROUP value
620 */
621 assert_hooks_match(
622 "template", git_repository_path(_repo),
623 "hooks/link.sample", filemode);
624
625 cl_fixture_cleanup("template");
626 }
627
628 void test_repo_init__can_reinit_an_initialized_repository(void)
629 {
630 git_repository *reinit;
631
632 cl_set_cleanup(&cleanup_repository, "extended");
633
634 cl_git_pass(git_futils_mkdir("extended", 0775, 0));
635 cl_git_pass(git_repository_init(&_repo, "extended", false));
636
637 cl_git_pass(git_repository_init(&reinit, "extended", false));
638
639 cl_assert_equal_s(git_repository_path(_repo), git_repository_path(reinit));
640
641 git_repository_free(reinit);
642 }
643
644 void test_repo_init__init_with_initial_commit(void)
645 {
646 git_index *index;
647
648 cl_set_cleanup(&cleanup_repository, "committed");
649
650 /* Initialize the repository */
651 cl_git_pass(git_repository_init(&_repo, "committed", 0));
652
653 /* Init will be automatically created when requested for a new repo */
654 cl_git_pass(git_repository_index(&index, _repo));
655
656 /* Create a file so we can commit it
657 *
658 * If you are writing code outside the test suite, you can create this
659 * file any way that you like, such as:
660 * FILE *fp = fopen("committed/file.txt", "w");
661 * fputs("some stuff\n", fp);
662 * fclose(fp);
663 * We like to use the help functions because they do error detection
664 * in a way that's easily compatible with our test suite.
665 */
666 cl_git_mkfile("committed/file.txt", "some stuff\n");
667
668 /* Add file to the index */
669 cl_git_pass(git_index_add_bypath(index, "file.txt"));
670 cl_git_pass(git_index_write(index));
671
672 /* Intentionally not using cl_repo_commit_from_index here so this code
673 * can be used as an example of how an initial commit is typically
674 * made to a repository...
675 */
676
677 /* Make sure we're ready to use git_signature_default :-) */
678 {
679 git_config *cfg, *local;
680 cl_git_pass(git_repository_config(&cfg, _repo));
681 cl_git_pass(git_config_open_level(&local, cfg, GIT_CONFIG_LEVEL_LOCAL));
682 cl_git_pass(git_config_set_string(local, "user.name", "Test User"));
683 cl_git_pass(git_config_set_string(local, "user.email", "t@example.com"));
684 git_config_free(local);
685 git_config_free(cfg);
686 }
687
688 /* Create a commit with the new contents of the index */
689 {
690 git_signature *sig;
691 git_oid tree_id, commit_id;
692 git_tree *tree;
693
694 cl_git_pass(git_signature_default(&sig, _repo));
695 cl_git_pass(git_index_write_tree(&tree_id, index));
696 cl_git_pass(git_tree_lookup(&tree, _repo, &tree_id));
697
698 cl_git_pass(git_commit_create_v(
699 &commit_id, _repo, "HEAD", sig, sig,
700 NULL, "First", tree, 0));
701
702 git_tree_free(tree);
703 git_signature_free(sig);
704 }
705
706 git_index_free(index);
707 }
708
709 void test_repo_init__at_filesystem_root(void)
710 {
711 git_repository *repo;
712 const char *sandbox = clar_sandbox_path();
713 git_buf root = GIT_BUF_INIT;
714 int root_len;
715
716 if (!cl_is_env_set("GITTEST_INVASIVE_FS_STRUCTURE"))
717 cl_skip();
718
719 root_len = git_path_root(sandbox);
720 cl_assert(root_len >= 0);
721
722 git_buf_put(&root, sandbox, root_len+1);
723 git_buf_joinpath(&root, root.ptr, "libgit2_test_dir");
724
725 cl_assert(!git_path_exists(root.ptr));
726
727 cl_git_pass(git_repository_init(&repo, root.ptr, 0));
728 cl_assert(git_path_isdir(root.ptr));
729 cl_git_pass(git_futils_rmdir_r(root.ptr, NULL, GIT_RMDIR_REMOVE_FILES));
730
731 git_buf_free(&root);
732 git_repository_free(repo);
733 }