mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-07 12:57:05 +00:00
Merge pull request #2204 from libgit2/rb/submodule-reference-counting
Make submodules externally refcounted
This commit is contained in:
commit
dc7efa1aef
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
if (git_submodule_lookup(&sm, data->repo, wditem->path) < 0) {
|
||||
giterr_clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GIT_SUBMODULE_STATUS_IS_WD_DIRTY(sm_status))
|
||||
return true;
|
||||
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);
|
||||
|
||||
sm_oid = git_submodule_wd_id(sm);
|
||||
if (!sm_oid)
|
||||
return false;
|
||||
|
||||
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,
|
||||
@ -324,12 +328,17 @@ static bool submodule_is_config_only(
|
||||
{
|
||||
git_submodule *sm = NULL;
|
||||
unsigned int sm_loc = 0;
|
||||
bool rval = false;
|
||||
|
||||
if (git_submodule_lookup(&sm, data->repo, path) < 0 ||
|
||||
git_submodule_location(&sm_loc, sm) < 0 ||
|
||||
sm_loc == GIT_SUBMODULE_STATUS_IN_CONFIG)
|
||||
if (git_submodule_lookup(&sm, data->repo, path) < 0)
|
||||
return true;
|
||||
|
||||
if (git_submodule_location(&sm_loc, sm) < 0 ||
|
||||
sm_loc == GIT_SUBMODULE_STATUS_IN_CONFIG)
|
||||
rval = true;
|
||||
|
||||
git_submodule_free(sm);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1258,7 +1267,6 @@ static int checkout_submodule(
|
||||
const git_diff_file *file)
|
||||
{
|
||||
int error = 0;
|
||||
git_submodule *sm;
|
||||
|
||||
/* Until submodules are supported, UPDATE_ONLY means do nothing here */
|
||||
if ((data->strategy & GIT_CHECKOUT_UPDATE_ONLY) != 0)
|
||||
@ -1269,7 +1277,7 @@ static int checkout_submodule(
|
||||
data->opts.dir_mode, GIT_MKDIR_PATH)) < 0)
|
||||
return error;
|
||||
|
||||
if ((error = git_submodule_lookup(&sm, data->repo, file->path)) < 0) {
|
||||
if ((error = git_submodule_lookup(NULL, data->repo, file->path)) < 0) {
|
||||
/* I've observed repos with submodules in the tree that do not
|
||||
* have a .gitmodules - core Git just makes an empty directory
|
||||
*/
|
||||
@ -1510,7 +1518,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 +1542,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)
|
||||
|
31
src/diff.c
31
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;
|
||||
}
|
||||
|
@ -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);
|
||||
@ -312,7 +320,8 @@ static int diff_file_content_load_workdir_file(
|
||||
|
||||
error = git_filter_list_apply_to_data(&out, fl, &raw);
|
||||
|
||||
git_buf_free(&raw);
|
||||
if (out.ptr != raw.ptr)
|
||||
git_buf_free(&raw);
|
||||
|
||||
if (!error) {
|
||||
fc->map.len = out.size;
|
||||
|
219
src/submodule.c
219
src/submodule.c
@ -77,12 +77,12 @@ __KHASH_IMPL(
|
||||
str, static kh_inline, const char *, void *, 1,
|
||||
str_hash_no_trailing_slash, str_equal_no_trailing_slash);
|
||||
|
||||
static int load_submodule_config(git_repository *repo);
|
||||
static int load_submodule_config(git_repository *repo, bool reload);
|
||||
static git_config_backend *open_gitmodules(git_repository *, bool, const git_oid *);
|
||||
static int lookup_head_remote(git_buf *url, git_repository *repo);
|
||||
static int submodule_get(git_submodule **, git_repository *, const char *, const char *);
|
||||
static int submodule_load_from_config(const git_config_entry *, void *);
|
||||
static int submodule_load_from_wd_lite(git_submodule *, const char *, void *);
|
||||
static int submodule_load_from_wd_lite(git_submodule *);
|
||||
static int submodule_update_config(git_submodule *, const char *, const char *, bool, bool);
|
||||
static void submodule_get_index_status(unsigned int *, git_submodule *);
|
||||
static void submodule_get_wd_status(unsigned int *, git_submodule *, git_repository *, git_submodule_ignore_t);
|
||||
@ -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)
|
||||
if ((error = load_submodule_config(repo, false)) < 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(
|
||||
@ -159,7 +182,7 @@ int git_submodule_foreach(
|
||||
|
||||
assert(repo && callback);
|
||||
|
||||
if ((error = load_submodule_config(repo)) < 0)
|
||||
if ((error = load_submodule_config(repo, true)) < 0)
|
||||
return error;
|
||||
|
||||
git_strmap_foreach_value(repo->submodules, sm, {
|
||||
@ -198,12 +221,15 @@ void git_submodule_config_free(git_repository *repo)
|
||||
if (smcfg == NULL)
|
||||
return;
|
||||
|
||||
git_strmap_foreach_value(smcfg, sm, { git_submodule_free(sm); });
|
||||
git_strmap_foreach_value(smcfg, sm, {
|
||||
sm->repo = NULL; /* disconnect from repo */;
|
||||
git_submodule_free(sm);
|
||||
});
|
||||
git_strmap_free(smcfg);
|
||||
}
|
||||
|
||||
int git_submodule_add_setup(
|
||||
git_submodule **submodule,
|
||||
git_submodule **out,
|
||||
git_repository *repo,
|
||||
const char *url,
|
||||
const char *path,
|
||||
@ -211,7 +237,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 +249,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 +334,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,11 +806,60 @@ 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)
|
||||
static void submodule_cache_remove_item(
|
||||
git_strmap *cache,
|
||||
const char *name,
|
||||
git_submodule *expected,
|
||||
bool free_after_remove)
|
||||
{
|
||||
khiter_t pos;
|
||||
git_submodule *found;
|
||||
|
||||
if (!cache)
|
||||
return;
|
||||
|
||||
pos = git_strmap_lookup_index(cache, name);
|
||||
|
||||
if (!git_strmap_valid_index(cache, pos))
|
||||
return;
|
||||
|
||||
found = git_strmap_value_at(cache, pos);
|
||||
|
||||
if (expected && found != expected)
|
||||
return;
|
||||
|
||||
git_strmap_set_value_at(cache, pos, NULL);
|
||||
git_strmap_delete_at(cache, pos);
|
||||
|
||||
if (free_after_remove)
|
||||
git_submodule_free(found);
|
||||
}
|
||||
|
||||
int git_submodule_reload_all(git_repository *repo, int force)
|
||||
{
|
||||
int error = 0;
|
||||
git_submodule *sm;
|
||||
|
||||
GIT_UNUSED(force);
|
||||
assert(repo);
|
||||
git_submodule_config_free(repo);
|
||||
return load_submodule_config(repo);
|
||||
|
||||
if (repo->submodules)
|
||||
git_strmap_foreach_value(repo->submodules, sm, { sm->flags = 0; });
|
||||
|
||||
error = load_submodule_config(repo, true);
|
||||
|
||||
git_strmap_foreach_value(repo->submodules, sm, {
|
||||
git_strmap *cache = repo->submodules;
|
||||
|
||||
if ((sm->flags & GIT_SUBMODULE_STATUS__IN_FLAGS) == 0) {
|
||||
submodule_cache_remove_item(cache, sm->name, sm, true);
|
||||
|
||||
if (sm->path != sm->name)
|
||||
submodule_cache_remove_item(cache, sm->path, sm, true);
|
||||
}
|
||||
});
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void submodule_update_from_index_entry(
|
||||
@ -855,11 +935,14 @@ 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 */
|
||||
@ -870,6 +953,10 @@ int git_submodule_reload(git_submodule *submodule)
|
||||
if ((error = submodule_update_head(submodule)) < 0)
|
||||
return error;
|
||||
|
||||
/* done if bare */
|
||||
if (git_repository_is_bare(submodule->repo))
|
||||
return error;
|
||||
|
||||
/* refresh config data */
|
||||
mods = open_gitmodules(submodule->repo, false, NULL);
|
||||
if (mods != NULL) {
|
||||
@ -893,11 +980,9 @@ int git_submodule_reload(git_submodule *submodule)
|
||||
}
|
||||
|
||||
/* refresh wd data */
|
||||
submodule->flags = submodule->flags &
|
||||
~(GIT_SUBMODULE_STATUS_IN_WD | GIT_SUBMODULE_STATUS__WD_OID_VALID);
|
||||
submodule->flags &= ~GIT_SUBMODULE_STATUS__ALL_WD_FLAGS;
|
||||
|
||||
return submodule_load_from_wd_lite(
|
||||
submodule, submodule->path, submodule->repo);
|
||||
return submodule_load_from_wd_lite(submodule);
|
||||
}
|
||||
|
||||
static void submodule_copy_oid_maybe(
|
||||
@ -1026,6 +1111,13 @@ static void submodule_release(git_submodule *sm)
|
||||
if (!sm)
|
||||
return;
|
||||
|
||||
if (sm->repo) {
|
||||
git_strmap *cache = sm->repo->submodules;
|
||||
submodule_cache_remove_item(cache, sm->name, sm, false);
|
||||
if (sm->path != sm->name)
|
||||
submodule_cache_remove_item(cache, sm->path, sm, false);
|
||||
}
|
||||
|
||||
if (sm->path != sm->name)
|
||||
git__free(sm->path);
|
||||
git__free(sm->name);
|
||||
@ -1042,17 +1134,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 +1158,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 +1239,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)
|
||||
@ -1230,8 +1326,8 @@ static int submodule_load_from_config(
|
||||
sm->update_default = sm->update;
|
||||
}
|
||||
else if (strcasecmp(property, "fetchRecurseSubmodules") == 0) {
|
||||
if (git_submodule_parse_recurse(&sm->fetch_recurse, value) < 0)
|
||||
return -1;
|
||||
if ((error = git_submodule_parse_recurse(&sm->fetch_recurse, value)) < 0)
|
||||
goto done;
|
||||
sm->fetch_recurse_default = sm->fetch_recurse;
|
||||
}
|
||||
else if (strcasecmp(property, "ignore") == 0) {
|
||||
@ -1242,20 +1338,15 @@ 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;
|
||||
}
|
||||
|
||||
static int submodule_load_from_wd_lite(
|
||||
git_submodule *sm, const char *name, void *payload)
|
||||
static int submodule_load_from_wd_lite(git_submodule *sm)
|
||||
{
|
||||
git_buf path = GIT_BUF_INIT;
|
||||
|
||||
GIT_UNUSED(name); GIT_UNUSED(payload);
|
||||
|
||||
if (git_repository_is_bare(sm->repo))
|
||||
return 0;
|
||||
|
||||
if (git_buf_joinpath(&path, git_repository_workdir(sm->repo), sm->path) < 0)
|
||||
return -1;
|
||||
|
||||
@ -1293,8 +1384,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 +1432,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);
|
||||
@ -1395,13 +1490,13 @@ static git_config_backend *open_gitmodules(
|
||||
return mods;
|
||||
}
|
||||
|
||||
static int load_submodule_config(git_repository *repo)
|
||||
static int load_submodule_config(git_repository *repo, bool reload)
|
||||
{
|
||||
int error;
|
||||
git_oid gitmodules_oid;
|
||||
git_config_backend *mods = NULL;
|
||||
|
||||
if (repo->submodules)
|
||||
if (!reload && repo->submodules)
|
||||
return 0;
|
||||
|
||||
memset(&gitmodules_oid, 0, sizeof(gitmodules_oid));
|
||||
@ -1414,6 +1509,8 @@ static int load_submodule_config(git_repository *repo)
|
||||
GITERR_CHECK_ALLOC(repo->submodules);
|
||||
}
|
||||
|
||||
/* TODO: only do the following if the sources appear modified */
|
||||
|
||||
/* add submodule information from index */
|
||||
|
||||
if ((error = load_submodule_config_from_index(repo, &gitmodules_oid)) < 0)
|
||||
@ -1433,8 +1530,16 @@ static int load_submodule_config(git_repository *repo)
|
||||
|
||||
/* shallow scan submodules in work tree */
|
||||
|
||||
if (!git_repository_is_bare(repo))
|
||||
error = git_submodule_foreach(repo, submodule_load_from_wd_lite, NULL);
|
||||
if (!git_repository_is_bare(repo)) {
|
||||
git_submodule *sm;
|
||||
|
||||
git_strmap_foreach_value(repo->submodules, sm, {
|
||||
sm->flags &= ~GIT_SUBMODULE_STATUS__ALL_WD_FLAGS;
|
||||
});
|
||||
git_strmap_foreach_value(repo->submodules, sm, {
|
||||
submodule_load_from_wd_lite(sm);
|
||||
});
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (mods != NULL)
|
||||
|
@ -111,6 +111,11 @@ enum {
|
||||
GIT_SUBMODULE_STATUS__INDEX_MULTIPLE_ENTRIES = (1u << 27),
|
||||
};
|
||||
|
||||
#define GIT_SUBMODULE_STATUS__ALL_WD_FLAGS \
|
||||
(GIT_SUBMODULE_STATUS_IN_WD | \
|
||||
GIT_SUBMODULE_STATUS__WD_OID_VALID | \
|
||||
GIT_SUBMODULE_STATUS__WD_FLAGS)
|
||||
|
||||
#define GIT_SUBMODULE_STATUS__CLEAR_INTERNAL(S) \
|
||||
((S) & ~(0xFFFFFFFFu << 20))
|
||||
|
||||
@ -128,9 +133,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(
|
||||
|
@ -131,7 +131,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 |
|
||||
@ -165,7 +165,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);
|
||||
@ -291,7 +291,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));
|
||||
@ -344,6 +346,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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
@ -401,29 +338,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_append2file(
|
||||
"submod2/.git/modules/sm_unchanged/info/exclude", "\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_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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user