diff --git a/src/index.c b/src/index.c index 6cc8ea1a3..24e447928 100644 --- a/src/index.c +++ b/src/index.c @@ -524,7 +524,9 @@ int git_index__changed_relative_to( if (git_index_read(index, false) < 0) giterr_clear(); - return (memcmp(&index->stamp, fs, sizeof(index->stamp)) == 0); + return (index->stamp.mtime != fs->mtime || + index->stamp.size != fs->size || + index->stamp.ino != fs->ino); } int git_index_write(git_index *index) diff --git a/tests/submodule/lookup.c b/tests/submodule/lookup.c index 86ba25c3a..34de5923e 100644 --- a/tests/submodule/lookup.c +++ b/tests/submodule/lookup.c @@ -130,18 +130,63 @@ void test_submodule_lookup__lookup_even_with_missing_index(void) test_submodule_lookup__simple_lookup(); /* baseline should still pass */ } +static void baseline_tests(void) +{ + /* small baseline that should work even if we change the index or make + * commits from the index + */ + assert_submodule_exists(g_repo, "sm_unchanged"); + assert_submodule_exists(g_repo, "sm_gitmodules_only"); + refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS); +} + +static void add_submodule_with_commit(const char *name) +{ + git_submodule *sm; + git_repository *smrepo; + git_index *idx; + git_buf p = GIT_BUF_INIT; + + cl_git_pass(git_submodule_add_setup(&sm, g_repo, + "https://github.com/libgit2/libgit2.git", name, 1)); + + assert_submodule_exists(g_repo, name); + + cl_git_pass(git_submodule_open(&smrepo, sm)); + cl_git_pass(git_repository_index(&idx, smrepo)); + + cl_git_pass(git_buf_joinpath(&p, git_repository_workdir(smrepo), "file")); + cl_git_mkfile(p.ptr, "new file"); + git_buf_free(&p); + + cl_git_pass(git_index_add_bypath(idx, "file")); + cl_git_pass(git_index_write(idx)); + git_index_free(idx); + + cl_repo_commit_from_index(NULL, smrepo, NULL, 0, "initial commit"); + git_repository_free(smrepo); + + cl_git_pass(git_submodule_add_finalize(sm)); + + git_submodule_free(sm); +} + void test_submodule_lookup__just_added(void) { git_submodule *sm; git_buf snap1 = GIT_BUF_INIT, snap2 = GIT_BUF_INIT; + git_reference *original_head = NULL; refute_submodule_exists(g_repo, "sm_just_added", GIT_ENOTFOUND); refute_submodule_exists(g_repo, "sm_just_added_2", GIT_ENOTFOUND); + refute_submodule_exists(g_repo, "sm_just_added_idx", GIT_ENOTFOUND); + refute_submodule_exists(g_repo, "sm_just_added_head", GIT_ENOTFOUND); refute_submodule_exists(g_repo, "mismatch_name", GIT_ENOTFOUND); refute_submodule_exists(g_repo, "mismatch_path", GIT_ENOTFOUND); - test_submodule_lookup__simple_lookup(); /* baseline */ + baseline_tests(); cl_git_pass(git_futils_readbuffer(&snap1, "submod2/.gitmodules")); + cl_git_pass(git_repository_head(&original_head, g_repo)); cl_git_pass(git_submodule_add_setup(&sm, g_repo, "https://github.com/libgit2/libgit2.git", "sm_just_added", 1)); @@ -151,8 +196,16 @@ void test_submodule_lookup__just_added(void) cl_git_pass(git_submodule_add_setup(&sm, g_repo, "https://github.com/libgit2/libgit2.git", "sm_just_added_2", 1)); assert_submodule_exists(g_repo, "sm_just_added_2"); + cl_git_fail(git_submodule_add_finalize(sm)); /* fails if no HEAD */ git_submodule_free(sm); + add_submodule_with_commit("sm_just_added_head"); + cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "commit new sm to head"); + assert_submodule_exists(g_repo, "sm_just_added_head"); + + add_submodule_with_commit("sm_just_added_idx"); + assert_submodule_exists(g_repo, "sm_just_added_idx"); + cl_git_pass(git_futils_readbuffer(&snap2, "submod2/.gitmodules")); cl_git_append2file( @@ -165,7 +218,9 @@ void test_submodule_lookup__just_added(void) assert_submodule_exists(g_repo, "mismatch_path"); assert_submodule_exists(g_repo, "sm_just_added"); assert_submodule_exists(g_repo, "sm_just_added_2"); - test_submodule_lookup__simple_lookup(); + assert_submodule_exists(g_repo, "sm_just_added_idx"); + assert_submodule_exists(g_repo, "sm_just_added_head"); + baseline_tests(); cl_git_rewritefile("submod2/.gitmodules", snap2.ptr); git_buf_free(&snap2); @@ -174,7 +229,9 @@ void test_submodule_lookup__just_added(void) refute_submodule_exists(g_repo, "mismatch_path", GIT_ENOTFOUND); assert_submodule_exists(g_repo, "sm_just_added"); assert_submodule_exists(g_repo, "sm_just_added_2"); - test_submodule_lookup__simple_lookup(); + assert_submodule_exists(g_repo, "sm_just_added_idx"); + assert_submodule_exists(g_repo, "sm_just_added_head"); + baseline_tests(); cl_git_rewritefile("submod2/.gitmodules", snap1.ptr); git_buf_free(&snap1); @@ -184,5 +241,31 @@ void test_submodule_lookup__just_added(void) /* note error code change, because add_setup made a repo in the workdir */ refute_submodule_exists(g_repo, "sm_just_added", GIT_EEXISTS); refute_submodule_exists(g_repo, "sm_just_added_2", GIT_EEXISTS); - test_submodule_lookup__simple_lookup(); + /* these still exist in index and head respectively */ + assert_submodule_exists(g_repo, "sm_just_added_idx"); + assert_submodule_exists(g_repo, "sm_just_added_head"); + baseline_tests(); + + { + git_index *idx; + cl_git_pass(git_repository_index(&idx, g_repo)); + cl_git_pass(git_index_remove_bypath(idx, "sm_just_added_idx")); + cl_git_pass(git_index_remove_bypath(idx, "sm_just_added_head")); + cl_git_pass(git_index_write(idx)); + git_index_free(idx); + } + + refute_submodule_exists(g_repo, "sm_just_added_idx", GIT_EEXISTS); + assert_submodule_exists(g_repo, "sm_just_added_head"); + + { + git_signature *sig; + cl_git_pass(git_signature_now(&sig, "resetter", "resetter@email.com")); + cl_git_pass(git_reference_create(NULL, g_repo, "refs/heads/master", git_reference_target(original_head), 1, sig, "move head back")); + git_signature_free(sig); + git_reference_free(original_head); + } + + refute_submodule_exists(g_repo, "sm_just_added_head", GIT_EEXISTS); } + diff --git a/tests/submodule/submodule_helpers.c b/tests/submodule/submodule_helpers.c index 546f0913a..50aa97568 100644 --- a/tests/submodule/submodule_helpers.c +++ b/tests/submodule/submodule_helpers.c @@ -126,20 +126,26 @@ git_repository *setup_fixture_submod2(void) return repo; } -void assert_submodule_exists(git_repository *repo, const char *name) +void assert__submodule_exists( + git_repository *repo, const char *name, + const char *msg, const char *file, int line) { git_submodule *sm; - cl_git_pass(git_submodule_lookup(&sm, repo, name)); - cl_assert(sm); + int error = git_submodule_lookup(&sm, repo, name); + if (error) + cl_git_report_failure(error, file, line, msg); + cl_assert_at_line(sm != NULL, file, line); git_submodule_free(sm); } -void refute_submodule_exists( - git_repository *repo, const char *name, int expected_error) +void refute__submodule_exists( + git_repository *repo, const char *name, int expected_error, + const char *msg, const char *file, int line) { git_submodule *sm; - cl_assert_equal_i( - expected_error, git_submodule_lookup(&sm, repo, name)); + clar__assert_equal( + file, line, msg, 1, "%i", + expected_error, (int)(git_submodule_lookup(&sm, repo, name))); } unsigned int get_submodule_status(git_repository *repo, const char *name) @@ -154,3 +160,19 @@ unsigned int get_submodule_status(git_repository *repo, const char *name) return status; } + +static int print_submodules(git_submodule *sm, const char *name, void *p) +{ + unsigned int loc = 0; + GIT_UNUSED(p); + git_submodule_location(&loc, sm); + fprintf(stderr, "# submodule %s (at %s) flags %x\n", + name, git_submodule_path(sm), loc); + return 0; +} + +void dump_submodules(git_repository *repo) +{ + git_submodule_foreach(repo, print_submodules, NULL); +} + diff --git a/tests/submodule/submodule_helpers.h b/tests/submodule/submodule_helpers.h index ec5510e3c..4b2620bfa 100644 --- a/tests/submodule/submodule_helpers.h +++ b/tests/submodule/submodule_helpers.h @@ -6,5 +6,16 @@ extern git_repository *setup_fixture_submod2(void); extern unsigned int get_submodule_status(git_repository *, const char *); -extern void assert_submodule_exists(git_repository *, const char *); -extern void refute_submodule_exists(git_repository *, const char *, int err); +extern void assert__submodule_exists( + git_repository *, const char *, const char *, const char *, int); + +#define assert_submodule_exists(repo,name) \ + assert__submodule_exists(repo, name, "git_submodule_lookup(" #name ") failed", __FILE__, __LINE__) + +extern void refute__submodule_exists( + git_repository *, const char *, int err, const char *, const char *, int); + +#define refute_submodule_exists(repo,name,code) \ + refute__submodule_exists(repo, name, code, "expected git_submodule_lookup(" #name ") to fail with error " #code, __FILE__, __LINE__) + +extern void dump_submodules(git_repository *repo);