worktree: implement git_worktree_open_from_repository

While we already provide functionality to look up a worktree from a
repository, we cannot do so the other way round. That is given a
repository, we want to look up its worktree if it actually exists.
Getting the worktree of a repository is useful when we want to get
certain meta information like the parent's location, getting the locked
status, etc.
This commit is contained in:
Patrick Steinhardt 2017-03-15 14:24:25 +01:00
parent dfc9870647
commit 3017ba94a3
3 changed files with 71 additions and 0 deletions

View File

@ -43,6 +43,18 @@ GIT_EXTERN(int) git_worktree_list(git_strarray *out, git_repository *repo);
*/
GIT_EXTERN(int) git_worktree_lookup(git_worktree **out, git_repository *repo, const char *name);
/**
* Open a worktree of a given repository
*
* If a repository is not the main tree but a worktree, this
* function will look up the worktree inside the parent
* repository and create a new `git_worktree` structure.
*
* @param out Out-pointer for the newly allocated worktree
* @param repo Repository to look up worktree for
*/
GIT_EXTERN(int) git_worktree_open_from_repository(git_worktree **out, git_repository *repo);
/**
* Free a previously allocated worktree
*

View File

@ -186,6 +186,39 @@ out:
return error;
}
int git_worktree_open_from_repository(git_worktree **out, git_repository *repo)
{
git_buf parent = GIT_BUF_INIT;
const char *gitdir, *commondir;
char *name = NULL;
int error = 0;
if (!git_repository_is_worktree(repo)) {
giterr_set(GITERR_WORKTREE, "cannot open worktree of a non-worktree repo");
error = -1;
goto out;
}
gitdir = git_repository_path(repo);
commondir = git_repository_commondir(repo);
if ((error = git_path_prettify_dir(&parent, commondir, NULL)) < 0)
goto out;
/* The name is defined by the last component in '.git/worktree/%s' */
name = git_path_basename(gitdir);
if ((error = open_worktree_dir(out, parent.ptr, gitdir, name)) < 0)
goto out;
out:
if (error)
free(name);
git_buf_free(&parent);
return error;
}
void git_worktree_free(git_worktree *wt)
{
if (!wt)

View File

@ -1,5 +1,6 @@
#include "clar_libgit2.h"
#include "repository.h"
#include "worktree.h"
#include "worktree_helpers.h"
#define COMMON_REPO "testrepo"
@ -115,3 +116,28 @@ void test_worktree_open__repository_with_nonexistent_parent(void)
cl_fixture_cleanup(WORKTREE_REPO);
}
void test_worktree_open__open_from_repository(void)
{
git_worktree *opened, *lookedup;
cl_git_pass(git_worktree_open_from_repository(&opened, fixture.worktree));
cl_git_pass(git_worktree_lookup(&lookedup, fixture.repo, WORKTREE_REPO));
cl_assert_equal_s(opened->name, lookedup->name);
cl_assert_equal_s(opened->gitdir_path, lookedup->gitdir_path);
cl_assert_equal_s(opened->gitlink_path, lookedup->gitlink_path);
cl_assert_equal_s(opened->parent_path, lookedup->parent_path);
cl_assert_equal_s(opened->commondir_path, lookedup->commondir_path);
cl_assert_equal_i(opened->locked, lookedup->locked);
git_worktree_free(opened);
git_worktree_free(lookedup);
}
void test_worktree_open__open_from_nonworktree_fails(void)
{
git_worktree *wt;
cl_git_fail(git_worktree_open_from_repository(&wt, fixture.repo));
}