diff options
author | Patrick Steinhardt <ps@pks.im> | 2020-06-17 14:09:04 +0200 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2020-07-12 18:12:16 +0200 |
commit | 2fcb4f2801ef9a1e74b4281a78deae5e25b0ad43 (patch) | |
tree | 956f69765ded9973b8453950b02d0b34a05d61a1 | |
parent | d6c62852076005053be9169cb4f3cd9cf9db2aea (diff) | |
download | libgit2-2fcb4f2801ef9a1e74b4281a78deae5e25b0ad43.tar.gz |
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.
-rw-r--r-- | src/repository.c | 45 | ||||
-rw-r--r-- | src/repository.h | 6 | ||||
-rw-r--r-- | tests/worktree/worktree.c | 30 |
3 files changed, 81 insertions, 0 deletions
diff --git a/src/repository.c b/src/repository.c index 5e818fb82..6c7370324 100644 --- a/src/repository.c +++ b/src/repository.c @@ -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) diff --git a/src/repository.h b/src/repository.h index bafdb5896..a823bdcd9 100644 --- a/src/repository.h +++ b/src/repository.h @@ -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. * diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c index 716d0aa0a..a08c305bc 100644 --- a/tests/worktree/worktree.c +++ b/tests/worktree/worktree.c @@ -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)); +} |