mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-03 15:27:01 +00:00
worktree: implement git_worktree_prune
Implement the `git_worktree_prune` function. This function can be used to delete working trees from a repository. According to the flags passed to it, it can either delete the working tree's gitdir only or both gitdir and the working directory.
This commit is contained in:
parent
2a503485fa
commit
f0cfc34105
@ -112,6 +112,32 @@ GIT_EXTERN(int) git_worktree_unlock(git_worktree *wt);
|
|||||||
*/
|
*/
|
||||||
GIT_EXTERN(int) git_worktree_is_locked(git_buf *reason, const git_worktree *wt);
|
GIT_EXTERN(int) git_worktree_is_locked(git_buf *reason, const git_worktree *wt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags which can be passed to git_worktree_prune to alter its
|
||||||
|
* behavior.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
/* Prune working tree even if working tree is valid */
|
||||||
|
GIT_WORKTREE_PRUNE_VALID = 1u << 0,
|
||||||
|
/* Prune working tree even if it is locked */
|
||||||
|
GIT_WORKTREE_PRUNE_LOCKED = 1u << 1,
|
||||||
|
/* Prune checked out working tree */
|
||||||
|
GIT_WORKTREE_PRUNE_WORKING_TREE = 1u << 2,
|
||||||
|
} git_worktree_prune_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prune working tree
|
||||||
|
*
|
||||||
|
* Prune the working tree, that is remove the git data
|
||||||
|
* structures on disk. The repository will only be pruned of
|
||||||
|
* `git_worktree_is_prunable` succeeds.
|
||||||
|
*
|
||||||
|
* @param wt Worktree to prune
|
||||||
|
* @param flags git_worktree_prune_t flags
|
||||||
|
* @return 0 or an error code
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_worktree_prune(git_worktree *wt, unsigned flags);
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
GIT_END_DECL
|
GIT_END_DECL
|
||||||
#endif
|
#endif
|
||||||
|
@ -356,3 +356,67 @@ out:
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_worktree_prune(git_worktree *wt, unsigned flags)
|
||||||
|
{
|
||||||
|
git_buf reason = GIT_BUF_INIT, path = GIT_BUF_INIT;
|
||||||
|
char *wtpath;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if ((flags & GIT_WORKTREE_PRUNE_LOCKED) == 0 &&
|
||||||
|
git_worktree_is_locked(&reason, wt))
|
||||||
|
{
|
||||||
|
if (!reason.size)
|
||||||
|
git_buf_attach_notowned(&reason, "no reason given", 15);
|
||||||
|
giterr_set(GITERR_WORKTREE, "Not pruning locked working tree: '%s'", reason.ptr);
|
||||||
|
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & GIT_WORKTREE_PRUNE_VALID) == 0 &&
|
||||||
|
git_worktree_validate(wt) == 0)
|
||||||
|
{
|
||||||
|
giterr_set(GITERR_WORKTREE, "Not pruning valid working tree");
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete gitdir in parent repository */
|
||||||
|
if ((err = git_buf_printf(&path, "%s/worktrees/%s", wt->parent_path, wt->name)) < 0)
|
||||||
|
goto out;
|
||||||
|
if (!git_path_exists(path.ptr))
|
||||||
|
{
|
||||||
|
giterr_set(GITERR_WORKTREE, "Worktree gitdir '%s' does not exist", path.ptr);
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((err = git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)) < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Skip deletion of the actual working tree if it does
|
||||||
|
* not exist or deletion was not requested */
|
||||||
|
if ((flags & GIT_WORKTREE_PRUNE_WORKING_TREE) == 0 ||
|
||||||
|
!git_path_exists(wt->gitlink_path))
|
||||||
|
{
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((wtpath = git_path_dirname(wt->gitlink_path)) == NULL)
|
||||||
|
goto out;
|
||||||
|
git_buf_attach(&path, wtpath, 0);
|
||||||
|
if (!git_path_exists(path.ptr))
|
||||||
|
{
|
||||||
|
giterr_set(GITERR_WORKTREE, "Working tree '%s' does not exist", path.ptr);
|
||||||
|
err = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((err = git_futils_rmdir_r(path.ptr, NULL, GIT_RMDIR_REMOVE_FILES)) < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
out:
|
||||||
|
git_buf_free(&reason);
|
||||||
|
git_buf_free(&path);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
@ -395,3 +395,61 @@ void test_worktree_worktree__unlock_locked_worktree(void)
|
|||||||
|
|
||||||
git_worktree_free(wt);
|
git_worktree_free(wt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_worktree_worktree__prune_valid(void)
|
||||||
|
{
|
||||||
|
git_worktree *wt;
|
||||||
|
git_repository *repo;
|
||||||
|
|
||||||
|
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
|
||||||
|
cl_git_pass(git_worktree_prune(wt, GIT_WORKTREE_PRUNE_VALID));
|
||||||
|
|
||||||
|
/* Assert the repository is not valid anymore */
|
||||||
|
cl_git_fail(git_repository_open_from_worktree(&repo, wt));
|
||||||
|
|
||||||
|
git_worktree_free(wt);
|
||||||
|
git_repository_free(repo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_worktree_worktree__prune_locked(void)
|
||||||
|
{
|
||||||
|
git_worktree *wt;
|
||||||
|
git_repository *repo;
|
||||||
|
|
||||||
|
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
|
||||||
|
cl_git_pass(git_worktree_lock(wt, NULL));
|
||||||
|
cl_git_fail(git_worktree_prune(wt, GIT_WORKTREE_PRUNE_VALID));
|
||||||
|
cl_git_fail(git_worktree_prune(wt, ~GIT_WORKTREE_PRUNE_LOCKED));
|
||||||
|
|
||||||
|
/* Assert the repository is still valid */
|
||||||
|
cl_git_pass(git_repository_open_from_worktree(&repo, wt));
|
||||||
|
|
||||||
|
git_worktree_free(wt);
|
||||||
|
git_repository_free(repo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_worktree_worktree__prune_gitdir(void)
|
||||||
|
{
|
||||||
|
git_worktree *wt;
|
||||||
|
|
||||||
|
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
|
||||||
|
cl_git_pass(git_worktree_prune(wt, GIT_WORKTREE_PRUNE_VALID));
|
||||||
|
|
||||||
|
cl_assert(!git_path_exists(wt->gitdir_path));
|
||||||
|
cl_assert(git_path_exists(wt->gitlink_path));
|
||||||
|
|
||||||
|
git_worktree_free(wt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_worktree_worktree__prune_both(void)
|
||||||
|
{
|
||||||
|
git_worktree *wt;
|
||||||
|
|
||||||
|
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
|
||||||
|
cl_git_pass(git_worktree_prune(wt, GIT_WORKTREE_PRUNE_WORKING_TREE | GIT_WORKTREE_PRUNE_VALID));
|
||||||
|
|
||||||
|
cl_assert(!git_path_exists(wt->gitdir_path));
|
||||||
|
cl_assert(!git_path_exists(wt->gitlink_path));
|
||||||
|
|
||||||
|
git_worktree_free(wt);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user