worktree: implement `git_worktree_validate` Add a new function that checks wether a given `struct git_worktree` is valid. The validation includes checking if the gitdir, parent directory and common directory are present.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
diff --git a/include/git2/errors.h b/include/git2/errors.h
index e959ffd..1d27136 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -100,6 +100,7 @@ typedef enum {
GITERR_REBASE,
GITERR_FILESYSTEM,
GITERR_PATCH,
+ GITERR_WORKTREE
} git_error_t;
/**
diff --git a/include/git2/worktree.h b/include/git2/worktree.h
index 8313265..c6ca30b 100644
--- a/include/git2/worktree.h
+++ b/include/git2/worktree.h
@@ -49,6 +49,18 @@ GIT_EXTERN(int) git_worktree_lookup(git_worktree **out, git_repository *repo, co
*/
GIT_EXTERN(void) git_worktree_free(git_worktree *wt);
+/**
+ * Check if worktree is valid
+ *
+ * A valid worktree requires both the git data structures inside
+ * the linked parent repository and the linked working copy to be
+ * present.
+ *
+ * @param wt Worktree to check
+ * @return 0 when worktree is valid, error-code otherwise
+ */
+GIT_EXTERN(int) git_worktree_validate(const git_worktree *wt);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/src/worktree.c b/src/worktree.c
index a0e5d93..2852c18 100644
--- a/src/worktree.c
+++ b/src/worktree.c
@@ -145,3 +145,41 @@ void git_worktree_free(git_worktree *wt)
git__free(wt->name);
git__free(wt);
}
+
+int git_worktree_validate(const git_worktree *wt)
+{
+ git_buf buf = GIT_BUF_INIT;
+ int err = 0;
+
+ assert(wt);
+
+ git_buf_puts(&buf, wt->gitdir_path);
+ if (!is_worktree_dir(&buf)) {
+ giterr_set(GITERR_WORKTREE,
+ "Worktree gitdir ('%s') is not valid",
+ wt->gitlink_path);
+ err = -1;
+ goto out;
+ }
+
+ if (!git_path_exists(wt->parent_path)) {
+ giterr_set(GITERR_WORKTREE,
+ "Worktree parent directory ('%s') does not exist ",
+ wt->parent_path);
+ err = -2;
+ goto out;
+ }
+
+ if (!git_path_exists(wt->commondir_path)) {
+ giterr_set(GITERR_WORKTREE,
+ "Worktree common directory ('%s') does not exist ",
+ wt->commondir_path);
+ err = -3;
+ goto out;
+ }
+
+out:
+ git_buf_free(&buf);
+
+ return err;
+}
diff --git a/tests/worktree/worktree.c b/tests/worktree/worktree.c
index d891d6f..7e9cd25 100644
--- a/tests/worktree/worktree.c
+++ b/tests/worktree/worktree.c
@@ -203,3 +203,53 @@ void test_worktree_worktree__open_invalid_parent(void)
git_buf_free(&buf);
git_worktree_free(wt);
}
+
+void test_worktree_worktree__validate(void)
+{
+ git_worktree *wt;
+
+ cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
+ cl_git_pass(git_worktree_validate(wt));
+
+ git_worktree_free(wt);
+}
+
+void test_worktree_worktree__validate_invalid_commondir(void)
+{
+ git_worktree *wt;
+
+ cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
+ git__free(wt->commondir_path);
+ wt->commondir_path = "/path/to/invalid/commondir";
+
+ cl_git_fail(git_worktree_validate(wt));
+
+ wt->commondir_path = NULL;
+ git_worktree_free(wt);
+}
+
+void test_worktree_worktree__validate_invalid_gitdir(void)
+{
+ git_worktree *wt;
+
+ cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
+ git__free(wt->gitdir_path);
+ wt->gitdir_path = "/path/to/invalid/gitdir";
+ cl_git_fail(git_worktree_validate(wt));
+
+ wt->gitdir_path = NULL;
+ git_worktree_free(wt);
+}
+
+void test_worktree_worktree__validate_invalid_parent(void)
+{
+ git_worktree *wt;
+
+ cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
+ git__free(wt->parent_path);
+ wt->parent_path = "/path/to/invalid/parent";
+ cl_git_fail(git_worktree_validate(wt));
+
+ wt->parent_path = NULL;
+ git_worktree_free(wt);
+}