Skip to content

Commit 883eeb5

Browse files
committed
worktree: switch over worktree pruning to an opts structure
The current signature of `git_worktree_prune` accepts a flags field to alter its behavior. This is not as flexible as we'd like it to be when we want to enable passing additional options in the future. As the function has not been part of any release yet, we are still free to alter its current signature. This commit does so by using our usual pattern of an options structure, which is easily extendable without breaking the API.
1 parent 8264a30 commit 883eeb5

File tree

4 files changed

+103
-23
lines changed

4 files changed

+103
-23
lines changed

include/git2/worktree.h

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,23 +161,44 @@ typedef enum {
161161
GIT_WORKTREE_PRUNE_WORKING_TREE = 1u << 2,
162162
} git_worktree_prune_t;
163163

164+
typedef struct git_worktree_prune_options {
165+
unsigned int version;
166+
167+
uint32_t flags;
168+
} git_worktree_prune_options;
169+
170+
#define GIT_WORKTREE_PRUNE_OPTIONS_VERSION 1
171+
#define GIT_WORKTREE_PRUNE_OPTIONS_INIT {GIT_WORKTREE_PRUNE_OPTIONS_VERSION,0}
172+
173+
/**
174+
* Initializes a `git_worktree_prune_options` with default vaules.
175+
* Equivalent to creating an instance with
176+
* GIT_WORKTREE_PRUNE_OPTIONS_INIT.
177+
*
178+
* @param opts the struct to initialize
179+
* @param version Verison of struct; pass `GIT_WORKTREE_PRUNE_OPTIONS_VERSION`
180+
* @return Zero on success; -1 on failure.
181+
*/
182+
GIT_EXTERN(int) git_worktree_prune_init_options(
183+
git_worktree_prune_options *opts,
184+
unsigned int version);
185+
164186
/**
165-
* Is the worktree prunable with the given set of flags?
187+
* Is the worktree prunable with the given options?
166188
*
167189
* A worktree is not prunable in the following scenarios:
168190
*
169191
* - the worktree is linking to a valid on-disk worktree. The
170-
* GIT_WORKTREE_PRUNE_VALID flag will cause this check to be
171-
* ignored.
172-
* - the worktree is not valid but locked. The
173-
* GIT_WORKRTEE_PRUNE_LOCKED flag will cause this check to be
174-
* ignored.
192+
* `valid` member will cause this check to be ignored.
193+
* - the worktree is locked. The `locked` flag will cause this
194+
* check to be ignored.
175195
*
176196
* If the worktree is not valid and not locked or if the above
177197
* flags have been passed in, this function will return a
178198
* positive value.
179199
*/
180-
GIT_EXTERN(int) git_worktree_is_prunable(git_worktree *wt, unsigned flags);
200+
GIT_EXTERN(int) git_worktree_is_prunable(git_worktree *wt,
201+
git_worktree_prune_options *opts);
181202

182203
/**
183204
* Prune working tree
@@ -187,10 +208,12 @@ GIT_EXTERN(int) git_worktree_is_prunable(git_worktree *wt, unsigned flags);
187208
* `git_worktree_is_prunable` succeeds.
188209
*
189210
* @param wt Worktree to prune
190-
* @param flags git_worktree_prune_t flags
211+
* @param opts Specifies which checks to override. See
212+
* `git_worktree_is_prunable`. May be NULL
191213
* @return 0 or an error code
192214
*/
193-
GIT_EXTERN(int) git_worktree_prune(git_worktree *wt, unsigned flags);
215+
GIT_EXTERN(int) git_worktree_prune(git_worktree *wt,
216+
git_worktree_prune_options *opts);
194217

195218
/** @} */
196219
GIT_END_DECL

src/worktree.c

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -456,11 +456,29 @@ int git_worktree_is_locked(git_buf *reason, const git_worktree *wt)
456456
return ret;
457457
}
458458

