From a15c7802c86cf995fa658ef0624c46d352ce9a81 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Tue, 25 Mar 2014 09:14:48 -0700 Subject: Make submodules externally refcounted `git_submodule` objects were already refcounted internally in case the submodule name was different from the path at which it was stored. This makes that refcounting externally used as well, so `git_submodule_lookup` and `git_submodule_add_setup` return an object that requires a `git_submodule_free` when done. --- examples/status.c | 25 ++-- include/git2/submodule.h | 44 ++++-- src/checkout.c | 26 ++-- src/diff.c | 31 ++-- src/diff_file.c | 14 +- src/submodule.c | 106 +++++++++----- src/submodule.h | 3 - tests/diff/submodules.c | 10 +- tests/stash/submodules.c | 3 + tests/status/submodules.c | 2 + tests/submodule/lookup.c | 95 +++++-------- tests/submodule/modify.c | 22 ++- tests/submodule/status.c | 275 ++++++++++++++---------------------- tests/submodule/submodule_helpers.c | 29 ++++ tests/submodule/submodule_helpers.h | 5 + 15 files changed, 356 insertions(+), 334 deletions(-) diff --git a/examples/status.c b/examples/status.c index 3adfe0d5d..feba77f84 100644 --- a/examples/status.c +++ b/examples/status.c @@ -363,18 +363,21 @@ static void print_short(git_repository *repo, git_status_list *status) unsigned int smstatus = 0; if (!git_submodule_lookup( - &sm, repo, s->index_to_workdir->new_file.path) && - !git_submodule_status(&smstatus, sm)) - { - if (smstatus & GIT_SUBMODULE_STATUS_WD_MODIFIED) - extra = " (new commits)"; - else if (smstatus & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) - extra = " (modified content)"; - else if (smstatus & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) - extra = " (modified content)"; - else if (smstatus & GIT_SUBMODULE_STATUS_WD_UNTRACKED) - extra = " (untracked content)"; + &sm, repo, s->index_to_workdir->new_file.path)) { + + if (!git_submodule_status(&smstatus, sm)) { + if (smstatus & GIT_SUBMODULE_STATUS_WD_MODIFIED) + extra = " (new commits)"; + else if (smstatus & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) + extra = " (modified content)"; + else if (smstatus & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) + extra = " (modified content)"; + else if (smstatus & GIT_SUBMODULE_STATUS_WD_UNTRACKED) + extra = " (untracked content)"; + } } + + git_submodule_free(sm); } /** diff --git a/include/git2/submodule.h b/include/git2/submodule.h index ac0abc0a4..789f2c045 100644 --- a/include/git2/submodule.h +++ b/include/git2/submodule.h @@ -123,21 +123,27 @@ typedef enum { * There may or may not be anything else at that path, but nothing that * looks like a submodule. In this case, this returns GIT_ENOTFOUND. * - * The submodule object is owned by the containing repo and will be freed - * when the repo is freed. The caller need not free the submodule. + * You must call `git_submodule_free` when done with the submodule. * - * @param submodule Pointer to submodule description object pointer.. - * @param repo The repository. - * @param name The name of the submodule. Trailing slashes will be ignored. + * @param out Output ptr to submodule; pass NULL to just get return code + * @param repo The parent repository + * @param name The name of or path to the submodule; trailing slashes okay * @return 0 on success, GIT_ENOTFOUND if submodule does not exist, - * GIT_EEXISTS if submodule exists in working directory only, -1 on - * other errors. + * GIT_EEXISTS if submodule exists in working directory only, + * -1 on other errors. */ GIT_EXTERN(int) git_submodule_lookup( - git_submodule **submodule, + git_submodule **out, git_repository *repo, const char *name); +/** + * Release a submodule + * + * @param submodule Submodule object + */ +GIT_EXTERN(void) git_submodule_free(git_submodule *submodule); + /** * Iterate over all tracked submodules of a repository. * @@ -175,9 +181,11 @@ GIT_EXTERN(int) git_submodule_foreach( * `git_submodule_add_finalize()` to wrap up adding the new submodule and * .gitmodules to the index to be ready to commit. * - * @param submodule The newly created submodule ready to open for clone - * @param repo Superproject repository to contain the new submodule - * @param url URL for the submodules remote + * You must call `git_submodule_free` on the submodule object when done. + * + * @param out The newly created submodule ready to open for clone + * @param repo The repository in which you want to create the submodule + * @param url URL for the submodule's remote * @param path Path at which the submodule should be created * @param use_gitlink Should workdir contain a gitlink to the repo in * .git/modules vs. repo directly in workdir. @@ -185,7 +193,7 @@ GIT_EXTERN(int) git_submodule_foreach( * -1 on other errors. */ GIT_EXTERN(int) git_submodule_add_setup( - git_submodule **submodule, + git_submodule **out, git_repository *repo, const char *url, const char *path, @@ -493,15 +501,23 @@ GIT_EXTERN(int) git_submodule_open( * * Call this to reread cached submodule information for this submodule if * you have reason to believe that it has changed. + * + * @param submodule The submodule to reload + * @param force Force reload even if the data doesn't seem out of date + * @return 0 on success, <0 on error */ -GIT_EXTERN(int) git_submodule_reload(git_submodule *submodule); +GIT_EXTERN(int) git_submodule_reload(git_submodule *submodule, int force); /** * Reread all submodule info. * * Call this to reload all cached submodule information for the repo. + * + * @param repo The repository to reload submodule data for + * @param force Force full reload even if the data doesn't seem out of date + * @return 0 on success, <0 on error */ -GIT_EXTERN(int) git_submodule_reload_all(git_repository *repo); +GIT_EXTERN(int) git_submodule_reload_all(git_repository *repo, int force); /** * Get the status for a submodule. diff --git a/src/checkout.c b/src/checkout.c index f882f3593..da9e5a12d 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -147,19 +147,23 @@ static bool checkout_is_workdir_modified( git_submodule *sm; unsigned int sm_status = 0; const git_oid *sm_oid = NULL; + bool rval = false; - if (git_submodule_lookup(&sm, data->repo, wditem->path) < 0 || - git_submodule_status(&sm_status, sm) < 0) - return true; - - if (GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status)) + if (git_submodule_lookup(&sm, data->repo, wditem->path) < 0) { + giterr_clear(); return true; + } - sm_oid = git_submodule_wd_id(sm); - if (!sm_oid) - return false; + if (git_submodule_status(&sm_status, sm) < 0 || + GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status)) + rval = true; + else if ((sm_oid = git_submodule_wd_id(sm)) == NULL) + rval = false; + else + rval = (git_oid__cmp(&baseitem->id, sm_oid) != 0); - return (git_oid__cmp(&baseitem->id, sm_oid) != 0); + git_submodule_free(sm); + return rval; } /* Look at the cache to decide if the workdir is modified. If not, @@ -1510,7 +1514,7 @@ static int checkout_create_submodules( /* initial reload of submodules if .gitmodules was changed */ if (data->reload_submodules && - (error = git_submodule_reload_all(data->repo)) < 0) + (error = git_submodule_reload_all(data->repo, 1)) < 0) return error; git_vector_foreach(&data->diff->deltas, i, delta) { @@ -1534,7 +1538,7 @@ static int checkout_create_submodules( } /* final reload once submodules have been updated */ - return git_submodule_reload_all(data->repo); + return git_submodule_reload_all(data->repo, 1); } static int checkout_lookup_head_tree(git_tree **out, git_repository *repo) diff --git a/src/diff.c b/src/diff.c index dc7735f4f..25c5937e6 100644 --- a/src/diff.c +++ b/src/diff.c @@ -528,12 +528,15 @@ int git_diff__oid_for_file( /* calculate OID for file if possible */ if (S_ISGITLINK(mode)) { git_submodule *sm; - const git_oid *sm_oid; - if (!git_submodule_lookup(&sm, repo, path) && - (sm_oid = git_submodule_wd_id(sm)) != NULL) - git_oid_cpy(oid, sm_oid); - else { + memset(oid, 0, sizeof(*oid)); + + if (!git_submodule_lookup(&sm, repo, path)) { + const git_oid *sm_oid = git_submodule_wd_id(sm); + if (sm_oid) + git_oid_cpy(oid, sm_oid); + git_submodule_free(sm); + } else { /* if submodule lookup failed probably just in an intermediate * state where some init hasn't happened, so ignore the error */ @@ -615,24 +618,24 @@ static int maybe_modified_submodule( } if (ign <= 0 && git_submodule_ignore(sub) == GIT_SUBMODULE_IGNORE_ALL) - return 0; - - if ((error = git_submodule__status( + /* ignore it */; + else if ((error = git_submodule__status( &sm_status, NULL, NULL, found_oid, sub, ign)) < 0) - return error; + /* return error below */; /* check IS_WD_UNMODIFIED because this case is only used * when the new side of the diff is the working directory */ - if (!GIT_SUBMODULE_STATUS_IS_WD_UNMODIFIED(sm_status)) + else if (!GIT_SUBMODULE_STATUS_IS_WD_UNMODIFIED(sm_status)) *status = GIT_DELTA_MODIFIED; /* now that we have a HEAD OID, check if HEAD moved */ - if ((sm_status & GIT_SUBMODULE_STATUS_IN_WD) != 0 && + else if ((sm_status & GIT_SUBMODULE_STATUS_IN_WD) != 0 && !git_oid_equal(&info->oitem->id, found_oid)) *status = GIT_DELTA_MODIFIED; - return 0; + git_submodule_free(sub); + return error; } static int maybe_modified( @@ -960,10 +963,8 @@ static int handle_unmatched_new_item( delta_type = GIT_DELTA_ADDED; else if (nitem->mode == GIT_FILEMODE_COMMIT) { - git_submodule *sm; - /* ignore things that are not actual submodules */ - if (git_submodule_lookup(&sm, info->repo, nitem->path) != 0) { + if (git_submodule_lookup(NULL, info->repo, nitem->path) != 0) { giterr_clear(); delta_type = GIT_DELTA_IGNORED; } diff --git a/src/diff_file.c b/src/diff_file.c index 7dabf8d6f..2f3f797c5 100644 --- a/src/diff_file.c +++ b/src/diff_file.c @@ -177,11 +177,17 @@ static int diff_file_content_commit_to_str( unsigned int sm_status = 0; const git_oid *sm_head; - if ((error = git_submodule_lookup(&sm, fc->repo, fc->file->path)) < 0 || - (error = git_submodule_status(&sm_status, sm)) < 0) { + if ((error = git_submodule_lookup(&sm, fc->repo, fc->file->path)) < 0) { /* GIT_EEXISTS means a "submodule" that has not been git added */ - if (error == GIT_EEXISTS) + if (error == GIT_EEXISTS) { + giterr_clear(); error = 0; + } + return error; + } + + if ((error = git_submodule_status(&sm_status, sm)) < 0) { + git_submodule_free(sm); return error; } @@ -196,6 +202,8 @@ static int diff_file_content_commit_to_str( if (GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status)) status = "-dirty"; + + git_submodule_free(sm); } git_oid_tostr(oid, sizeof(oid), &fc->file->id); diff --git a/src/submodule.c b/src/submodule.c index 9eaf77dae..291311658 100644 --- a/src/submodule.c +++ b/src/submodule.c @@ -99,27 +99,55 @@ static int submodule_config_key_trunc_puts(git_buf *key, const char *suffix) return git_buf_puts(key, suffix); } +/* lookup submodule or return ENOTFOUND if it doesn't exist */ +static int submodule_lookup( + git_submodule **out, + git_strmap *cache, + const char *name, + const char *alternate) +{ + khiter_t pos; + + /* lock cache */ + + pos = git_strmap_lookup_index(cache, name); + + if (!git_strmap_valid_index(cache, pos) && alternate) + pos = git_strmap_lookup_index(cache, alternate); + + if (!git_strmap_valid_index(cache, pos)) { + /* unlock cache */ + return GIT_ENOTFOUND; /* don't set error - caller will cope */ + } + + if (out != NULL) { + git_submodule *sm = git_strmap_value_at(cache, pos); + GIT_REFCOUNT_INC(sm); + *out = sm; + } + + /* unlock cache */ + + return 0; +} + /* * PUBLIC APIS */ int git_submodule_lookup( - git_submodule **sm_ptr, /* NULL if user only wants to test existence */ + git_submodule **out, /* NULL if user only wants to test existence */ git_repository *repo, - const char *name) /* trailing slash is allowed */ + const char *name) /* trailing slash is allowed */ { int error; - khiter_t pos; assert(repo && name); if ((error = load_submodule_config(repo)) < 0) return error; - pos = git_strmap_lookup_index(repo->submodules, name); - - if (!git_strmap_valid_index(repo->submodules, pos)) { - error = GIT_ENOTFOUND; + if ((error = submodule_lookup(out, repo->submodules, name, NULL)) < 0) { /* check if a plausible submodule exists at path */ if (git_repository_workdir(repo)) { @@ -137,14 +165,9 @@ int git_submodule_lookup( giterr_set(GITERR_SUBMODULE, (error == GIT_ENOTFOUND) ? "No submodule named '%s'" : "Submodule '%s' has not been added yet", name); - - return error; } - if (sm_ptr) - *sm_ptr = git_strmap_value_at(repo->submodules, pos); - - return 0; + return error; } int git_submodule_foreach( @@ -203,7 +226,7 @@ void git_submodule_config_free(git_repository *repo) } int git_submodule_add_setup( - git_submodule **submodule, + git_submodule **out, git_repository *repo, const char *url, const char *path, @@ -211,7 +234,7 @@ int git_submodule_add_setup( { int error = 0; git_config_backend *mods = NULL; - git_submodule *sm; + git_submodule *sm = NULL; git_buf name = GIT_BUF_INIT, real_url = GIT_BUF_INIT; git_repository_init_options initopt = GIT_REPOSITORY_INIT_OPTIONS_INIT; git_repository *subrepo = NULL; @@ -223,6 +246,7 @@ int git_submodule_add_setup( if (git_submodule_lookup(&sm, repo, path) < 0) giterr_clear(); else { + git_submodule_free(sm); giterr_set(GITERR_SUBMODULE, "Attempt to add a submodule that already exists"); return GIT_EEXISTS; @@ -307,12 +331,16 @@ int git_submodule_add_setup( /* add submodule to hash and "reload" it */ if (!(error = submodule_get(&sm, repo, path, NULL)) && - !(error = git_submodule_reload(sm))) + !(error = git_submodule_reload(sm, false))) error = git_submodule_init(sm, false); cleanup: - if (submodule != NULL) - *submodule = !error ? sm : NULL; + if (error && sm) { + git_submodule_free(sm); + sm = NULL; + } + if (out != NULL) + *out = sm; if (mods != NULL) git_config_file_free(mods); @@ -775,8 +803,9 @@ int git_submodule_open(git_repository **subrepo, git_submodule *sm) return git_submodule__open(subrepo, sm, false); } -int git_submodule_reload_all(git_repository *repo) +int git_submodule_reload_all(git_repository *repo, int force) { + GIT_UNUSED(force); assert(repo); git_submodule_config_free(repo); return load_submodule_config(repo); @@ -855,11 +884,13 @@ static int submodule_update_head(git_submodule *submodule) return 0; } -int git_submodule_reload(git_submodule *submodule) +int git_submodule_reload(git_submodule *submodule, int force) { int error = 0; git_config_backend *mods; + GIT_UNUSED(force); + assert(submodule); /* refresh index data */ @@ -1042,17 +1073,15 @@ void git_submodule_free(git_submodule *sm) } static int submodule_get( - git_submodule **sm_ptr, + git_submodule **out, git_repository *repo, const char *name, const char *alternate) { + int error = 0; git_strmap *smcfg = repo->submodules; khiter_t pos; git_submodule *sm; - int error; - - assert(repo && name); pos = git_strmap_lookup_index(smcfg, name); @@ -1068,22 +1097,28 @@ static int submodule_get( */ pos = kh_put(str, smcfg, sm->name, &error); - if (error < 0) { - git_submodule_free(sm); - sm = NULL; - } else if (error == 0) { + if (error < 0) + goto done; + else if (error == 0) { git_submodule_free(sm); sm = git_strmap_value_at(smcfg, pos); } else { + error = 0; git_strmap_set_value_at(smcfg, pos, sm); } } else { sm = git_strmap_value_at(smcfg, pos); } - *sm_ptr = sm; +done: + if (error < 0) + git_submodule_free(sm); + else if (out) { + GIT_REFCOUNT_INC(sm); + *out = sm; + } - return (sm != NULL) ? 0 : -1; + return error; } static int submodule_config_error(const char *property, const char *value) @@ -1143,7 +1178,7 @@ static int submodule_load_from_config( const char *namestart, *property, *alternate = NULL; const char *key = entry->name, *value = entry->value, *path; git_buf name = GIT_BUF_INIT; - git_submodule *sm; + git_submodule *sm = NULL; int error = 0; if (git__prefixcmp(key, "submodule.") != 0) @@ -1242,6 +1277,7 @@ static int submodule_load_from_config( /* ignore other unknown submodule properties */ done: + git_submodule_free(sm); /* offset refcount inc from submodule_get() */ git_buf_free(&name); return error; } @@ -1293,8 +1329,10 @@ static int load_submodule_config_from_index( else sm->flags |= GIT_SUBMODULE_STATUS__INDEX_NOT_SUBMODULE; } else if (S_ISGITLINK(entry->mode)) { - if (!submodule_get(&sm, repo, entry->path, NULL)) + if (!submodule_get(&sm, repo, entry->path, NULL)) { submodule_update_from_index_entry(sm, entry); + git_submodule_free(sm); + } } else if (strcmp(entry->path, GIT_MODULES_FILE) == 0) git_oid_cpy(gitmodules_oid, &entry->id); } @@ -1339,9 +1377,11 @@ static int load_submodule_config_from_head( else sm->flags |= GIT_SUBMODULE_STATUS__HEAD_NOT_SUBMODULE; } else if (S_ISGITLINK(entry->mode)) { - if (!submodule_get(&sm, repo, entry->path, NULL)) + if (!submodule_get(&sm, repo, entry->path, NULL)) { submodule_update_from_head_data( sm, entry->mode, &entry->id); + git_submodule_free(sm); + } } else if (strcmp(entry->path, GIT_MODULES_FILE) == 0 && git_oid_iszero(gitmodules_oid)) { git_oid_cpy(gitmodules_oid, &entry->id); diff --git a/src/submodule.h b/src/submodule.h index 5e532e1ae..de7f7b581 100644 --- a/src/submodule.h +++ b/src/submodule.h @@ -128,9 +128,6 @@ extern int git_submodule_open_bare( git_repository **repo, git_submodule *submodule); -/* Release reference to submodule object - not currently for external use */ -extern void git_submodule_free(git_submodule *sm); - extern int git_submodule_parse_ignore( git_submodule_ignore_t *out, const char *value); extern int git_submodule_parse_update( diff --git a/tests/diff/submodules.c b/tests/diff/submodules.c index da96ba9c5..62e07e0c6 100644 --- a/tests/diff/submodules.c +++ b/tests/diff/submodules.c @@ -123,7 +123,7 @@ void test_diff_submodules__dirty_submodule_2(void) g_repo = setup_fixture_submodules(); - cl_git_pass(git_submodule_reload_all(g_repo)); + cl_git_pass(git_submodule_reload_all(g_repo, 1)); opts.flags = GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT | @@ -157,7 +157,7 @@ void test_diff_submodules__dirty_submodule_2(void) git_diff_free(diff); - cl_git_pass(git_submodule_reload_all(g_repo)); + cl_git_pass(git_submodule_reload_all(g_repo, 1)); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_dirty); @@ -281,7 +281,9 @@ void test_diff_submodules__invalid_cache(void) check_diff_patches(diff, expected_dirty); git_diff_free(diff); - cl_git_pass(git_submodule_reload_all(g_repo)); + git_submodule_free(sm); + + cl_git_pass(git_submodule_reload_all(g_repo, 1)); cl_git_pass(git_submodule_lookup(&sm, g_repo, smpath)); cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); @@ -334,6 +336,8 @@ void test_diff_submodules__invalid_cache(void) p_unlink("submod2/sm_changed_head/new_around_here"); + git_submodule_free(sm); + cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts)); check_diff_patches(diff, expected_moved); git_diff_free(diff); diff --git a/tests/stash/submodules.c b/tests/stash/submodules.c index 137c4408c..8cadca0f2 100644 --- a/tests/stash/submodules.c +++ b/tests/stash/submodules.c @@ -19,6 +19,9 @@ void test_stash_submodules__initialize(void) void test_stash_submodules__cleanup(void) { + git_submodule_free(sm); + sm = NULL; + git_signature_free(signature); signature = NULL; } diff --git a/tests/status/submodules.c b/tests/status/submodules.c index 80ff162fd..8575f9f2d 100644 --- a/tests/status/submodules.c +++ b/tests/status/submodules.c @@ -29,6 +29,7 @@ void test_status_submodules__api(void) cl_assert(sm != NULL); cl_assert_equal_s("testrepo", git_submodule_name(sm)); cl_assert_equal_s("testrepo", git_submodule_path(sm)); + git_submodule_free(sm); } void test_status_submodules__0(void) @@ -136,6 +137,7 @@ void test_status_submodules__moved_head(void) cl_git_pass(git_submodule_lookup(&sm, g_repo, "testrepo")); cl_git_pass(git_submodule_open(&smrepo, sm)); + git_submodule_free(sm); /* move submodule HEAD to c47800c7266a2be04c571c04d5a6614691ea99bd */ cl_git_pass( diff --git a/tests/submodule/lookup.c b/tests/submodule/lookup.c index ac3fa0415..cc29b11b2 100644 --- a/tests/submodule/lookup.c +++ b/tests/submodule/lookup.c @@ -12,31 +12,25 @@ void test_submodule_lookup__initialize(void) void test_submodule_lookup__simple_lookup(void) { - git_submodule *sm; - - /* lookup existing */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_assert(sm); + assert_submodule_exists(g_repo, "sm_unchanged"); /* lookup pending change in .gitmodules that is not in HEAD */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_assert(sm); + assert_submodule_exists(g_repo, "sm_added_and_uncommited"); - /* lookup pending change in .gitmodules that is neither in HEAD nor index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_gitmodules_only")); - cl_assert(sm); + /* lookup pending change in .gitmodules that is not in HEAD nor index */ + assert_submodule_exists(g_repo, "sm_gitmodules_only"); /* lookup git repo subdir that is not added as submodule */ - cl_assert(git_submodule_lookup(&sm, g_repo, "not-submodule") == GIT_EEXISTS); + refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS); /* lookup existing directory that is not a submodule */ - cl_assert(git_submodule_lookup(&sm, g_repo, "just_a_dir") == GIT_ENOTFOUND); + refute_submodule_exists(g_repo, "just_a_dir", GIT_ENOTFOUND); /* lookup existing file that is not a submodule */ - cl_assert(git_submodule_lookup(&sm, g_repo, "just_a_file") == GIT_ENOTFOUND); + refute_submodule_exists(g_repo, "just_a_file", GIT_ENOTFOUND); /* lookup non-existent item */ - cl_assert(git_submodule_lookup(&sm, g_repo, "no_such_file") == GIT_ENOTFOUND); + refute_submodule_exists(g_repo, "no_such_file", GIT_ENOTFOUND); } void test_submodule_lookup__accessors(void) @@ -57,6 +51,9 @@ void test_submodule_lookup__accessors(void) cl_assert(git_submodule_ignore(sm) == GIT_SUBMODULE_IGNORE_NONE); cl_assert(git_submodule_update(sm) == GIT_SUBMODULE_UPDATE_CHECKOUT); + git_submodule_free(sm); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); cl_assert_equal_s("sm_changed_head", git_submodule_name(sm)); @@ -65,6 +62,9 @@ void test_submodule_lookup__accessors(void) cl_assert(git_oid_streq(git_submodule_wd_id(sm), "3d9386c507f6b093471a3e324085657a3c2b4247") == 0); + git_submodule_free(sm); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); cl_assert_equal_s("sm_added_and_uncommited", git_submodule_name(sm)); @@ -72,6 +72,9 @@ void test_submodule_lookup__accessors(void) cl_assert(git_submodule_head_id(sm) == NULL); cl_assert(git_oid_streq(git_submodule_wd_id(sm), oid) == 0); + git_submodule_free(sm); + + cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); cl_assert_equal_s("sm_missing_commits", git_submodule_name(sm)); @@ -79,6 +82,8 @@ void test_submodule_lookup__accessors(void) cl_assert(git_oid_streq(git_submodule_head_id(sm), oid) == 0); cl_assert(git_oid_streq(git_submodule_wd_id(sm), "5e4963595a9774b90524d35a807169049de8ccad") == 0); + + git_submodule_free(sm); } typedef struct { @@ -104,69 +109,35 @@ void test_submodule_lookup__foreach(void) void test_submodule_lookup__lookup_even_with_unborn_head(void) { git_reference *head; - git_submodule *sm; /* put us on an unborn branch */ cl_git_pass(git_reference_symbolic_create( &head, g_repo, "HEAD", "refs/heads/garbage", 1, NULL, NULL)); git_reference_free(head); - /* lookup existing */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_assert(sm); - - /* lookup pending change in .gitmodules that is not in HEAD */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_assert(sm); - - /* lookup pending change in .gitmodules that is neither in HEAD nor index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_gitmodules_only")); - cl_assert(sm); - - /* lookup git repo subdir that is not added as submodule */ - cl_assert_equal_i(GIT_EEXISTS, git_submodule_lookup(&sm, g_repo, "not-submodule")); - - /* lookup existing directory that is not a submodule */ - cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_dir")); - - /* lookup existing file that is not a submodule */ - cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_file")); - - /* lookup non-existent item */ - cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "no_such_file")); + assert_submodule_exists(g_repo, "sm_unchanged"); + assert_submodule_exists(g_repo, "sm_added_and_uncommited"); + assert_submodule_exists(g_repo, "sm_gitmodules_only"); + refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS); + refute_submodule_exists(g_repo, "just_a_dir", GIT_ENOTFOUND); + refute_submodule_exists(g_repo, "just_a_file", GIT_ENOTFOUND); + refute_submodule_exists(g_repo, "no_such_file", GIT_ENOTFOUND); } void test_submodule_lookup__lookup_even_with_missing_index(void) { git_index *idx; - git_submodule *sm; /* give the repo an empty index */ cl_git_pass(git_index_new(&idx)); git_repository_set_index(g_repo, idx); git_index_free(idx); - /* lookup existing */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_assert(sm); - - /* lookup pending change in .gitmodules that is not in HEAD */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_assert(sm); - - /* lookup pending change in .gitmodules that is neither in HEAD nor index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_gitmodules_only")); - cl_assert(sm); - - /* lookup git repo subdir that is not added as submodule */ - cl_assert_equal_i(GIT_EEXISTS, git_submodule_lookup(&sm, g_repo, "not-submodule")); - - /* lookup existing directory that is not a submodule */ - cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_dir")); - - /* lookup existing file that is not a submodule */ - cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "just_a_file")); - - /* lookup non-existent item */ - cl_assert_equal_i(GIT_ENOTFOUND, git_submodule_lookup(&sm, g_repo, "no_such_file")); + assert_submodule_exists(g_repo, "sm_unchanged"); + assert_submodule_exists(g_repo, "sm_added_and_uncommited"); + assert_submodule_exists(g_repo, "sm_gitmodules_only"); + refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS); + refute_submodule_exists(g_repo, "just_a_dir", GIT_ENOTFOUND); + refute_submodule_exists(g_repo, "just_a_file", GIT_ENOTFOUND); + refute_submodule_exists(g_repo, "no_such_file", GIT_ENOTFOUND); } diff --git a/tests/submodule/modify.c b/tests/submodule/modify.c index e3e4d8aed..1aaa56388 100644 --- a/tests/submodule/modify.c +++ b/tests/submodule/modify.c @@ -21,15 +21,16 @@ void test_submodule_modify__add(void) const char *s; /* re-add existing submodule */ - cl_assert( - git_submodule_add_setup(NULL, g_repo, "whatever", "sm_unchanged", 1) == - GIT_EEXISTS ); + cl_assert_equal_i( + GIT_EEXISTS, + git_submodule_add_setup(NULL, g_repo, "whatever", "sm_unchanged", 1)); /* add a submodule using a gitlink */ cl_git_pass( git_submodule_add_setup(&sm, g_repo, SM_LIBGIT2_URL, SM_LIBGIT2, 1) ); + git_submodule_free(sm); cl_assert(git_path_isfile("submod2/" SM_LIBGIT2 "/.git")); @@ -48,6 +49,7 @@ void test_submodule_modify__add(void) cl_git_pass( git_submodule_add_setup(&sm, g_repo, SM_LIBGIT2_URL, SM_LIBGIT2B, 0) ); + git_submodule_free(sm); cl_assert(git_path_isdir("submod2/" SM_LIBGIT2B "/.git")); cl_assert(git_path_isfile("submod2/" SM_LIBGIT2B "/.git/HEAD")); @@ -95,7 +97,7 @@ void test_submodule_modify__init(void) /* call init and see that settings are copied */ cl_git_pass(git_submodule_foreach(g_repo, init_one_submodule, NULL)); - git_submodule_reload_all(g_repo); + git_submodule_reload_all(g_repo, 1); /* confirm submodule data in config */ cl_git_pass(git_repository_config(&cfg, g_repo)); @@ -159,6 +161,10 @@ void test_submodule_modify__sync(void) cl_git_pass(git_config_get_string(&str, cfg, "submodule."SM3".url")); cl_assert_equal_s(git_submodule_url(sm3), str); git_config_free(cfg); + + git_submodule_free(sm1); + git_submodule_free(sm2); + git_submodule_free(sm3); } void test_submodule_modify__edit_and_save(void) @@ -231,7 +237,7 @@ void test_submodule_modify__edit_and_save(void) cl_assert_equal_i(GIT_SUBMODULE_RECURSE_YES, git_submodule_fetch_recurse_submodules(sm1)); /* call reload and check that the new values are loaded */ - cl_git_pass(git_submodule_reload(sm1)); + cl_git_pass(git_submodule_reload(sm1, 0)); cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm1)); cl_assert_equal_i( @@ -253,16 +259,18 @@ void test_submodule_modify__edit_and_save(void) GIT_SUBMODULE_RECURSE_NO, git_submodule_fetch_recurse_submodules(sm2)); /* set fetchRecurseSubmodules on-demand */ - cl_git_pass(git_submodule_reload(sm1)); + cl_git_pass(git_submodule_reload(sm1, 0)); git_submodule_set_fetch_recurse_submodules(sm1, GIT_SUBMODULE_RECURSE_ONDEMAND); cl_assert_equal_i( GIT_SUBMODULE_RECURSE_ONDEMAND, git_submodule_fetch_recurse_submodules(sm1)); /* call save */ cl_git_pass(git_submodule_save(sm1)); - cl_git_pass(git_submodule_reload(sm1)); + cl_git_pass(git_submodule_reload(sm1, 0)); cl_assert_equal_i( GIT_SUBMODULE_RECURSE_ONDEMAND, git_submodule_fetch_recurse_submodules(sm1)); + git_submodule_free(sm1); + git_submodule_free(sm2); git_repository_free(r2); git__free(old_url); } diff --git a/tests/submodule/status.c b/tests/submodule/status.c index f5111c84f..4fa7114a4 100644 --- a/tests/submodule/status.c +++ b/tests/submodule/status.c @@ -18,19 +18,43 @@ void test_submodule_status__cleanup(void) void test_submodule_status__unchanged(void) { - unsigned int status, expected; - git_submodule *sm; - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_status(&status, sm)); - cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - expected = GIT_SUBMODULE_STATUS_IN_HEAD | + unsigned int status = get_submodule_status(g_repo, "sm_unchanged"); + unsigned int expected = + GIT_SUBMODULE_STATUS_IN_HEAD | GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS_IN_CONFIG | GIT_SUBMODULE_STATUS_IN_WD; - cl_assert(status == expected); + cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); + cl_assert(expected == status); +} + +static void rm_submodule(const char *name) +{ + git_buf path = GIT_BUF_INIT; + cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), name)); + cl_git_pass(git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)); + git_buf_free(&path); +} + +static void add_submodule_to_index(const char *name) +{ + git_submodule *sm; + cl_git_pass(git_submodule_lookup(&sm, g_repo, name)); + cl_git_pass(git_submodule_add_to_index(sm, true)); + git_submodule_free(sm); +} + +static void rm_submodule_from_index(const char *name) +{ + git_index *index; + size_t pos; + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_assert(!git_index_find(&pos, index, name)); + cl_git_pass(git_index_remove(index, name, 0)); + cl_git_pass(git_index_write(index)); + git_index_free(index); } /* 4 values of GIT_SUBMODULE_IGNORE to check */ @@ -38,81 +62,49 @@ void test_submodule_status__unchanged(void) void test_submodule_status__ignore_none(void) { unsigned int status; - git_submodule *sm; - git_buf path = GIT_BUF_INIT; - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged")); - cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); + rm_submodule("sm_unchanged"); - cl_assert_equal_i(GIT_ENOTFOUND, - git_submodule_lookup(&sm, g_repo, "just_a_dir")); - cl_assert_equal_i(GIT_EEXISTS, - git_submodule_lookup(&sm, g_repo, "not-submodule")); - cl_assert_equal_i(GIT_EEXISTS, - git_submodule_lookup(&sm, g_repo, "not")); + refute_submodule_exists(g_repo, "just_a_dir", GIT_ENOTFOUND); + refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS); + refute_submodule_exists(g_repo, "not", GIT_EEXISTS); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_index"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) != 0); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_head"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_file"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) != 0); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_untracked_file"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNTRACKED) != 0); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_missing_commits"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_added_and_uncommited"); cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0); /* removed sm_unchanged for deleted workdir */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_unchanged"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0); /* now mkdir sm_unchanged to test uninitialized */ - cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_reload(sm)); - cl_git_pass(git_submodule_status(&status, sm)); + cl_git_pass(git_futils_mkdir("sm_unchanged", "submod2", 0755, 0)); + status = get_submodule_status(g_repo, "sm_unchanged"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0); /* update sm_changed_head in index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_add_to_index(sm, true)); - /* reload is not needed because add_to_index updates the submodule data */ - cl_git_pass(git_submodule_status(&status, sm)); + add_submodule_to_index("sm_changed_head"); + status = get_submodule_status(g_repo, "sm_changed_head"); cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0); /* remove sm_changed_head from index */ - { - git_index *index; - size_t pos; - - cl_git_pass(git_repository_index(&index, g_repo)); - cl_assert(!git_index_find(&pos, index, "sm_changed_head")); - cl_git_pass(git_index_remove(index, "sm_changed_head", 0)); - cl_git_pass(git_index_write(index)); - - git_index_free(index); - } - - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_reload(sm)); - cl_git_pass(git_submodule_status(&status, sm)); + rm_submodule_from_index("sm_changed_head"); + status = get_submodule_status(g_repo, "sm_changed_head"); cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_DELETED) != 0); - - git_buf_free(&path); } static int set_sm_ignore(git_submodule *sm, const char *name, void *payload) @@ -126,191 +118,136 @@ static int set_sm_ignore(git_submodule *sm, const char *name, void *payload) void test_submodule_status__ignore_untracked(void) { unsigned int status; - git_submodule *sm; - git_buf path = GIT_BUF_INIT; git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_UNTRACKED; - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged")); - cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); - + rm_submodule("sm_unchanged"); cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign)); - cl_git_fail(git_submodule_lookup(&sm, g_repo, "not-submodule")); + refute_submodule_exists(g_repo, "just_a_dir", GIT_ENOTFOUND); + refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS); + refute_submodule_exists(g_repo, "not", GIT_EEXISTS); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_index"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_INDEX_MODIFIED) != 0); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_head"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_file"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_WD_MODIFIED) != 0); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_untracked_file"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_missing_commits"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_added_and_uncommited"); cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0); /* removed sm_unchanged for deleted workdir */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_unchanged"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0); /* now mkdir sm_unchanged to test uninitialized */ - cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_reload(sm)); - cl_git_pass(git_submodule_status(&status, sm)); + cl_git_pass(git_futils_mkdir("sm_unchanged", "submod2", 0755, 0)); + status = get_submodule_status(g_repo, "sm_unchanged"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0); /* update sm_changed_head in index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_add_to_index(sm, true)); - /* reload is not needed because add_to_index updates the submodule data */ - cl_git_pass(git_submodule_status(&status, sm)); + add_submodule_to_index("sm_changed_head"); + status = get_submodule_status(g_repo, "sm_changed_head"); cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0); - - git_buf_free(&path); } void test_submodule_status__ignore_dirty(void) { unsigned int status; - git_submodule *sm; - git_buf path = GIT_BUF_INIT; git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_DIRTY; - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged")); - cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); - + rm_submodule("sm_unchanged"); cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign)); - cl_assert_equal_i(GIT_ENOTFOUND, - git_submodule_lookup(&sm, g_repo, "just_a_dir")); - cl_assert_equal_i(GIT_EEXISTS, - git_submodule_lookup(&sm, g_repo, "not-submodule")); - cl_assert_equal_i(GIT_EEXISTS, - git_submodule_lookup(&sm, g_repo, "not")); + refute_submodule_exists(g_repo, "just_a_dir", GIT_ENOTFOUND); + refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS); + refute_submodule_exists(g_repo, "not", GIT_EEXISTS); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_index"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_head"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_file"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_untracked_file"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_missing_commits"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_MODIFIED) != 0); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_added_and_uncommited"); cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_ADDED) != 0); /* removed sm_unchanged for deleted workdir */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_unchanged"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_DELETED) != 0); /* now mkdir sm_unchanged to test uninitialized */ - cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_reload(sm)); - cl_git_pass(git_submodule_status(&status, sm)); + cl_git_pass(git_futils_mkdir("sm_unchanged", "submod2", 0755, 0)); + status = get_submodule_status(g_repo, "sm_unchanged"); cl_assert((status & GIT_SUBMODULE_STATUS_WD_UNINITIALIZED) != 0); /* update sm_changed_head in index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_add_to_index(sm, true)); - /* reload is not needed because add_to_index updates the submodule data */ - cl_git_pass(git_submodule_status(&status, sm)); + add_submodule_to_index("sm_changed_head"); + status = get_submodule_status(g_repo, "sm_changed_head"); cl_assert((status & GIT_SUBMODULE_STATUS_INDEX_MODIFIED) != 0); - - git_buf_free(&path); } void test_submodule_status__ignore_all(void) { unsigned int status; - git_submodule *sm; - git_buf path = GIT_BUF_INIT; git_submodule_ignore_t ign = GIT_SUBMODULE_IGNORE_ALL; - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged")); - cl_git_pass(git_futils_rmdir_r(git_buf_cstr(&path), NULL, GIT_RMDIR_REMOVE_FILES)); - + rm_submodule("sm_unchanged"); cl_git_pass(git_submodule_foreach(g_repo, set_sm_ignore, &ign)); - cl_assert_equal_i(GIT_ENOTFOUND, - git_submodule_lookup(&sm, g_repo, "just_a_dir")); - cl_assert_equal_i(GIT_EEXISTS, - git_submodule_lookup(&sm, g_repo, "not-submodule")); - cl_assert_equal_i(GIT_EEXISTS, - git_submodule_lookup(&sm, g_repo, "not")); + refute_submodule_exists(g_repo, "just_a_dir", GIT_ENOTFOUND); + refute_submodule_exists(g_repo, "not-submodule", GIT_EEXISTS); + refute_submodule_exists(g_repo, "not", GIT_EEXISTS); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_index")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_index"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_head"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_file")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_file"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_untracked_file")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_changed_untracked_file"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_missing_commits")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_missing_commits"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_added_and_uncommited")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_added_and_uncommited"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); /* removed sm_unchanged for deleted workdir */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_status(&status, sm)); + status = get_submodule_status(g_repo, "sm_unchanged"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); /* now mkdir sm_unchanged to test uninitialized */ - cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_reload(sm)); - cl_git_pass(git_submodule_status(&status, sm)); + cl_git_pass(git_futils_mkdir("sm_unchanged", "submod2", 0755, 0)); + status = get_submodule_status(g_repo, "sm_unchanged"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); /* update sm_changed_head in index */ - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_changed_head")); - cl_git_pass(git_submodule_add_to_index(sm, true)); - /* reload is not needed because add_to_index updates the submodule data */ - cl_git_pass(git_submodule_status(&status, sm)); + add_submodule_to_index("sm_changed_head"); + status = get_submodule_status(g_repo, "sm_changed_head"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); - - git_buf_free(&path); } typedef struct { @@ -397,29 +334,23 @@ void test_submodule_status__iterator(void) void test_submodule_status__untracked_dirs_containing_ignored_files(void) { - git_buf path = GIT_BUF_INIT; unsigned int status, expected; - git_submodule *sm; - - cl_git_pass(git_buf_joinpath(&path, git_repository_path(g_repo), "modules/sm_unchanged/info/exclude")); - cl_git_append2file(git_buf_cstr(&path), "\n*.ignored\n"); - cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "sm_unchanged/directory")); - cl_git_pass(git_futils_mkdir(git_buf_cstr(&path), NULL, 0755, 0)); - cl_git_pass(git_buf_joinpath(&path, git_buf_cstr(&path), "i_am.ignored")); - cl_git_mkfile(git_buf_cstr(&path), "ignored this file, please\n"); + cl_git_append2file( + "submod2/.git/modules/sm_unchanged/info/exclude", "\n*.ignored\n"); - cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_unchanged")); - cl_git_pass(git_submodule_status(&status, sm)); + cl_git_pass( + git_futils_mkdir("sm_unchanged/directory", "submod2", 0755, 0)); + cl_git_mkfile( + "submod2/sm_unchanged/directory/i_am.ignored", + "ignore this file, please\n"); + status = get_submodule_status(g_repo, "sm_unchanged"); cl_assert(GIT_SUBMODULE_STATUS_IS_UNMODIFIED(status)); expected = GIT_SUBMODULE_STATUS_IN_HEAD | GIT_SUBMODULE_STATUS_IN_INDEX | GIT_SUBMODULE_STATUS_IN_CONFIG | GIT_SUBMODULE_STATUS_IN_WD; - cl_assert(status == expected); - - git_buf_free(&path); } diff --git a/tests/submodule/submodule_helpers.c b/tests/submodule/submodule_helpers.c index d5750675c..546f0913a 100644 --- a/tests/submodule/submodule_helpers.c +++ b/tests/submodule/submodule_helpers.c @@ -125,3 +125,32 @@ git_repository *setup_fixture_submod2(void) return repo; } + +void assert_submodule_exists(git_repository *repo, const char *name) +{ + git_submodule *sm; + cl_git_pass(git_submodule_lookup(&sm, repo, name)); + cl_assert(sm); + git_submodule_free(sm); +} + +void refute_submodule_exists( + git_repository *repo, const char *name, int expected_error) +{ + git_submodule *sm; + cl_assert_equal_i( + expected_error, git_submodule_lookup(&sm, repo, name)); +} + +unsigned int get_submodule_status(git_repository *repo, const char *name) +{ + git_submodule *sm = NULL; + unsigned int status = 0; + + cl_git_pass(git_submodule_lookup(&sm, repo, name)); + cl_assert(sm); + cl_git_pass(git_submodule_status(&status, sm)); + git_submodule_free(sm); + + return status; +} diff --git a/tests/submodule/submodule_helpers.h b/tests/submodule/submodule_helpers.h index 610c40720..ec5510e3c 100644 --- a/tests/submodule/submodule_helpers.h +++ b/tests/submodule/submodule_helpers.h @@ -3,3 +3,8 @@ extern void rewrite_gitmodules(const char *workdir); /* these will automatically set a cleanup callback */ extern git_repository *setup_fixture_submodules(void); 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); -- cgit v1.2.1