summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2023-05-16 12:41:41 +0100
committerEdward Thomson <ethomson@edwardthomson.com>2023-05-16 12:41:41 +0100
commitf041a94e2c358e84adb5a0fe108288fcb3802970 (patch)
treeb01428dbfdd3e41123aa8cbee3da857affd839e5
parent9d41a3fd694d983ade53fb602a58f6df25ce0656 (diff)
parent12b54ae00948a7a8422af53a8e98a5aa4d51f1f7 (diff)
downloadlibgit2-main.tar.gz
Merge branch 'worktree_prunable' (PR #5712)HEADmain
-rw-r--r--include/git2/worktree.h4
-rw-r--r--src/libgit2/worktree.c35
-rw-r--r--tests/libgit2/worktree/worktree.c13
3 files changed, 41 insertions, 11 deletions
diff --git a/include/git2/worktree.h b/include/git2/worktree.h
index bb024dc94..9193eaf34 100644
--- a/include/git2/worktree.h
+++ b/include/git2/worktree.h
@@ -237,7 +237,9 @@ GIT_EXTERN(int) git_worktree_prune_options_init(
*
* If the worktree is not valid and not locked or if the above
* flags have been passed in, this function will return a
- * positive value.
+ * positive value. If the worktree is not prunable, an error
+ * message will be set (visible in `giterr_last`) with details about
+ * why.
*
* @param wt Worktree to check.
* @param opts The prunable options.
diff --git a/src/libgit2/worktree.c b/src/libgit2/worktree.c
index 82e1d2d7e..a878634ca 100644
--- a/src/libgit2/worktree.c
+++ b/src/libgit2/worktree.c
@@ -565,6 +565,8 @@ int git_worktree_is_prunable(git_worktree *wt,
git_worktree_prune_options *opts)
{
git_worktree_prune_options popts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
+ git_str path = GIT_STR_INIT;
+ int ret = 0;
GIT_ERROR_CHECK_VERSION(
opts, GIT_WORKTREE_PRUNE_OPTIONS_VERSION,
@@ -575,27 +577,40 @@ int git_worktree_is_prunable(git_worktree *wt,
if ((popts.flags & GIT_WORKTREE_PRUNE_LOCKED) == 0) {
git_str reason = GIT_STR_INIT;
- int error;
- if ((error = git_worktree__is_locked(&reason, wt)) < 0)
- return error;
+ if ((ret = git_worktree__is_locked(&reason, wt)) < 0)
+ goto out;
+
+ if (ret) {
+ git_error_set(GIT_ERROR_WORKTREE,
+ "not pruning locked working tree: '%s'",
+ reason.size ? reason.ptr : "is locked");
- if (error) {
- if (!reason.size)
- git_str_attach_notowned(&reason, "no reason given", 15);
- git_error_set(GIT_ERROR_WORKTREE, "not pruning locked working tree: '%s'", reason.ptr);
git_str_dispose(&reason);
- return 0;
+ ret = 0;
+ goto out;
}
}
if ((popts.flags & GIT_WORKTREE_PRUNE_VALID) == 0 &&
git_worktree_validate(wt) == 0) {
git_error_set(GIT_ERROR_WORKTREE, "not pruning valid working tree");
- return 0;
+ goto out;
}
- return 1;
+ if ((ret = git_str_printf(&path, "%s/worktrees/%s", wt->commondir_path, wt->name) < 0))
+ goto out;
+
+ if (!git_fs_path_exists(path.ptr)) {
+ git_error_set(GIT_ERROR_WORKTREE, "worktree gitdir ('%s') does not exist", path.ptr);
+ goto out;
+ }
+
+ ret = 1;
+
+out:
+ git_str_dispose(&path);
+ return ret;
}
int git_worktree_prune(git_worktree *wt,
diff --git a/tests/libgit2/worktree/worktree.c b/tests/libgit2/worktree/worktree.c
index 9fd27f49c..fed5c9259 100644
--- a/tests/libgit2/worktree/worktree.c
+++ b/tests/libgit2/worktree/worktree.c
@@ -645,3 +645,16 @@ void test_worktree_worktree__validate_invalid_worktreedir(void)
git_worktree_free(wt);
}
+
+void test_worktree_worktree__is_prunable_missing_repo(void)
+{
+ git_worktree *wt;
+
+ cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
+ p_rename("testrepo", "testrepo-tmp");
+ /* Should not be prunable since the repository moved */
+ cl_assert(!git_worktree_is_prunable(wt, NULL));
+ p_rename("testrepo-tmp", "testrepo");
+
+ git_worktree_free(wt);
+}