459-
int git_worktree_is_prunable(git_worktree *wt, unsigned flags)
459+
int git_worktree_prune_init_options(
460+
git_worktree_prune_options *opts,
461+
unsigned int version)
462+
{
463+
GIT_INIT_STRUCTURE_FROM_TEMPLATE(opts, version,
464+
git_worktree_prune_options, GIT_WORKTREE_PRUNE_OPTIONS_INIT);
465+
return 0;
466+
}
467+
468+
int git_worktree_is_prunable(git_worktree *wt,
469+
git_worktree_prune_options *opts)
460470
{
461471
git_buf reason = GIT_BUF_INIT;
472+
git_worktree_prune_options popts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
473+
474+
GITERR_CHECK_VERSION(
475+
opts, GIT_WORKTREE_PRUNE_OPTIONS_VERSION,
476+
"git_worktree_prune_options");
477+
478+
if (opts)
479+
memcpy(&popts, opts, sizeof(popts));
462480

463-
if ((flags & GIT_WORKTREE_PRUNE_LOCKED) == 0 &&
481+
if ((popts.flags & GIT_WORKTREE_PRUNE_LOCKED) == 0 &&
464482
git_worktree_is_locked(&reason, wt))
465483
{
466484
if (!reason.size)
@@ -471,7 +489,7 @@ int git_worktree_is_prunable(git_worktree *wt, unsigned flags)
471489
return 0;
472490
}
473491

474-
if ((flags & GIT_WORKTREE_PRUNE_VALID) == 0 &&
492+
if ((popts.flags & GIT_WORKTREE_PRUNE_VALID) == 0 &&
475493
git_worktree_validate(wt) == 0)
476494
{
477495
giterr_set(GITERR_WORKTREE, "Not pruning valid working tree");
@@ -481,13 +499,22 @@ int git_worktree_is_prunable(git_worktree *wt, unsigned flags)
481499
return 1;
482500
}
483501

484-
int git_worktree_prune(git_worktree *wt, unsigned flags)
502+
int git_worktree_prune(git_worktree *wt,
503+
git_worktree_prune_options *opts)
485504
{
505+
git_worktree_prune_options popts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
486506
git_buf path = GIT_BUF_INIT;
487507
char *wtpath;
488508
int err;
489509

490-
if (!git_worktree_is_prunable(wt, flags)) {
510+
GITERR_CHECK_VERSION(
511+
opts, GIT_WORKTREE_PRUNE_OPTIONS_VERSION,
512+
"git_worktree_prune_options");
513+
514+
if (opts)
515+
memcpy(&popts, opts, sizeof(popts));
516+
517+
if (!git_worktree_is_prunable(wt, &popts)) {
491518
err = -1;
492519
goto out;
493520
}
@@ -506,7 +533,7 @@ int git_worktree_prune(git_worktree *wt, unsigned flags)
506533

507534
/* Skip deletion of the actual working tree if it does
508535
* not exist or deletion was not requested */
509-
if ((flags & GIT_WORKTREE_PRUNE_WORKING_TREE) == 0 ||
536+
if ((popts.flags & GIT_WORKTREE_PRUNE_WORKING_TREE) == 0 ||
510537
!git_path_exists(wt->gitlink_path))
511538
{
512539
goto out;

tests/worktree/refs.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,14 @@ void test_worktree_refs__delete_fails_for_checked_out_branch(void)
118118

119119
void test_worktree_refs__delete_succeeds_after_pruning_worktree(void)
120120
{
121+
git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
121122
git_reference *branch;
122123
git_worktree *worktree;
123124

125+
opts.flags = GIT_WORKTREE_PRUNE_VALID;
126+
124127
cl_git_pass(git_worktree_lookup(&worktree, fixture.repo, fixture.worktreename));
125-
cl_git_pass(git_worktree_prune(worktree, GIT_WORKTREE_PRUNE_VALID));
128+
cl_git_pass(git_worktree_prune(worktree, &opts));
126129
git_worktree_free(worktree);
127130

128131
cl_git_pass(git_branch_lookup(&branch, fixture.repo,

tests/worktree/worktree.c

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -454,13 +454,31 @@ void test_worktree_worktree__unlock_locked_worktree(void)
454454
git_worktree_free(wt);
455455
}
456456

457+
void test_worktree_worktree__prune_without_opts_fails(void)
458+
{
459+
git_worktree *wt;
460+
git_repository *repo;
461+
462+
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
463+
cl_git_fail(git_worktree_prune(wt, NULL));
464+
465+
/* Assert the repository is still valid */
466+
cl_git_pass(git_repository_open_from_worktree(&repo, wt));
467+
468+
git_worktree_free(wt);
469+
git_repository_free(repo);
470+
}
471+
457472
void test_worktree_worktree__prune_valid(void)
458473
{
474+
git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
459475
git_worktree *wt;
460476
git_repository *repo;
461477

478+
opts.flags = GIT_WORKTREE_PRUNE_VALID;
479+
462480
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
463-
cl_git_pass(git_worktree_prune(wt, GIT_WORKTREE_PRUNE_VALID));
481+
cl_git_pass(git_worktree_prune(wt, &opts));
464482

465483
/* Assert the repository is not valid anymore */
466484
cl_git_fail(git_repository_open_from_worktree(&repo, wt));
@@ -471,40 +489,49 @@ void test_worktree_worktree__prune_valid(void)
471489

472490
void test_worktree_worktree__prune_locked(void)
473491
{
492+
git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
474493
git_worktree *wt;
475494
git_repository *repo;
476495

477496
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
478497
cl_git_pass(git_worktree_lock(wt, NULL));
479-
cl_git_fail(git_worktree_prune(wt, GIT_WORKTREE_PRUNE_VALID));
480-
cl_git_fail(git_worktree_prune(wt, ~GIT_WORKTREE_PRUNE_LOCKED));
481498

499+
opts.flags = GIT_WORKTREE_PRUNE_VALID;
500+
cl_git_fail(git_worktree_prune(wt, &opts));
482501
/* Assert the repository is still valid */
483502
cl_git_pass(git_repository_open_from_worktree(&repo, wt));
484503

504+
opts.flags = GIT_WORKTREE_PRUNE_VALID|GIT_WORKTREE_PRUNE_LOCKED;
505+
cl_git_pass(git_worktree_prune(wt, &opts));
506+
485507
git_worktree_free(wt);
486508
git_repository_free(repo);
487509
}
488510

489-
void test_worktree_worktree__prune_gitdir(void)
511+
void test_worktree_worktree__prune_gitdir_only(void)
490512
{
513+
git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
491514
git_worktree *wt;
492515

516+
opts.flags = GIT_WORKTREE_PRUNE_VALID;
493517
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
494-
cl_git_pass(git_worktree_prune(wt, GIT_WORKTREE_PRUNE_VALID));
518+
cl_git_pass(git_worktree_prune(wt, &opts));
495519

496520
cl_assert(!git_path_exists(wt->gitdir_path));
497521
cl_assert(git_path_exists(wt->gitlink_path));
498522

499523
git_worktree_free(wt);
500524
}
501525

502-
void test_worktree_worktree__prune_both(void)
526+
void test_worktree_worktree__prune_worktree(void)
503527
{
528+
git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
504529
git_worktree *wt;
505530

531+
opts.flags = GIT_WORKTREE_PRUNE_VALID|GIT_WORKTREE_PRUNE_WORKING_TREE;
532+
506533
cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
507-
cl_git_pass(git_worktree_prune(wt, GIT_WORKTREE_PRUNE_WORKING_TREE | GIT_WORKTREE_PRUNE_VALID));
534+
cl_git_pass(git_worktree_prune(wt, &opts));
508535

509536
cl_assert(!git_path_exists(wt->gitdir_path));
510537
cl_assert(!git_path_exists(wt->gitlink_path));

0 commit comments

Comments
 (0)