summaryrefslogtreecommitdiff
path: root/src/worktree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/worktree.c')
-rw-r--r--src/worktree.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/worktree.c b/src/worktree.c
index 28d895d5c..a0e5d934a 100644
--- a/src/worktree.c
+++ b/src/worktree.c
@@ -9,6 +9,7 @@
#include "common.h"
#include "repository.h"
+#include "worktree.h"
static bool is_worktree_dir(git_buf *dir)
{
@@ -56,3 +57,91 @@ exit:
return error;
}
+
+static char *read_link(const char *base, const char *file)
+{
+ git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT;
+
+ assert(base && file);
+
+ if (git_buf_joinpath(&path, base, file) < 0)
+ goto err;
+ if (git_futils_readbuffer(&buf, path.ptr) < 0)
+ goto err;
+ git_buf_free(&path);
+
+ git_buf_rtrim(&buf);
+
+ if (!git_path_is_relative(buf.ptr))
+ return git_buf_detach(&buf);
+
+ if (git_buf_sets(&path, base) < 0)
+ goto err;
+ if (git_path_apply_relative(&path, buf.ptr) < 0)
+ goto err;
+ git_buf_free(&buf);
+
+ return git_buf_detach(&path);
+
+err:
+ git_buf_free(&buf);
+ git_buf_free(&path);
+
+ return NULL;
+}
+
+int git_worktree_lookup(git_worktree **out, git_repository *repo, const char *name)
+{
+ git_buf path = GIT_BUF_INIT;
+ git_worktree *wt = NULL;
+ int error;
+
+ assert(repo && name);
+
+ *out = NULL;
+
+ if ((error = git_buf_printf(&path, "%s/worktrees/%s", repo->commondir, name)) < 0)
+ goto out;
+
+ if (!is_worktree_dir(&path)) {
+ error = -1;
+ goto out;
+ }
+
+ if ((wt = git__malloc(sizeof(struct git_repository))) == NULL) {
+ error = -1;
+ goto out;
+ }
+
+ if ((wt->name = git__strdup(name)) == NULL
+ || (wt->commondir_path = read_link(path.ptr, "commondir")) == NULL
+ || (wt->gitlink_path = read_link(path.ptr, "gitdir")) == NULL
+ || (wt->parent_path = git__strdup(git_repository_path(repo))) == NULL) {
+ error = -1;
+ goto out;
+ }
+ wt->gitdir_path = git_buf_detach(&path);
+
+ (*out) = wt;
+
+out:
+ git_buf_free(&path);
+
+ if (error)
+ git_worktree_free(wt);
+
+ return error;
+}
+
+void git_worktree_free(git_worktree *wt)
+{
+ if (!wt)
+ return;
+
+ git__free(wt->commondir_path);
+ git__free(wt->gitlink_path);
+ git__free(wt->gitdir_path);
+ git__free(wt->parent_path);
+ git__free(wt->name);
+ git__free(wt);
+}