1 #include "clar_libgit2.h"
3 #include "repository.h"
8 STANDARD_REPOSITORY
= 0,
12 static git_repository
*_repo
= NULL
;
13 static mode_t g_umask
= 0;
15 void test_repo_init__initialize(void)
19 /* load umask if not already loaded */
21 g_umask
= p_umask(022);
22 (void)p_umask(g_umask
);
26 static void cleanup_repository(void *path
)
28 git_repository_free(_repo
);
31 cl_fixture_cleanup((const char *)path
);
34 static void ensure_repository_init(
35 const char *working_directory
,
37 const char *expected_path_repository
,
38 const char *expected_working_directory
)
42 cl_assert(!git_path_isdir(working_directory
));
44 cl_git_pass(git_repository_init(&_repo
, working_directory
, is_bare
));
46 workdir
= git_repository_workdir(_repo
);
47 if (workdir
!= NULL
|| expected_working_directory
!= NULL
) {
49 git__suffixcmp(workdir
, expected_working_directory
) == 0
54 git__suffixcmp(git_repository_path(_repo
), expected_path_repository
) == 0
57 cl_assert(git_repository_is_bare(_repo
) == is_bare
);
61 DWORD fattrs
= GetFileAttributes(git_repository_path(_repo
));
62 cl_assert((fattrs
& FILE_ATTRIBUTE_HIDDEN
) != 0);
66 cl_assert(git_repository_is_empty(_repo
));
69 void test_repo_init__standard_repo(void)
71 cl_set_cleanup(&cleanup_repository
, "testrepo");
72 ensure_repository_init("testrepo/", 0, "testrepo/.git/", "testrepo/");
75 void test_repo_init__standard_repo_noslash(void)
77 cl_set_cleanup(&cleanup_repository
, "testrepo");
78 ensure_repository_init("testrepo", 0, "testrepo/.git/", "testrepo/");
81 void test_repo_init__bare_repo(void)
83 cl_set_cleanup(&cleanup_repository
, "testrepo.git");
84 ensure_repository_init("testrepo.git/", 1, "testrepo.git/", NULL
);
87 void test_repo_init__bare_repo_noslash(void)
89 cl_set_cleanup(&cleanup_repository
, "testrepo.git");
90 ensure_repository_init("testrepo.git", 1, "testrepo.git/", NULL
);
93 void test_repo_init__bare_repo_escaping_current_workdir(void)
95 git_buf path_repository
= GIT_BUF_INIT
;
96 git_buf path_current_workdir
= GIT_BUF_INIT
;
98 cl_git_pass(git_path_prettify_dir(&path_current_workdir
, ".", NULL
));
100 cl_git_pass(git_buf_joinpath(&path_repository
, git_buf_cstr(&path_current_workdir
), "a/b/c"));
101 cl_git_pass(git_futils_mkdir_r(git_buf_cstr(&path_repository
), NULL
, GIT_DIR_MODE
));
103 /* Change the current working directory */
104 cl_git_pass(chdir(git_buf_cstr(&path_repository
)));
106 /* Initialize a bare repo with a relative path escaping out of the current working directory */
107 cl_git_pass(git_repository_init(&_repo
, "../d/e.git", 1));
108 cl_git_pass(git__suffixcmp(git_repository_path(_repo
), "/a/b/d/e.git/"));
110 git_repository_free(_repo
);
112 /* Open a bare repo with a relative path escaping out of the current working directory */
113 cl_git_pass(git_repository_open(&_repo
, "../d/e.git"));
115 cl_git_pass(chdir(git_buf_cstr(&path_current_workdir
)));
117 git_buf_free(&path_current_workdir
);
118 git_buf_free(&path_repository
);
120 cleanup_repository("a");
123 void test_repo_init__reinit_bare_repo(void)
125 cl_set_cleanup(&cleanup_repository
, "reinit.git");
127 /* Initialize the repository */
128 cl_git_pass(git_repository_init(&_repo
, "reinit.git", 1));
129 git_repository_free(_repo
);
131 /* Reinitialize the repository */
132 cl_git_pass(git_repository_init(&_repo
, "reinit.git", 1));
135 void test_repo_init__reinit_too_recent_bare_repo(void)
139 /* Initialize the repository */
140 cl_git_pass(git_repository_init(&_repo
, "reinit.git", 1));
141 git_repository_config(&config
, _repo
);
144 * Hack the config of the repository to make it look like it has
145 * been created by a recenter version of git/libgit2
147 cl_git_pass(git_config_set_int32(config
, "core.repositoryformatversion", 42));
149 git_config_free(config
);
150 git_repository_free(_repo
);
152 /* Try to reinitialize the repository */
153 cl_git_fail(git_repository_init(&_repo
, "reinit.git", 1));
155 cl_fixture_cleanup("reinit.git");
158 void test_repo_init__additional_templates(void)
160 git_buf path
= GIT_BUF_INIT
;
162 cl_set_cleanup(&cleanup_repository
, "tester");
164 ensure_repository_init("tester", 0, "tester/.git/", "tester/");
167 git_buf_joinpath(&path
, git_repository_path(_repo
), "description"));
168 cl_assert(git_path_isfile(git_buf_cstr(&path
)));
171 git_buf_joinpath(&path
, git_repository_path(_repo
), "info/exclude"));
172 cl_assert(git_path_isfile(git_buf_cstr(&path
)));
175 git_buf_joinpath(&path
, git_repository_path(_repo
), "hooks"));
176 cl_assert(git_path_isdir(git_buf_cstr(&path
)));
177 /* won't confirm specific contents of hooks dir since it may vary */
182 static void assert_config_entry_on_init_bytype(
183 const char *config_key
, int expected_value
, bool is_bare
)
186 int error
, current_value
;
187 const char *repo_path
= is_bare
?
188 "config_entry/test.bare.git" : "config_entry/test.non.bare.git";
190 cl_set_cleanup(&cleanup_repository
, "config_entry");
192 cl_git_pass(git_repository_init(&_repo
, repo_path
, is_bare
));
194 cl_git_pass(git_repository_config(&config
, _repo
));
195 error
= git_config_get_bool(¤t_value
, config
, config_key
);
196 git_config_free(config
);
198 if (expected_value
>= 0) {
199 cl_assert_equal_i(0, error
);
200 cl_assert_equal_i(expected_value
, current_value
);
202 cl_assert_equal_i(expected_value
, error
);
206 static void assert_config_entry_on_init(
207 const char *config_key
, int expected_value
)
209 assert_config_entry_on_init_bytype(config_key
, expected_value
, true);
210 git_repository_free(_repo
);
212 assert_config_entry_on_init_bytype(config_key
, expected_value
, false);
215 void test_repo_init__detect_filemode(void)
217 assert_config_entry_on_init("core.filemode", cl_is_chmod_supported());
220 void test_repo_init__detect_ignorecase(void)
223 bool found_without_match
;
225 cl_git_write2file("testCAPS", "whatever\n", 0, O_CREAT
| O_WRONLY
, 0666);
226 found_without_match
= (p_stat("Testcaps", &st
) == 0);
227 cl_must_pass(p_unlink("testCAPS"));
229 assert_config_entry_on_init(
230 "core.ignorecase", found_without_match
? true : GIT_ENOTFOUND
);
233 void test_repo_init__detect_precompose_unicode_required(void)
236 char *composed
= "ḱṷṓn", *decomposed
= "ḱṷṓn";
240 cl_git_write2file(composed
, "whatever\n", 0, O_CREAT
| O_WRONLY
, 0666);
241 found_with_nfd
= (p_stat(decomposed
, &st
) == 0);
242 cl_must_pass(p_unlink(composed
));
244 assert_config_entry_on_init("core.precomposeunicode", found_with_nfd
);
246 assert_config_entry_on_init("core.precomposeunicode", GIT_ENOTFOUND
);
250 void test_repo_init__reinit_doesnot_overwrite_ignorecase(void)
255 /* Init a new repo */
256 cl_set_cleanup(&cleanup_repository
, "not.overwrite.git");
257 cl_git_pass(git_repository_init(&_repo
, "not.overwrite.git", 1));
259 /* Change the "core.ignorecase" config value to something unlikely */
260 git_repository_config(&config
, _repo
);
261 git_config_set_int32(config
, "core.ignorecase", 42);
262 git_config_free(config
);
263 git_repository_free(_repo
);
266 /* Reinit the repository */
267 cl_git_pass(git_repository_init(&_repo
, "not.overwrite.git", 1));
268 git_repository_config(&config
, _repo
);
270 /* Ensure the "core.ignorecase" config value hasn't been updated */
271 cl_git_pass(git_config_get_int32(¤t_value
, config
, "core.ignorecase"));
272 cl_assert_equal_i(42, current_value
);
274 git_config_free(config
);
277 void test_repo_init__reinit_overwrites_filemode(void)
279 int expected
= cl_is_chmod_supported(), current_value
;
281 /* Init a new repo */
282 cl_set_cleanup(&cleanup_repository
, "overwrite.git");
283 cl_git_pass(git_repository_init(&_repo
, "overwrite.git", 1));
285 /* Change the "core.filemode" config value to something unlikely */
286 cl_repo_set_bool(_repo
, "core.filemode", !expected
);
288 git_repository_free(_repo
);
291 /* Reinit the repository */
292 cl_git_pass(git_repository_init(&_repo
, "overwrite.git", 1));
294 /* Ensure the "core.filemode" config value has been reset */
295 current_value
= cl_repo_get_bool(_repo
, "core.filemode");
296 cl_assert_equal_i(expected
, current_value
);
299 void test_repo_init__sets_logAllRefUpdates_according_to_type_of_repository(void)
301 assert_config_entry_on_init_bytype("core.logallrefupdates", GIT_ENOTFOUND
, true);
302 git_repository_free(_repo
);
303 assert_config_entry_on_init_bytype("core.logallrefupdates", true, false);
306 void test_repo_init__extended_0(void)
308 git_repository_init_options opts
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
310 /* without MKDIR this should fail */
311 cl_git_fail(git_repository_init_ext(&_repo
, "extended", &opts
));
313 /* make the directory first, then it should succeed */
314 cl_git_pass(git_futils_mkdir("extended", NULL
, 0775, 0));
315 cl_git_pass(git_repository_init_ext(&_repo
, "extended", &opts
));
317 cl_assert(!git__suffixcmp(git_repository_workdir(_repo
), "/extended/"));
318 cl_assert(!git__suffixcmp(git_repository_path(_repo
), "/extended/.git/"));
319 cl_assert(!git_repository_is_bare(_repo
));
320 cl_assert(git_repository_is_empty(_repo
));
322 cleanup_repository("extended");
325 void test_repo_init__extended_1(void)
330 git_repository_init_options opts
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
332 opts
.flags
= GIT_REPOSITORY_INIT_MKPATH
|
333 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
;
334 opts
.mode
= GIT_REPOSITORY_INIT_SHARED_GROUP
;
335 opts
.workdir_path
= "../c_wd";
336 opts
.description
= "Awesomest test repository evah";
337 opts
.initial_head
= "development";
338 opts
.origin_url
= "https://github.com/libgit2/libgit2.git";
340 cl_git_pass(git_repository_init_ext(&_repo
, "root/b/c.git", &opts
));
342 cl_assert(!git__suffixcmp(git_repository_workdir(_repo
), "/c_wd/"));
343 cl_assert(!git__suffixcmp(git_repository_path(_repo
), "/c.git/"));
344 cl_assert(git_path_isfile("root/b/c_wd/.git"));
345 cl_assert(!git_repository_is_bare(_repo
));
346 /* repo will not be counted as empty because we set head to "development" */
347 cl_assert(!git_repository_is_empty(_repo
));
349 cl_git_pass(git_path_lstat(git_repository_path(_repo
), &st
));
350 cl_assert(S_ISDIR(st
.st_mode
));
351 if (cl_is_chmod_supported())
352 cl_assert((S_ISGID
& st
.st_mode
) == S_ISGID
);
354 cl_assert((S_ISGID
& st
.st_mode
) == 0);
356 cl_git_pass(git_reference_lookup(&ref
, _repo
, "HEAD"));
357 cl_assert(git_reference_type(ref
) == GIT_REF_SYMBOLIC
);
358 cl_assert_equal_s("refs/heads/development", git_reference_symbolic_target(ref
));
359 git_reference_free(ref
);
361 cl_git_pass(git_remote_load(&remote
, _repo
, "origin"));
362 cl_assert_equal_s("origin", git_remote_name(remote
));
363 cl_assert_equal_s(opts
.origin_url
, git_remote_url(remote
));
364 git_remote_free(remote
);
366 git_repository_free(_repo
);
367 cl_fixture_cleanup("root");
370 void test_repo_init__relative_gitdir(void)
372 git_repository_init_options opts
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
374 const char *worktree_path
;
375 git_buf dot_git_content
= GIT_BUF_INIT
;
377 opts
.workdir_path
= "../c_wd";
379 GIT_REPOSITORY_INIT_MKPATH
|
380 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
|
381 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
;
383 /* make the directory first, then it should succeed */
384 cl_git_pass(git_repository_init_ext(&_repo
, "root/b/my_repository", &opts
));
386 cl_assert(!git__suffixcmp(git_repository_workdir(_repo
), "root/b/c_wd/"));
387 cl_assert(!git__suffixcmp(git_repository_path(_repo
), "root/b/my_repository/"));
388 cl_assert(!git_repository_is_bare(_repo
));
389 cl_assert(git_repository_is_empty(_repo
));
391 /* Verify that the gitlink and worktree entries are relative */
393 /* Verify worktree */
394 cl_git_pass(git_repository_config(&cfg
, _repo
));
395 cl_git_pass(git_config_get_string(&worktree_path
, cfg
, "core.worktree"));
396 cl_assert_equal_s("../c_wd/", worktree_path
);
399 cl_git_pass(git_futils_readbuffer(&dot_git_content
, "root/b/c_wd/.git"));
400 cl_assert_equal_s("gitdir: ../my_repository/", dot_git_content
.ptr
);
402 git_buf_free(&dot_git_content
);
403 git_config_free(cfg
);
404 cleanup_repository("root");
407 void test_repo_init__relative_gitdir_2(void)
409 git_repository_init_options opts
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
411 const char *worktree_path
;
412 git_buf dot_git_content
= GIT_BUF_INIT
;
413 git_buf full_path
= GIT_BUF_INIT
;
415 cl_git_pass(git_path_prettify(&full_path
, ".", NULL
));
416 cl_git_pass(git_buf_joinpath(&full_path
, full_path
.ptr
, "root/b/c_wd"));
418 opts
.workdir_path
= full_path
.ptr
;
420 GIT_REPOSITORY_INIT_MKPATH
|
421 GIT_REPOSITORY_INIT_RELATIVE_GITLINK
|
422 GIT_REPOSITORY_INIT_NO_DOTGIT_DIR
;
424 /* make the directory first, then it should succeed */
425 cl_git_pass(git_repository_init_ext(&_repo
, "root/b/my_repository", &opts
));
426 git_buf_free(&full_path
);
428 cl_assert(!git__suffixcmp(git_repository_workdir(_repo
), "root/b/c_wd/"));
429 cl_assert(!git__suffixcmp(git_repository_path(_repo
), "root/b/my_repository/"));
430 cl_assert(!git_repository_is_bare(_repo
));
431 cl_assert(git_repository_is_empty(_repo
));
433 /* Verify that the gitlink and worktree entries are relative */
435 /* Verify worktree */
436 cl_git_pass(git_repository_config(&cfg
, _repo
));
437 cl_git_pass(git_config_get_string(&worktree_path
, cfg
, "core.worktree"));
438 cl_assert_equal_s("../c_wd/", worktree_path
);
441 cl_git_pass(git_futils_readbuffer(&dot_git_content
, "root/b/c_wd/.git"));
442 cl_assert_equal_s("gitdir: ../my_repository/", dot_git_content
.ptr
);
444 git_buf_free(&dot_git_content
);
445 git_config_free(cfg
);
446 cleanup_repository("root");
449 #define CLEAR_FOR_CORE_FILEMODE(M) ((M) &= ~0177)
451 static void assert_hooks_match(
452 const char *template_dir
,
453 const char *repo_dir
,
454 const char *hook_path
,
457 git_buf expected
= GIT_BUF_INIT
;
458 git_buf actual
= GIT_BUF_INIT
;
459 struct stat expected_st
, st
;
461 cl_git_pass(git_buf_joinpath(&expected
, template_dir
, hook_path
));
462 cl_git_pass(git_path_lstat(expected
.ptr
, &expected_st
));
464 cl_git_pass(git_buf_joinpath(&actual
, repo_dir
, hook_path
));
465 cl_git_pass(git_path_lstat(actual
.ptr
, &st
));
467 cl_assert(expected_st
.st_size
== st
.st_size
);
469 if (GIT_MODE_TYPE(expected_st
.st_mode
) != GIT_FILEMODE_LINK
) {
470 mode_t expected_mode
=
471 GIT_MODE_TYPE(expected_st
.st_mode
) |
472 (GIT_PERMS_FOR_WRITE(expected_st
.st_mode
) & ~g_umask
);
474 if (!core_filemode
) {
475 CLEAR_FOR_CORE_FILEMODE(expected_mode
);
476 CLEAR_FOR_CORE_FILEMODE(st
.st_mode
);
479 cl_assert_equal_i_fmt(expected_mode
, st
.st_mode
, "%07o");
482 git_buf_free(&expected
);
483 git_buf_free(&actual
);
486 static void assert_mode_seems_okay(
487 const char *base
, const char *path
,
488 git_filemode_t expect_mode
, bool expect_setgid
, bool core_filemode
)
490 git_buf full
= GIT_BUF_INIT
;
493 cl_git_pass(git_buf_joinpath(&full
, base
, path
));
494 cl_git_pass(git_path_lstat(full
.ptr
, &st
));
497 if (!core_filemode
) {
498 CLEAR_FOR_CORE_FILEMODE(expect_mode
);
499 CLEAR_FOR_CORE_FILEMODE(st
.st_mode
);
500 expect_setgid
= false;
504 cl_assert_equal_b(expect_setgid
, (st
.st_mode
& S_ISGID
) != 0);
507 GIT_PERMS_IS_EXEC(expect_mode
), GIT_PERMS_IS_EXEC(st
.st_mode
));
509 cl_assert_equal_i_fmt(
510 GIT_MODE_TYPE(expect_mode
), GIT_MODE_TYPE(st
.st_mode
), "%07o");
513 void test_repo_init__extended_with_template(void)
515 git_buf expected
= GIT_BUF_INIT
;
516 git_buf actual
= GIT_BUF_INIT
;
517 git_repository_init_options opts
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
520 cl_set_cleanup(&cleanup_repository
, "templated.git");
522 opts
.flags
= GIT_REPOSITORY_INIT_MKPATH
| GIT_REPOSITORY_INIT_BARE
|
523 GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE
;
524 opts
.template_path
= cl_fixture("template");
526 cl_git_pass(git_repository_init_ext(&_repo
, "templated.git", &opts
));
528 cl_assert(git_repository_is_bare(_repo
));
530 cl_assert(!git__suffixcmp(git_repository_path(_repo
), "/templated.git/"));
532 cl_git_pass(git_futils_readbuffer(
533 &expected
, cl_fixture("template/description")));
534 cl_git_pass(git_futils_readbuffer(
535 &actual
, "templated.git/description"));
537 cl_assert_equal_s(expected
.ptr
, actual
.ptr
);
539 git_buf_free(&expected
);
540 git_buf_free(&actual
);
542 filemode
= cl_repo_get_bool(_repo
, "core.filemode");
545 cl_fixture("template"), git_repository_path(_repo
),
546 "hooks/update.sample", filemode
);
549 cl_fixture("template"), git_repository_path(_repo
),
550 "hooks/link.sample", filemode
);
553 void test_repo_init__extended_with_template_and_shared_mode(void)
555 git_buf expected
= GIT_BUF_INIT
;
556 git_buf actual
= GIT_BUF_INIT
;
557 git_repository_init_options opts
= GIT_REPOSITORY_INIT_OPTIONS_INIT
;
559 const char *repo_path
= NULL
;
561 cl_set_cleanup(&cleanup_repository
, "init_shared_from_tpl");
563 opts
.flags
= GIT_REPOSITORY_INIT_MKPATH
|
564 GIT_REPOSITORY_INIT_EXTERNAL_TEMPLATE
;
565 opts
.template_path
= cl_fixture("template");
566 opts
.mode
= GIT_REPOSITORY_INIT_SHARED_GROUP
;
568 cl_git_pass(git_repository_init_ext(&_repo
, "init_shared_from_tpl", &opts
));
570 cl_assert(!git_repository_is_bare(_repo
));
571 cl_assert(!git__suffixcmp(git_repository_path(_repo
), "/init_shared_from_tpl/.git/"));
573 filemode
= cl_repo_get_bool(_repo
, "core.filemode");
575 cl_git_pass(git_futils_readbuffer(
576 &expected
, cl_fixture("template/description")));
577 cl_git_pass(git_futils_readbuffer(
578 &actual
, "init_shared_from_tpl/.git/description"));
580 cl_assert_equal_s(expected
.ptr
, actual
.ptr
);
582 git_buf_free(&expected
);
583 git_buf_free(&actual
);
585 repo_path
= git_repository_path(_repo
);
586 assert_mode_seems_okay(repo_path
, "hooks",
587 GIT_FILEMODE_TREE
| GIT_REPOSITORY_INIT_SHARED_GROUP
, true, filemode
);
588 assert_mode_seems_okay(repo_path
, "info",
589 GIT_FILEMODE_TREE
| GIT_REPOSITORY_INIT_SHARED_GROUP
, true, filemode
);
590 assert_mode_seems_okay(repo_path
, "description",
591 GIT_FILEMODE_BLOB
, false, filemode
);
593 /* for a non-symlinked hook, it should have shared permissions now */
595 cl_fixture("template"), git_repository_path(_repo
),
596 "hooks/update.sample", filemode
);
598 /* for a symlinked hook, the permissions still should match the
599 * source link, not the GIT_REPOSITORY_INIT_SHARED_GROUP value
602 cl_fixture("template"), git_repository_path(_repo
),
603 "hooks/link.sample", filemode
);
606 void test_repo_init__can_reinit_an_initialized_repository(void)
608 git_repository
*reinit
;
610 cl_set_cleanup(&cleanup_repository
, "extended");
612 cl_git_pass(git_futils_mkdir("extended", NULL
, 0775, 0));
613 cl_git_pass(git_repository_init(&_repo
, "extended", false));
615 cl_git_pass(git_repository_init(&reinit
, "extended", false));
617 cl_assert_equal_s(git_repository_path(_repo
), git_repository_path(reinit
));
619 git_repository_free(reinit
);
622 void test_repo_init__init_with_initial_commit(void)
626 cl_set_cleanup(&cleanup_repository
, "committed");
628 /* Initialize the repository */
629 cl_git_pass(git_repository_init(&_repo
, "committed", 0));
631 /* Init will be automatically created when requested for a new repo */
632 cl_git_pass(git_repository_index(&index
, _repo
));
634 /* Create a file so we can commit it
636 * If you are writing code outside the test suite, you can create this
637 * file any way that you like, such as:
638 * FILE *fp = fopen("committed/file.txt", "w");
639 * fputs("some stuff\n", fp);
641 * We like to use the help functions because they do error detection
642 * in a way that's easily compatible with our test suite.
644 cl_git_mkfile("committed/file.txt", "some stuff\n");
646 /* Add file to the index */
647 cl_git_pass(git_index_add_bypath(index
, "file.txt"));
648 cl_git_pass(git_index_write(index
));
650 /* Intentionally not using cl_repo_commit_from_index here so this code
651 * can be used as an example of how an initial commit is typically
652 * made to a repository...
655 /* Make sure we're ready to use git_signature_default :-) */
657 git_config
*cfg
, *local
;
658 cl_git_pass(git_repository_config(&cfg
, _repo
));
659 cl_git_pass(git_config_open_level(&local
, cfg
, GIT_CONFIG_LEVEL_LOCAL
));
660 cl_git_pass(git_config_set_string(local
, "user.name", "Test User"));
661 cl_git_pass(git_config_set_string(local
, "user.email", "t@example.com"));
662 git_config_free(local
);
663 git_config_free(cfg
);
666 /* Create a commit with the new contents of the index */
669 git_oid tree_id
, commit_id
;
672 cl_git_pass(git_signature_default(&sig
, _repo
));
673 cl_git_pass(git_index_write_tree(&tree_id
, index
));
674 cl_git_pass(git_tree_lookup(&tree
, _repo
, &tree_id
));
676 cl_git_pass(git_commit_create_v(
677 &commit_id
, _repo
, "HEAD", sig
, sig
,
678 NULL
, "First", tree
, 0));
681 git_signature_free(sig
);
684 git_index_free(index
);