Skip to content

Commit 74511aa

Browse files
committed
repository: add function to iterate over all HEADs
While we already provide functions to get the current repository's HEAD, it is quite involved to iterate over HEADs of both the repository and all linked work trees. This commit implements a function `git_repository_foreach_head`, which accepts a callback which is then called for all HEAD files.
1 parent 3e84aa5 commit 74511aa

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

src/repository.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2137,6 +2137,38 @@ int git_repository_head_for_worktree(git_reference **out, git_repository *repo,
21372137
return error;
21382138
}
21392139

2140+
int git_repository_foreach_head(git_repository *repo, git_repository_foreach_head_cb cb, void *payload)
2141+
{
2142+
git_strarray worktrees = GIT_VECTOR_INIT;
2143+
git_buf path = GIT_BUF_INIT;
2144+
int error;
2145+
size_t i;
2146+
2147+
/* Execute callback for HEAD of commondir */
2148+
if ((error = git_buf_joinpath(&path, repo->commondir, GIT_HEAD_FILE)) < 0 ||
2149+
(error = cb(repo, path.ptr, payload) != 0))
2150+
goto out;
2151+
2152+
if ((error = git_worktree_list(&worktrees, repo)) < 0) {
2153+
error = 0;
2154+
goto out;
2155+
}
2156+
2157+
/* Execute callback for all worktree HEADs */
2158+
for (i = 0; i < worktrees.count; i++) {
2159+
if (get_worktree_file_path(&path, repo, worktrees.strings[i], GIT_HEAD_FILE) < 0)
2160+
continue;
2161+
2162+
if ((error = cb(repo, path.ptr, payload)) != 0)
2163+
goto out;
2164+
}
2165+
2166+
out:
2167+
git_buf_free(&path);
2168+
git_strarray_free(&worktrees);
2169+
return error;
2170+
}
2171+
21402172
int git_repository_head_unborn(git_repository *repo)
21412173
{
21422174
git_reference *ref = NULL;

src/repository.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,26 @@ GIT_INLINE(git_attr_cache *) git_repository_attr_cache(git_repository *repo)
159159
int git_repository_head_tree(git_tree **tree, git_repository *repo);
160160
int git_repository_create_head(const char *git_dir, const char *ref_name);
161161

162+
/*
163+
* Called for each HEAD.
164+
*
165+
* Can return either 0, causing the iteration over HEADs to
166+
* continue, or a non-0 value causing the iteration to abort. The
167+
* return value is passed back to the caller of
168+
* `git_repository_foreach_head`
169+
*/
170+
typedef int (*git_repository_foreach_head_cb)(git_repository *repo, const char *path, void *payload);
171+
172+
/*
173+
* Iterate over repository and all worktree HEADs.
174+
*
175+
* This function will be called for the repository HEAD and for
176+
* all HEADS of linked worktrees. For each HEAD, the callback is
177+
* executed with the given payload. The return value equals the
178+
* return value of the last executed callback function.
179+
*/
180+
int git_repository_foreach_head(git_repository *repo, git_repository_foreach_head_cb cb, void *payload);
181+
162182
/*
163183
* Weak pointers to repository internals.
164184
*

0 commit comments

Comments
 (0)