Commit 3017ba94 by Patrick Steinhardt

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.
parent dfc98706
...@@ -44,6 +44,18 @@ GIT_EXTERN(int) git_worktree_list(git_strarray *out, git_repository *repo); ...@@ -44,6 +44,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); 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 * Free a previously allocated worktree
* *
* @param wt worktree handle to close. If NULL nothing occurs. * @param wt worktree handle to close. If NULL nothing occurs.
......
...@@ -186,6 +186,39 @@ out: ...@@ -186,6 +186,39 @@ out:
return error; 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) void git_worktree_free(git_worktree *wt)
{ {
if (!wt) if (!wt)
......
#include "clar_libgit2.h" #include "clar_libgit2.h"
#include "repository.h" #include "repository.h"
#include "worktree.h"
#include "worktree_helpers.h" #include "worktree_helpers.h"
#define COMMON_REPO "testrepo" #define COMMON_REPO "testrepo"
...@@ -115,3 +116,28 @@ void test_worktree_open__repository_with_nonexistent_parent(void) ...@@ -115,3 +116,28 @@ void test_worktree_open__repository_with_nonexistent_parent(void)
cl_fixture_cleanup(WORKTREE_REPO); 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));
}
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