void test_checkout_icase__conflicts_with_casechanged_subtrees(void) { git_reference *orig_ref; git_object *orig, *subtrees; git_oid oid; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; cl_git_pass(git_reference_lookup_resolved(&orig_ref, repo, "HEAD", 100)); cl_git_pass(git_object_lookup(&orig, repo, git_reference_target(orig_ref), GIT_OBJ_COMMIT)); cl_git_pass(git_reset(repo, (git_object *)orig, GIT_RESET_HARD, NULL)); cl_must_pass(p_mkdir("testrepo/AB", 0777)); cl_must_pass(p_mkdir("testrepo/AB/C", 0777)); cl_git_write2file("testrepo/AB/C/3.txt", "Foobar!\n", 8, O_RDWR|O_CREAT, 0666); cl_git_pass(git_reference_name_to_id(&oid, repo, "refs/heads/subtrees")); cl_git_pass(git_object_lookup(&subtrees, repo, &oid, GIT_OBJ_ANY)); cl_git_fail(git_checkout_tree(repo, subtrees, &checkout_opts)); git_object_free(orig); git_object_free(subtrees); git_reference_free(orig_ref); }
void test_path_win32__8dot3_name(void) { #ifdef GIT_WIN32 char *shortname; if (!cl_sandbox_supports_8dot3()) clar__skip(); /* Some guaranteed short names */ cl_assert_equal_s("PROGRA~1", (shortname = git_win32_path_8dot3_name("C:\\Program Files"))); git__free(shortname); cl_assert_equal_s("WINDOWS", (shortname = git_win32_path_8dot3_name("C:\\WINDOWS"))); git__free(shortname); /* Create some predictible short names */ cl_must_pass(p_mkdir(".foo", 0777)); cl_assert_equal_s("FOO~1", (shortname = git_win32_path_8dot3_name(".foo"))); git__free(shortname); cl_git_write2file("bar~1", "foobar\n", 7, O_RDWR|O_CREAT, 0666); cl_must_pass(p_mkdir(".bar", 0777)); cl_assert_equal_s("BAR~2", (shortname = git_win32_path_8dot3_name(".bar"))); git__free(shortname); #endif }
void test_checkout_icase__refuses_to_overwrite_files_for_files(void) { checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING; cl_git_write2file("testrepo/BRANCH_FILE.txt", "neue file\n", 10, \ O_WRONLY | O_CREAT | O_TRUNC, 0644); cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts)); assert_name_is("testrepo/BRANCH_FILE.txt"); }
void test_checkout_icase__overwrites_files_for_files_when_forced(void) { checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_git_write2file("testrepo/NEW.txt", "neue file\n", 10, \ O_WRONLY | O_CREAT | O_TRUNC, 0644); cl_git_pass(git_checkout_tree(repo, obj, &checkout_opts)); assert_name_is("testrepo/new.txt"); }
void test_index_filemodes__trusted(void) { git_index *index; /* Only run these tests on platforms where I can actually * chmod a file and get the stat results I expect! */ if (!cl_is_chmod_supported()) return; cl_repo_set_bool(g_repo, "core.filemode", true); cl_git_pass(git_repository_index(&index, g_repo)); cl_assert((git_index_caps(index) & GIT_INDEXCAP_NO_FILEMODE) == 0); /* 1 - add 0644 over existing 0644 -> expect 0644 */ replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644); add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB); /* 2 - add 0644 over existing 0755 -> expect 0644 */ replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644); add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB); /* 3 - add 0755 over existing 0644 -> expect 0755 */ replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755); add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB_EXECUTABLE); /* 4 - add 0755 over existing 0755 -> expect 0755 */ replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755); add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); /* 5 - add new 0644 -> expect 0644 */ cl_git_write2file("filemodes/new_off", "blah", 0, O_WRONLY | O_CREAT | O_TRUNC, 0644); add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); /* 6 - add 0755 -> expect 0755 */ cl_git_write2file("filemodes/new_on", "blah", 0, O_WRONLY | O_CREAT | O_TRUNC, 0755); add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB_EXECUTABLE); git_index_free(index); }
void test_repo_init__detect_ignorecase(void) { struct stat st; bool found_without_match; cl_git_write2file("testCAPS", "whatever\n", 0, O_CREAT | O_WRONLY, 0666); found_without_match = (p_stat("Testcaps", &st) == 0); cl_must_pass(p_unlink("testCAPS")); assert_config_entry_on_init( "core.ignorecase", found_without_match ? true : GIT_ENOTFOUND); }
/* A tree that contains an entry "git~2", when we have forced the short * name for ".git" into "GIT~2". */ void test_checkout_nasty__git_custom_shortname(void) { #ifdef GIT_WIN32 if (!cl_sandbox_supports_8dot3()) clar__skip(); cl_must_pass(p_rename("nasty/.git", "nasty/_temp")); cl_git_write2file("nasty/git~1", "", 0, O_RDWR|O_CREAT, 0666); cl_must_pass(p_rename("nasty/_temp", "nasty/.git")); test_checkout_fails("refs/heads/git_tilde2", ".git/foobar"); #endif }
void test_checkout_icase__refuses_to_overwrite_populated_folders_for_files(void) { checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE|GIT_CHECKOUT_RECREATE_MISSING; cl_must_pass(p_mkdir("testrepo/BRANCH_FILE.txt", 0777)); cl_git_write2file("testrepo/BRANCH_FILE.txt/foobar", "neue file\n", 10, \ O_WRONLY | O_CREAT | O_TRUNC, 0644); cl_git_fail(git_checkout_tree(repo, obj, &checkout_opts)); assert_name_is("testrepo/BRANCH_FILE.txt"); cl_assert(git_path_isdir("testrepo/BRANCH_FILE.txt")); }
void update_attr_callback( const char *path, size_t completed_steps, size_t total_steps, void *payload) { GIT_UNUSED(completed_steps); GIT_UNUSED(total_steps); GIT_UNUSED(payload); if (path && strcmp(path, "ident1.txt") == 0) cl_git_write2file("testrepo/.gitattributes", "*.txt ident\n", 12, O_RDWR|O_CREAT, 0666); }
void test_index_filemodes__untrusted(void) { git_index *index; cl_repo_set_bool(g_repo, "core.filemode", false); cl_git_pass(git_repository_index(&index, g_repo)); cl_assert((git_index_caps(index) & GIT_INDEXCAP_NO_FILEMODE) != 0); /* 1 - add 0644 over existing 0644 -> expect 0644 */ replace_file_with_mode("exec_off", "filemodes/exec_off.0", 0644); add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB); /* 2 - add 0644 over existing 0755 -> expect 0755 */ replace_file_with_mode("exec_on", "filemodes/exec_on.0", 0644); add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); /* 3 - add 0755 over existing 0644 -> expect 0644 */ replace_file_with_mode("exec_off", "filemodes/exec_off.1", 0755); add_and_check_mode(index, "exec_off", GIT_FILEMODE_BLOB); /* 4 - add 0755 over existing 0755 -> expect 0755 */ replace_file_with_mode("exec_on", "filemodes/exec_on.1", 0755); add_and_check_mode(index, "exec_on", GIT_FILEMODE_BLOB_EXECUTABLE); /* 5 - add new 0644 -> expect 0644 */ cl_git_write2file("filemodes/new_off", "blah", 0, O_WRONLY | O_CREAT | O_TRUNC, 0644); add_and_check_mode(index, "new_off", GIT_FILEMODE_BLOB); /* 6 - add new 0755 -> expect 0644 if core.filemode == false */ cl_git_write2file("filemodes/new_on", "blah", 0, O_WRONLY | O_CREAT | O_TRUNC, 0755); add_and_check_mode(index, "new_on", GIT_FILEMODE_BLOB); git_index_free(index); }
void test_repo_init__detect_precompose_unicode_required(void) { #ifdef GIT_USE_ICONV char *composed = "ḱṷṓn", *decomposed = "ḱṷṓn"; struct stat st; bool found_with_nfd; cl_git_write2file(composed, "whatever\n", 0, O_CREAT | O_WRONLY, 0666); found_with_nfd = (p_stat(decomposed, &st) == 0); cl_must_pass(p_unlink(composed)); assert_config_entry_on_init("core.precomposeunicode", found_with_nfd); #else assert_config_entry_on_init("core.precomposeunicode", GIT_ENOTFOUND); #endif }
static void replace_file_with_mode( const char *filename, const char *backup, unsigned int create_mode) { git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT; cl_git_pass(git_buf_joinpath(&path, "filemodes", filename)); cl_git_pass(git_buf_printf(&content, "%s as %08u (%d)", filename, create_mode, rand())); cl_git_pass(p_rename(path.ptr, backup)); cl_git_write2file( path.ptr, content.ptr, content.size, O_WRONLY|O_CREAT|O_TRUNC, create_mode); git_buf_free(&path); git_buf_free(&content); }
bool cl_sandbox_supports_8dot3(void) { git_buf longpath = GIT_BUF_INIT; char *shortname; bool supported; cl_git_pass( git_buf_joinpath(&longpath, clar_sandbox_path(), "longer_than_8dot3")); cl_git_write2file(longpath.ptr, "", 0, O_RDWR|O_CREAT, 0666); shortname = git_win32_path_8dot3_name(longpath.ptr); supported = (shortname != NULL); git__free(shortname); git_buf_free(&longpath); return supported; }
/* A tree that contains an entry "git~3", which should be allowed, since * it is not the typical short name ("GIT~1") or the actual short name * ("GIT~2") for ".git". */ void test_checkout_nasty__only_looks_like_a_git_shortname(void) { #ifdef GIT_WIN32 git_oid commit_id; git_commit *commit; git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; cl_must_pass(p_rename("nasty/.git", "nasty/_temp")); cl_git_write2file("nasty/git~1", "", 0, O_RDWR|O_CREAT, 0666); cl_must_pass(p_rename("nasty/_temp", "nasty/.git")); cl_git_pass(git_reference_name_to_id(&commit_id, repo, "refs/heads/git_tilde3")); cl_git_pass(git_commit_lookup(&commit, repo, &commit_id)); opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_git_pass(git_checkout_tree(repo, (const git_object *)commit, &opts)); cl_assert(git_path_exists("nasty/git~3/foobar")); git_commit_free(commit); #endif }
/* Ensures that custom shortnames are included: creates a GIT~1 so that the * .git folder itself will have to be named GIT~2 */ void test_repo_reservedname__custom_shortname_recognized(void) { #ifdef GIT_WIN32 git_repository *repo; git_buf *reserved; size_t reserved_len; if (!cl_sandbox_supports_8dot3()) clar__skip(); repo = cl_git_sandbox_init("nasty"); cl_must_pass(p_rename("nasty/.git", "nasty/_temp")); cl_git_write2file("nasty/git~1", "", 0, O_RDWR|O_CREAT, 0666); cl_must_pass(p_rename("nasty/_temp", "nasty/.git")); cl_assert(git_repository__reserved_names(&reserved, &reserved_len, repo, true)); cl_assert_equal_i(3, reserved_len); cl_assert_equal_s(".git", reserved[0].ptr); cl_assert_equal_s("GIT~1", reserved[1].ptr); cl_assert_equal_s("GIT~2", reserved[2].ptr); #endif }
void test_submodule_update__can_force_update(void) { git_submodule *sm = NULL; git_checkout_options checkout_options = GIT_CHECKOUT_OPTIONS_INIT; git_submodule_update_options update_options = GIT_SUBMODULE_UPDATE_OPTIONS_INIT; unsigned int submodule_status = 0; git_reference *branch_reference = NULL; git_object *branch_commit = NULL; g_repo = setup_fixture_submodule_simple(); /* Initialize and update the sub repository */ cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo")); cl_git_pass(git_submodule_status(&submodule_status, sm)); cl_assert_equal_i(submodule_status, GIT_SUBMODULE_STATUS_IN_HEAD | GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS_IN_CONFIG | GIT_SUBMODULE_STATUS_WD_UNINITIALIZED); cl_git_pass(git_submodule_update(sm, 1, &update_options)); /* verify expected state */ cl_assert(git_oid_streq(git_submodule_head_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); cl_assert(git_oid_streq(git_submodule_index_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); /* checkout the alternate_1 branch */ checkout_options.checkout_strategy = GIT_CHECKOUT_SAFE; cl_git_pass(git_reference_lookup(&branch_reference, g_repo, "refs/heads/alternate_1")); cl_git_pass(git_reference_peel(&branch_commit, branch_reference, GIT_OBJ_COMMIT)); cl_git_pass(git_checkout_tree(g_repo, branch_commit, &checkout_options)); cl_git_pass(git_repository_set_head(g_repo, git_reference_name(branch_reference))); /* * Verify state after checkout of parent repository. The submodule ID in the * HEAD commit and index should be updated, but not the workdir. */ cl_git_pass(git_submodule_status(&submodule_status, sm)); cl_assert_equal_i(submodule_status, GIT_SUBMODULE_STATUS_IN_HEAD | GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS_IN_CONFIG | GIT_SUBMODULE_STATUS_IN_WD | GIT_SUBMODULE_STATUS_WD_MODIFIED); cl_assert(git_oid_streq(git_submodule_head_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "be3563ae3f795b2b4353bcce3a527ad0a4f7f644") == 0); cl_assert(git_oid_streq(git_submodule_index_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); /* * Create a conflicting edit in the subrepository to verify that * the submodule update action is blocked. */ cl_git_write2file("submodule_simple/testrepo/branch_file.txt", "a conflicting edit", 0, O_WRONLY | O_CREAT | O_TRUNC, 0777); /* forcefully checkout and verify the submodule state was updated. */ update_options.checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; cl_git_pass(git_submodule_update(sm, 0, &update_options)); cl_assert(git_oid_streq(git_submodule_head_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); cl_assert(git_oid_streq(git_submodule_index_id(sm), "a65fedf39aefe402d3bb6e24df4d4f5fe4547750") == 0); git_submodule_free(sm); git_object_free(branch_commit); git_reference_free(branch_reference); }
void cl_git_rewritefile(const char *filename, const char *new_content) { cl_git_write2file(filename, new_content, O_WRONLY | O_CREAT | O_TRUNC, 0644); }
void cl_git_append2file(const char *filename, const char *new_content) { cl_git_write2file(filename, new_content, O_WRONLY | O_CREAT | O_APPEND, 0644); }
void cl_git_append2file(const char *path, const char *content) { cl_git_write2file(path, content, 0, O_WRONLY | O_CREAT | O_APPEND, 0644); }
void cl_git_rewritefile(const char *path, const char *content) { cl_git_write2file(path, content, 0, O_WRONLY | O_CREAT | O_TRUNC, 0644); }