void test_attr_ignore__globs_and_path_delimiters(void) { cl_git_rewritefile("attr/.gitignore", "foo/bar/**"); assert_is_ignored(true, "foo/bar/baz"); assert_is_ignored(true, "foo/bar/baz/quux"); cl_git_rewritefile("attr/.gitignore", "_*/"); assert_is_ignored(true, "sub/_test/a/file"); assert_is_ignored(false, "test_folder/file"); assert_is_ignored(true, "_test/file"); assert_is_ignored(true, "_test/a/file"); cl_git_rewritefile("attr/.gitignore", "**/_*/"); assert_is_ignored(true, "sub/_test/a/file"); assert_is_ignored(false, "test_folder/file"); assert_is_ignored(true, "_test/file"); assert_is_ignored(true, "_test/a/file"); cl_git_rewritefile("attr/.gitignore", "**/_*/foo/bar/*ux"); assert_is_ignored(true, "sub/_test/foo/bar/qux/file"); assert_is_ignored(true, "_test/foo/bar/qux/file"); assert_is_ignored(true, "_test/foo/bar/crux/file"); assert_is_ignored(false, "_test/foo/bar/code/file"); }
void test_iterator_workdir__advance_over_with_pathlist(void) { git_vector pathlist = GIT_VECTOR_INIT; git_iterator *i; git_iterator_options i_opts = GIT_ITERATOR_OPTIONS_INIT; git_vector_insert(&pathlist, "dirA/subdir1/subdir2/file"); git_vector_insert(&pathlist, "dirB/subdir1/subdir2"); git_vector_insert(&pathlist, "dirC/subdir1/nonexistent"); git_vector_insert(&pathlist, "dirD/subdir1/nonexistent"); git_vector_insert(&pathlist, "dirD/subdir1/subdir2"); git_vector_insert(&pathlist, "dirD/nonexistent"); i_opts.pathlist.strings = (char **)pathlist.contents; i_opts.pathlist.count = pathlist.length; i_opts.flags |= GIT_ITERATOR_DONT_IGNORE_CASE | GIT_ITERATOR_DONT_AUTOEXPAND; g_repo = cl_git_sandbox_init("icase"); /* Create a directory that has a file that is included in our pathlist */ cl_must_pass(p_mkdir("icase/dirA", 0777)); cl_must_pass(p_mkdir("icase/dirA/subdir1", 0777)); cl_must_pass(p_mkdir("icase/dirA/subdir1/subdir2", 0777)); cl_git_rewritefile("icase/dirA/subdir1/subdir2/file", "foo!"); /* Create a directory that has a directory that is included in our pathlist */ cl_must_pass(p_mkdir("icase/dirB", 0777)); cl_must_pass(p_mkdir("icase/dirB/subdir1", 0777)); cl_must_pass(p_mkdir("icase/dirB/subdir1/subdir2", 0777)); cl_git_rewritefile("icase/dirB/subdir1/subdir2/file", "foo!"); /* Create a directory that would contain an entry in our pathlist, but * that entry does not actually exist. We don't know this until we * advance_over it. We want to distinguish this from an actually empty * or ignored directory. */ cl_must_pass(p_mkdir("icase/dirC", 0777)); cl_must_pass(p_mkdir("icase/dirC/subdir1", 0777)); cl_must_pass(p_mkdir("icase/dirC/subdir1/subdir2", 0777)); cl_git_rewritefile("icase/dirC/subdir1/subdir2/file", "foo!"); /* Create a directory that has a mix of actual and nonexistent paths */ cl_must_pass(p_mkdir("icase/dirD", 0777)); cl_must_pass(p_mkdir("icase/dirD/subdir1", 0777)); cl_must_pass(p_mkdir("icase/dirD/subdir1/subdir2", 0777)); cl_git_rewritefile("icase/dirD/subdir1/subdir2/file", "foo!"); cl_git_pass(git_iterator_for_workdir(&i, g_repo, NULL, NULL, &i_opts)); expect_advance_over(i, "dirA/", GIT_ITERATOR_STATUS_NORMAL); expect_advance_over(i, "dirB/", GIT_ITERATOR_STATUS_NORMAL); expect_advance_over(i, "dirC/", GIT_ITERATOR_STATUS_FILTERED); expect_advance_over(i, "dirD/", GIT_ITERATOR_STATUS_NORMAL); cl_git_fail_with(GIT_ITEROVER, git_iterator_advance(NULL, i)); git_iterator_free(i); git_vector_free(&pathlist); }
void test_status_ignore__leading_slash_ignores(void) { git_status_options opts = GIT_STATUS_OPTIONS_INIT; status_entry_counts counts; static const char *paths_2[] = { "dir/.gitignore", "dir/a/ignore_me", "dir/b/ignore_me", "dir/ignore_me", "ignore_also/file", "ignore_me", "test/.gitignore", "test/ignore_me/and_me/file", "test/ignore_me/file", "test/ignore_me/file2", }; static const unsigned int statuses_2[] = { GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, }; make_test_data(test_repo_1, test_files_1); cl_fake_home(); cl_git_mkfile("home/.gitignore", "/ignore_me\n"); { git_config *cfg; cl_git_pass(git_repository_config(&cfg, g_repo)); cl_git_pass(git_config_set_string( cfg, "core.excludesfile", "~/.gitignore")); git_config_free(cfg); } cl_git_rewritefile("empty_standard_repo/.git/info/exclude", "/ignore_also\n"); cl_git_rewritefile("empty_standard_repo/dir/.gitignore", "/ignore_me\n"); cl_git_rewritefile("empty_standard_repo/test/.gitignore", "/and_me\n"); memset(&counts, 0x0, sizeof(status_entry_counts)); counts.expected_entry_count = 10; counts.expected_paths = paths_2; counts.expected_statuses = statuses_2; opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; cl_git_pass(git_status_foreach_ext( g_repo, &opts, cb_status__normal, &counts)); cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); cl_assert_equal_i(0, counts.wrong_status_flags_count); cl_assert_equal_i(0, counts.wrong_sorted_path); }
void test_stash_apply__initialize(void) { git_oid oid; repo = cl_git_sandbox_init_new("stash"); cl_git_pass(git_repository_index(&repo_index, repo)); cl_git_pass(git_signature_new(&signature, "nulltoken", "*****@*****.**", 1323847743, 60)); /* Wed Dec 14 08:29:03 2011 +0100 */ cl_git_mkfile("stash/what", "hello\n"); cl_git_mkfile("stash/how", "small\n"); cl_git_mkfile("stash/who", "world\n"); cl_git_mkfile("stash/where", "meh\n"); cl_git_pass(git_index_add_bypath(repo_index, "what")); cl_git_pass(git_index_add_bypath(repo_index, "how")); cl_git_pass(git_index_add_bypath(repo_index, "who")); cl_repo_commit_from_index(NULL, repo, signature, 0, "Initial commit"); cl_git_rewritefile("stash/what", "goodbye\n"); cl_git_rewritefile("stash/who", "funky world\n"); cl_git_mkfile("stash/when", "tomorrow\n"); cl_git_mkfile("stash/why", "would anybody use stash?\n"); cl_git_mkfile("stash/where", "????\n"); cl_git_pass(git_index_add_bypath(repo_index, "who")); cl_git_pass(git_index_add_bypath(repo_index, "why")); cl_git_pass(git_index_add_bypath(repo_index, "where")); git_index_write(repo_index); cl_git_rewritefile("stash/where", "....\n"); /* Pre-stash state */ assert_status(repo, "what", GIT_STATUS_WT_MODIFIED); assert_status(repo, "how", GIT_STATUS_CURRENT); assert_status(repo, "who", GIT_STATUS_INDEX_MODIFIED); assert_status(repo, "when", GIT_STATUS_WT_NEW); assert_status(repo, "why", GIT_STATUS_INDEX_NEW); assert_status(repo, "where", GIT_STATUS_INDEX_NEW|GIT_STATUS_WT_MODIFIED); cl_git_pass(git_stash_save(&oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED)); /* Post-stash state */ assert_status(repo, "what", GIT_STATUS_CURRENT); assert_status(repo, "how", GIT_STATUS_CURRENT); assert_status(repo, "who", GIT_STATUS_CURRENT); assert_status(repo, "when", GIT_ENOTFOUND); assert_status(repo, "why", GIT_ENOTFOUND); assert_status(repo, "where", GIT_ENOTFOUND); }
void test_config_refresh__delete_value(void) { git_config *cfg; int32_t v; cl_git_mkfile(TEST_FILE, "[section]\n\tvalue = 1\n\n"); /* By freeing the config, we make sure we flush the values */ cl_git_pass(git_config_open_ondisk(&cfg, TEST_FILE)); cl_git_pass(git_config_get_int32(&v, cfg, "section.value")); cl_assert_equal_i(1, v); cl_git_fail(git_config_get_int32(&v, cfg, "section.newval")); cl_git_rewritefile(TEST_FILE, "[section]\n\tnewval = 10\n\n"); cl_git_pass(git_config_get_int32(&v, cfg, "section.value")); cl_assert_equal_i(1, v); cl_git_fail(git_config_get_int32(&v, cfg, "section.newval")); cl_git_pass(git_config_refresh(cfg)); cl_git_fail(git_config_get_int32(&v, cfg, "section.value")); cl_git_pass(git_config_get_int32(&v, cfg, "section.newval")); cl_assert_equal_i(10, v); git_config_free(cfg); }
void test_repo_open__bad_gitlinks(void) { git_repository *repo; static const char *bad_links[] = { "garbage\n", "gitdir", "gitdir:\n", "gitdir: foobar", "gitdir: ../invalid", "gitdir: ../invalid2", "gitdir: ../attr/.git with extra stuff", NULL }; const char **scan; cl_git_sandbox_init("attr"); cl_git_pass(p_mkdir("alternate", 0777)); cl_git_pass(p_mkdir("invalid", 0777)); cl_git_pass(git_futils_mkdir_r("invalid2/.git", NULL, 0777)); for (scan = bad_links; *scan != NULL; scan++) { cl_git_rewritefile("alternate/.git", *scan); cl_git_fail(git_repository_open_ext(&repo, "alternate", 0, NULL)); } git_futils_rmdir_r("invalid", NULL, GIT_RMDIR_REMOVE_FILES); git_futils_rmdir_r("invalid2", NULL, GIT_RMDIR_REMOVE_FILES); }
void test_apply_both__application_failure_leaves_workdir_unmodified(void) { git_diff *diff; git_index *index; const char *diff_file = DIFF_MODIFY_TWO_FILES; struct merge_index_entry workdir_expected[] = { { 0100644, "f51658077d85f2264fa179b4d0848268cb3475c3", 0, "asparagus.txt" }, { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, { 0100644, "8684724651336001c5dbce74bed6736d2443958d", 0, "veal.txt" }, }; size_t workdir_expected_cnt = sizeof(workdir_expected) / sizeof(struct merge_index_entry); /* mutate the workdir */ cl_git_rewritefile("merge-recursive/veal.txt", "This is a modification.\n"); cl_git_pass(git_repository_index(&index, repo)); cl_git_pass(git_index_add_bypath(index, "veal.txt")); cl_git_pass(git_index_write(index)); git_index_free(index); cl_git_pass(git_diff_from_buffer(&diff, diff_file, strlen(diff_file))); cl_git_fail_with(GIT_EAPPLYFAIL, git_apply(repo, diff, GIT_APPLY_LOCATION_BOTH, NULL)); validate_apply_workdir(repo, workdir_expected, workdir_expected_cnt); git_diff_free(diff); }
void test_status_worktree__at_head_parent(void) { git_repository *repo = cl_git_sandbox_init("empty_standard_repo"); git_status_options opts = GIT_STATUS_OPTIONS_INIT; git_status_list *statuslist; git_tree *parent_tree; const git_status_entry *status; cl_git_mkfile("empty_standard_repo/file1", "ping"); stage_and_commit(repo, "file1"); cl_git_pass(git_repository_head_tree(&parent_tree, repo)); cl_git_mkfile("empty_standard_repo/file2", "pong"); stage_and_commit(repo, "file2"); cl_git_rewritefile("empty_standard_repo/file2", "pyng"); opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; opts.baseline = parent_tree; cl_git_pass(git_status_list_new(&statuslist, repo, &opts)); cl_assert_equal_sz(1, git_status_list_entrycount(statuslist)); status = git_status_byindex(statuslist, 0); cl_assert(status != NULL); cl_assert_equal_s("file2", status->index_to_workdir->old_file.path); cl_assert_equal_i(GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_NEW, status->status); git_tree_free(parent_tree); git_status_list_free(statuslist); }
void test_status_ignore__1(void) { int ignored; g_repo = cl_git_sandbox_init("attr"); cl_git_rewritefile("attr/.gitignore", "/*.txt\n/dir/\n"); git_attr_cache_flush(g_repo); cl_git_pass(git_status_should_ignore(&ignored, g_repo, "root_test4.txt")); cl_assert(ignored); cl_git_pass(git_status_should_ignore(&ignored, g_repo, "sub/subdir_test2.txt")); cl_assert(!ignored); cl_git_pass(git_status_should_ignore(&ignored, g_repo, "dir")); cl_assert(ignored); cl_git_pass(git_status_should_ignore(&ignored, g_repo, "dir/")); cl_assert(ignored); cl_git_pass(git_status_should_ignore(&ignored, g_repo, "sub/dir")); cl_assert(!ignored); cl_git_pass(git_status_should_ignore(&ignored, g_repo, "sub/dir/")); cl_assert(!ignored); }
void test_diff_submodules__dirty_submodule(void) { git_diff_options opts = GIT_DIFF_OPTIONS_INIT; git_diff_list *diff = NULL; static const char *expected[] = { "<SKIP>", /* .gitmodules */ NULL, /* added */ NULL, /* ignored */ "diff --git a/modified b/modified\nindex 092bfb9..452216e 100644\n--- a/modified\n+++ b/modified\n@@ -1 +1,2 @@\n-yo\n+changed\n+\n", /* modified */ "diff --git a/testrepo b/testrepo\nindex a65fedf..a65fedf 160000\n--- a/testrepo\n+++ b/testrepo\n@@ -1 +1 @@\n-Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750\n+Subproject commit a65fedf39aefe402d3bb6e24df4d4f5fe4547750-dirty\n", /* testrepo.git */ NULL, /* unmodified */ NULL, /* untracked */ "<END>" }; setup_submodules(); cl_git_rewritefile("submodules/testrepo/README", "heyheyhey"); cl_git_mkfile("submodules/testrepo/all_new.txt", "never seen before"); opts.flags = GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_INCLUDE_UNMODIFIED; cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected); git_diff_list_free(diff); }
static void create_paths(const char *root, int depth) { git_buf fullpath = GIT_BUF_INIT; size_t root_len; int i; cl_git_pass(git_buf_puts(&fullpath, root)); cl_git_pass(git_buf_putc(&fullpath, '/')); root_len = fullpath.size; for (i = 0; i < 8; i++) { bool file = (depth == 0 || (i % 2) == 0); git_buf_truncate(&fullpath, root_len); cl_git_pass(git_buf_printf(&fullpath, "item%d", i)); if (file) { cl_git_rewritefile(fullpath.ptr, "This is a file!\n"); } else { cl_must_pass(p_mkdir(fullpath.ptr, 0777)); if (depth > 0) create_paths(fullpath.ptr, (depth - 1)); } } git_buf_dispose(&fullpath); }
void test_attr_ignore__leading_stars(void) { cl_git_rewritefile( "attr/.gitignore", "*/onestar\n" "**/twostars\n" "*/parent1/kid1/*\n" "**/parent2/kid2/*\n"); assert_is_ignored(true, "dir1/onestar"); assert_is_ignored(true, "dir1/onestar/child"); /* in ignored dir */ assert_is_ignored(false, "dir1/dir2/onestar"); assert_is_ignored(true, "dir1/twostars"); assert_is_ignored(true, "dir1/twostars/child"); /* in ignored dir */ assert_is_ignored(true, "dir1/dir2/twostars"); assert_is_ignored(true, "dir1/dir2/twostars/child"); /* in ignored dir */ assert_is_ignored(true, "dir1/dir2/dir3/twostars"); assert_is_ignored(true, "dir1/parent1/kid1/file"); assert_is_ignored(true, "dir1/parent1/kid1/file/inside/parent"); assert_is_ignored(false, "dir1/dir2/parent1/kid1/file"); assert_is_ignored(false, "dir1/parent1/file"); assert_is_ignored(false, "dir1/kid1/file"); assert_is_ignored(true, "dir1/parent2/kid2/file"); assert_is_ignored(true, "dir1/parent2/kid2/file/inside/parent"); assert_is_ignored(true, "dir1/dir2/parent2/kid2/file"); assert_is_ignored(true, "dir1/dir2/dir3/parent2/kid2/file"); assert_is_ignored(false, "dir1/parent2/file"); assert_is_ignored(false, "dir1/kid2/file"); }
void test_status_ignore__empty_repo_with_gitignore_rewrite(void) { status_entry_single st; int ignored; g_repo = cl_git_sandbox_init("empty_standard_repo"); cl_git_mkfile( "empty_standard_repo/look-ma.txt", "I'm going to be ignored!"); memset(&st, 0, sizeof(st)); cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); cl_assert(st.count == 1); cl_assert(st.status == GIT_STATUS_WT_NEW); cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); cl_assert(st.status == GIT_STATUS_WT_NEW); cl_git_pass(git_status_should_ignore(&ignored, g_repo, "look-ma.txt")); cl_assert(!ignored); cl_git_rewritefile("empty_standard_repo/.gitignore", "*.nomatch\n"); memset(&st, 0, sizeof(st)); cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); cl_assert(st.count == 2); cl_assert(st.status == GIT_STATUS_WT_NEW); cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); cl_assert(st.status == GIT_STATUS_WT_NEW); cl_git_pass(git_status_should_ignore(&ignored, g_repo, "look-ma.txt")); cl_assert(!ignored); cl_git_rewritefile("empty_standard_repo/.gitignore", "*.txt\n"); memset(&st, 0, sizeof(st)); cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); cl_assert(st.count == 2); cl_assert(st.status == GIT_STATUS_IGNORED); cl_git_pass(git_status_file(&st.status, g_repo, "look-ma.txt")); cl_assert(st.status == GIT_STATUS_IGNORED); cl_git_pass(git_status_should_ignore(&ignored, g_repo, "look-ma.txt")); cl_assert(ignored); }
static void force_create_file(const char *file) { int error = git_futils_rmdir_r(file, NULL, GIT_RMDIR_REMOVE_FILES | GIT_RMDIR_REMOVE_BLOCKERS); cl_assert(!error || error == GIT_ENOTFOUND); cl_git_pass(git_futils_mkpath2file(file, 0777)); cl_git_rewritefile(file, "yowza!!"); }
static void add_to_workdir(const char *filename, const char *content) { git_buf buf = GIT_BUF_INIT; cl_git_pass(git_buf_joinpath(&buf, "attr", filename)); cl_git_rewritefile(git_buf_cstr(&buf), content); git_buf_free(&buf); }
void test_attr_ignore__ignore_root(void) { cl_git_rewritefile("attr/.gitignore", "/\n\n/NewFolder\n/NewFolder/NewFolder"); assert_is_ignored(false, "File.txt"); assert_is_ignored(true, "NewFolder"); assert_is_ignored(true, "NewFolder/NewFolder"); assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); }
static void make_gitlink_dir(const char *dir, const char *linktext) { git_buf path = GIT_BUF_INIT; cl_git_pass(git_futils_mkdir(dir, NULL, 0777, GIT_MKDIR_VERIFY_DIR)); cl_git_pass(git_buf_joinpath(&path, dir, ".git")); cl_git_rewritefile(path.ptr, linktext); git_buf_free(&path); }
void test_attr_ignore__honor_temporary_rules(void) { cl_git_rewritefile("attr/.gitignore", "/NewFolder\n/NewFolder/NewFolder"); assert_is_ignored(false, "File.txt"); assert_is_ignored(true, "NewFolder"); assert_is_ignored(true, "NewFolder/NewFolder"); assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); }
void test_status_worktree__issue_592_ignores_0(void) { int count = 0; status_entry_single st; git_repository *repo = cl_git_sandbox_init("issue_592"); cl_git_pass(git_status_foreach(repo, cb_status__count, &count)); cl_assert_equal_i(0, count); cl_git_rewritefile("issue_592/.gitignore", ".gitignore\n*.txt\nc/\n[tT]*/\n"); cl_git_pass(git_status_foreach(repo, cb_status__count, &count)); cl_assert_equal_i(1, count); /* This is a situation where the behavior of libgit2 is * different from core git. Core git will show ignored.txt * in the list of ignored files, even though the directory * "t" is ignored and the file is untracked because we have * the explicit "*.txt" ignore rule. Libgit2 just excludes * all untracked files that are contained within ignored * directories without explicitly listing them. */ cl_git_rewritefile("issue_592/t/ignored.txt", "ping"); memset(&st, 0, sizeof(st)); cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); cl_assert_equal_i(1, st.count); cl_assert(st.status == GIT_STATUS_IGNORED); cl_git_rewritefile("issue_592/c/ignored_by_dir", "ping"); memset(&st, 0, sizeof(st)); cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); cl_assert_equal_i(1, st.count); cl_assert(st.status == GIT_STATUS_IGNORED); cl_git_rewritefile("issue_592/t/ignored_by_dir_pattern", "ping"); memset(&st, 0, sizeof(st)); cl_git_pass(git_status_foreach(repo, cb_status__single, &st)); cl_assert_equal_i(1, st.count); cl_assert(st.status == GIT_STATUS_IGNORED); }
void test_status_ignore__subdirectories(void) { status_entry_single st; int ignored; git_status_options opts; GIT_UNUSED(opts); g_repo = cl_git_sandbox_init("empty_standard_repo"); cl_git_mkfile( "empty_standard_repo/ignore_me", "I'm going to be ignored!"); cl_git_rewritefile("empty_standard_repo/.gitignore", "ignore_me\n"); memset(&st, 0, sizeof(st)); cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); cl_assert_equal_i(2, st.count); cl_assert(st.status == GIT_STATUS_IGNORED); cl_git_pass(git_status_file(&st.status, g_repo, "ignore_me")); cl_assert(st.status == GIT_STATUS_IGNORED); cl_git_pass(git_status_should_ignore(&ignored, g_repo, "ignore_me")); cl_assert(ignored); /* So, interestingly, as per the comment in diff_from_iterators() the * following file is ignored, but in a way so that it does not show up * in status even if INCLUDE_IGNORED is used. This actually matches * core git's behavior - if you follow these steps and try running "git * status -uall --ignored" then the following file and directory will * not show up in the output at all. */ cl_git_pass( git_futils_mkdir_r("empty_standard_repo/test/ignore_me", NULL, 0775)); cl_git_mkfile( "empty_standard_repo/test/ignore_me/file", "I'm going to be ignored!"); opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED | GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; memset(&st, 0, sizeof(st)); cl_git_pass(git_status_foreach(g_repo, cb_status__single, &st)); cl_assert_equal_i(2, st.count); cl_git_pass(git_status_file(&st.status, g_repo, "test/ignore_me/file")); cl_assert(st.status == GIT_STATUS_IGNORED); cl_git_pass( git_status_should_ignore(&ignored, g_repo, "test/ignore_me/file")); cl_assert(ignored); }
void test_attr_ignore__full_paths(void) { cl_git_rewritefile("attr/.gitignore", "Folder/*/Contained"); assert_is_ignored(true, "Folder/Middle/Contained"); assert_is_ignored(false, "Folder/Middle/More/More/Contained"); cl_git_rewritefile("attr/.gitignore", "Folder/**/Contained"); assert_is_ignored(true, "Folder/Middle/Contained"); assert_is_ignored(true, "Folder/Middle/More/More/Contained"); cl_git_rewritefile("attr/.gitignore", "Folder/**/Contained/*/Child"); assert_is_ignored(true, "Folder/Middle/Contained/Happy/Child"); assert_is_ignored(false, "Folder/Middle/Contained/Not/Happy/Child"); assert_is_ignored(true, "Folder/Middle/More/More/Contained/Happy/Child"); assert_is_ignored(false, "Folder/Middle/More/More/Contained/Not/Happy/Child"); }
void test_config_read__invalid_key_chars(void) { git_config *cfg; cl_set_cleanup(&clean_test_config, NULL); cl_git_mkfile("./testconfig", "[foo]\n has_underscore = git2\n"); cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); cl_git_rewritefile("./testconfig", "[foo]\n has/slash = git2\n"); cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); cl_git_rewritefile("./testconfig", "[foo]\n has+plus = git2\n"); cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); cl_git_rewritefile("./testconfig", "[no_key]\n = git2\n"); cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig")); git_config_free(cfg); }
void test_submodule_nosubs__bad_gitmodules(void) { git_repository *repo = cl_git_sandbox_init("status"); cl_git_mkfile("status/.gitmodules", "[submodule \"foobar\"]\tpath=blargle\n\turl=\n\tbranch=\n\tupdate=flooble\n\n"); cl_git_rewritefile("status/.gitmodules", "[submodule \"foobar\"]\tpath=blargle\n\turl=\n\tbranch=\n\tupdate=rebase\n\n"); cl_git_pass(git_submodule_lookup(NULL, repo, "foobar")); cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(NULL, repo, "subdir")); }
void test_index_tests__preserves_case(void) { git_repository *repo; git_index *index; const git_index_entry *entry; int index_caps; cl_set_cleanup(&cleanup_myrepo, NULL); cl_git_pass(git_repository_init(&repo, "./myrepo", 0)); cl_git_pass(git_repository_index(&index, repo)); index_caps = git_index_caps(index); cl_git_rewritefile("myrepo/test.txt", "hey there\n"); cl_git_pass(git_index_add_bypath(index, "test.txt")); cl_git_pass(p_rename("myrepo/test.txt", "myrepo/TEST.txt")); cl_git_rewritefile("myrepo/TEST.txt", "hello again\n"); cl_git_pass(git_index_add_bypath(index, "TEST.txt")); if (index_caps & GIT_INDEXCAP_IGNORE_CASE) cl_assert_equal_i(1, (int)git_index_entrycount(index)); else cl_assert_equal_i(2, (int)git_index_entrycount(index)); /* Test access by path instead of index */ cl_assert((entry = git_index_get_bypath(index, "test.txt", 0)) != NULL); /* The path should *not* have changed without an explicit remove */ cl_assert(git__strcmp(entry->path, "test.txt") == 0); cl_assert((entry = git_index_get_bypath(index, "TEST.txt", 0)) != NULL); if (index_caps & GIT_INDEXCAP_IGNORE_CASE) /* The path should *not* have changed without an explicit remove */ cl_assert(git__strcmp(entry->path, "test.txt") == 0); else cl_assert(git__strcmp(entry->path, "TEST.txt") == 0); git_index_free(index); git_repository_free(repo); }
void test_stash_apply__conflict_workdir_with_default(void) { cl_git_rewritefile("stash/what", "ciao\n"); cl_git_fail_with(git_stash_apply(repo, 0, NULL), GIT_ECONFLICT); cl_assert_equal_i(git_index_has_conflicts(repo_index), 0); assert_status(repo, "what", GIT_STATUS_WT_MODIFIED); assert_status(repo, "how", GIT_STATUS_CURRENT); assert_status(repo, "who", GIT_STATUS_CURRENT); assert_status(repo, "when", GIT_STATUS_WT_NEW); }
void test_attr_ignore__symlink_to_outside(void) { #ifdef GIT_WIN32 cl_skip(); #endif cl_git_rewritefile("attr/.gitignore", "symlink\n"); cl_git_mkfile("target", "target"); cl_git_pass(p_symlink("../target", "attr/symlink")); assert_is_ignored(true, "symlink"); assert_is_ignored(true, "lala/../symlink"); }
void test_apply_both__keeps_nonconflicting_changes(void) { git_diff *diff; git_index *index; git_index_entry idx_entry; const char *diff_file = DIFF_MODIFY_TWO_FILES; struct merge_index_entry index_expected[] = { { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, { 0100644, "898d12687fb35be271c27c795a6b32c8b51da79e", 0, "beef.txt" }, { 0100644, "c4e6cca3ec6ae0148ed231f97257df8c311e015f", 0, "gravy.txt" }, { 0100644, "68af1fc7407fd9addf1701a87eb1c95c7494c598", 0, "oyster.txt" }, { 0100644, "a7b066537e6be7109abfe4ff97b675d4e077da20", 0, "veal.txt" }, }; size_t index_expected_cnt = sizeof(index_expected) / sizeof(struct merge_index_entry); struct merge_index_entry workdir_expected[] = { { 0100644, "ffb36e513f5fdf8a6ba850a20142676a2ac4807d", 0, "asparagus.txt" }, { 0100644, "68f6182f4c85d39e1309d97c7e456156dc9c0096", 0, "beef.txt" }, { 0100644, "4b7c5650008b2e747fe1809eeb5a1dde0e80850a", 0, "bouilli.txt" }, { 0100644, "f75ba05f340c51065cbea2e1fdbfe5fe13144c97", 0, "gravy.txt" }, { 0100644, "a7b066537e6be7109abfe4ff97b675d4e077da20", 0, "veal.txt" }, }; size_t workdir_expected_cnt = sizeof(workdir_expected) / sizeof(struct merge_index_entry); /* mutate the index */ cl_git_pass(git_repository_index(&index, repo)); memset(&idx_entry, 0, sizeof(git_index_entry)); idx_entry.mode = 0100644; idx_entry.path = "beef.txt"; cl_git_pass(git_oid_fromstr(&idx_entry.id, "898d12687fb35be271c27c795a6b32c8b51da79e")); cl_git_pass(git_index_add(index, &idx_entry)); cl_git_pass(git_index_remove(index, "bouilli.txt", 0)); cl_git_pass(git_index_write(index)); git_index_free(index); /* and mutate the working directory */ cl_git_rmfile("merge-recursive/oyster.txt"); cl_git_rewritefile("merge-recursive/gravy.txt", "Hello, world.\n"); cl_git_pass(git_diff_from_buffer(&diff, diff_file, strlen(diff_file))); cl_git_pass(git_apply(repo, diff, GIT_APPLY_LOCATION_BOTH, NULL)); validate_apply_index(repo, index_expected, index_expected_cnt); validate_apply_workdir(repo, workdir_expected, workdir_expected_cnt); git_diff_free(diff); }
static void write_attributes(git_repository *repo) { git_buf buf = GIT_BUF_INIT; cl_git_pass(git_buf_joinpath(&buf, git_repository_path(repo), "info")); cl_git_pass(git_buf_joinpath(&buf, git_buf_cstr(&buf), "attributes")); cl_git_pass(git_futils_mkpath2file(git_buf_cstr(&buf), 0777)); cl_git_rewritefile(git_buf_cstr(&buf), GITATTR); git_buf_free(&buf); }
void test_status_ignore__subdirectories_not_at_root(void) { git_status_options opts = GIT_STATUS_OPTIONS_INIT; status_entry_counts counts; static const char *paths_1[] = { "dir/.gitignore", "dir/a/ignore_me", "dir/b/ignore_me", "dir/ignore_me", "ignore_also/file", "ignore_me", "test/.gitignore", "test/ignore_me/and_me/file", "test/ignore_me/file", "test/ignore_me/file2", }; static const unsigned int statuses_1[] = { GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_IGNORED, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, GIT_STATUS_IGNORED, GIT_STATUS_WT_NEW, GIT_STATUS_WT_NEW, }; make_test_data(test_repo_1, test_files_1); cl_git_rewritefile("empty_standard_repo/dir/.gitignore", "ignore_me\n/ignore_also\n"); cl_git_rewritefile("empty_standard_repo/test/.gitignore", "and_me\n"); memset(&counts, 0x0, sizeof(status_entry_counts)); counts.expected_entry_count = 10; counts.expected_paths = paths_1; counts.expected_statuses = statuses_1; opts.flags = GIT_STATUS_OPT_DEFAULTS | GIT_STATUS_OPT_RECURSE_IGNORED_DIRS; cl_git_pass(git_status_foreach_ext( g_repo, &opts, cb_status__normal, &counts)); cl_assert_equal_i(counts.expected_entry_count, counts.entry_count); cl_assert_equal_i(0, counts.wrong_status_flags_count); cl_assert_equal_i(0, counts.wrong_sorted_path); }
void test_status_worktree__line_endings_dont_count_as_changes_with_autocrlf(void) { git_repository *repo = cl_git_sandbox_init("status"); unsigned int status; cl_repo_set_bool(repo, "core.autocrlf", true); cl_git_rewritefile("status/current_file", "current_file\r\n"); cl_git_pass(git_status_file(&status, repo, "current_file")); cl_assert_equal_i(GIT_STATUS_CURRENT, status); }