Commit 2fcb4f28 by Patrick Steinhardt

repository: introduce new function to iterate over all worktrees

Given a Git repository, it's non-trivial to iterate over all worktrees
that are associated with it, including the "main" repository. This
commit adds a new internal function `git_repository_foreach_worktree`
that does this for us.
parent d6c62852
......@@ -2254,6 +2254,51 @@ out:
return error;
}
int git_repository_foreach_worktree(git_repository *repo,
git_repository_foreach_worktree_cb cb,
void *payload)
{
git_strarray worktrees = {0};
git_repository *worktree_repo = NULL;
git_worktree *worktree = NULL;
int error;
size_t i;
if ((error = git_repository_open(&worktree_repo, repo->commondir)) < 0 ||
(error = cb(worktree_repo, payload) != 0))
goto out;
git_repository_free(worktree_repo);
worktree_repo = NULL;
if ((error = git_worktree_list(&worktrees, repo)) < 0)
goto out;
for (i = 0; i < worktrees.count; i++) {
git_repository_free(worktree_repo);
worktree_repo = NULL;
git_worktree_free(worktree);
worktree = NULL;
if ((error = git_worktree_lookup(&worktree, repo, worktrees.strings[i]) < 0) ||
(error = git_repository_open_from_worktree(&worktree_repo, worktree)) < 0) {
if (error != GIT_ENOTFOUND)
goto out;
error = 0;
continue;
}
if ((error = cb(worktree_repo, payload)) != 0)
goto out;
}
out:
git_strarray_dispose(&worktrees);
git_repository_free(worktree_repo);
git_worktree_free(worktree);
return error;
}
int git_repository_foreach_head(git_repository *repo,
git_repository_foreach_head_cb cb,
int flags, void *payload)
......
......@@ -166,6 +166,12 @@ GIT_INLINE(git_attr_cache *) git_repository_attr_cache(git_repository *repo)
int git_repository_head_tree(git_tree **tree, git_repository *repo);
int git_repository_create_head(const char *git_dir, const char *ref_name);
typedef int (*git_repository_foreach_worktree_cb)(git_repository *, void *);
int git_repository_foreach_worktree(git_repository *repo,
git_repository_foreach_worktree_cb cb,
void *payload);
/*
* Called for each HEAD.
*
......
......@@ -623,3 +623,33 @@ void test_worktree_worktree__foreach_head_gives_same_results_in_wt_and_repo(void
git_vector_free(&repo_refs);
git_vector_free(&worktree_refs);
}
static int foreach_worktree_cb(git_repository *worktree, void *payload)
{
int *counter = (int *)payload;
switch (*counter) {
case 0:
cl_assert_equal_s(git_repository_path(fixture.repo),
git_repository_path(worktree));
cl_assert(!git_repository_is_worktree(worktree));
break;
case 1:
cl_assert_equal_s(git_repository_path(fixture.worktree),
git_repository_path(worktree));
cl_assert(git_repository_is_worktree(worktree));
break;
default:
cl_fail("more worktrees found than expected");
}
(*counter)++;
return 0;
}
void test_worktree_worktree__foreach_worktree_lists_all_worktrees(void)
{
int counter = 0;
cl_git_pass(git_repository_foreach_worktree(fixture.repo, foreach_worktree_cb, &counter));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment