worktree.c 17.9 KB
Newer Older
1 2
#include "clar_libgit2.h"
#include "worktree_helpers.h"
3
#include "submodule/submodule_helpers.h"
4

5
#include "checkout.h"
6
#include "repository.h"
7
#include "worktree.h"
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

#define COMMON_REPO "testrepo"
#define WORKTREE_REPO "testrepo-worktree"

static worktree_fixture fixture =
	WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO);

void test_worktree_worktree__initialize(void)
{
	setup_fixture_worktree(&fixture);
}

void test_worktree_worktree__cleanup(void)
{
	cleanup_fixture_worktree(&fixture);
}

void test_worktree_worktree__list(void)
{
	git_strarray wts;

	cl_git_pass(git_worktree_list(&wts, fixture.repo));
	cl_assert_equal_i(wts.count, 1);
	cl_assert_equal_s(wts.strings[0], "testrepo-worktree");

33
	git_strarray_dispose(&wts);
34 35 36 37 38 39 40 41 42
}

void test_worktree_worktree__list_with_invalid_worktree_dirs(void)
{
	const char *filesets[3][2] = {
		{ "gitdir", "commondir" },
		{ "gitdir", "HEAD" },
		{ "HEAD", "commondir" },
	};
43
	git_str path = GIT_STR_INIT;
44
	git_strarray wts;
45
	size_t i, j, len;
46

47
	cl_git_pass(git_str_joinpath(&path,
48 49
	            fixture.repo->commondir,
	            "worktrees/invalid"));
50 51 52 53 54 55 56
	cl_git_pass(p_mkdir(path.ptr, 0755));

	len = path.size;

	for (i = 0; i < ARRAY_SIZE(filesets); i++) {

		for (j = 0; j < ARRAY_SIZE(filesets[i]); j++) {
57 58
			git_str_truncate(&path, len);
			cl_git_pass(git_str_joinpath(&path, path.ptr, filesets[i][j]));
59 60 61 62 63 64
			cl_git_pass(p_close(p_creat(path.ptr, 0644)));
		}

		cl_git_pass(git_worktree_list(&wts, fixture.worktree));
		cl_assert_equal_i(wts.count, 1);
		cl_assert_equal_s(wts.strings[0], "testrepo-worktree");
65
		git_strarray_dispose(&wts);
66 67

		for (j = 0; j < ARRAY_SIZE(filesets[i]); j++) {
68 69
			git_str_truncate(&path, len);
			cl_git_pass(git_str_joinpath(&path, path.ptr, filesets[i][j]));
70 71 72 73
			p_unlink(path.ptr);
		}
	}

74
	git_str_dispose(&path);
75 76 77 78 79 80 81 82 83 84
}

void test_worktree_worktree__list_in_worktree_repo(void)
{
	git_strarray wts;

	cl_git_pass(git_worktree_list(&wts, fixture.worktree));
	cl_assert_equal_i(wts.count, 1);
	cl_assert_equal_s(wts.strings[0], "testrepo-worktree");

85
	git_strarray_dispose(&wts);
86 87 88 89 90 91 92 93 94 95 96 97 98
}

void test_worktree_worktree__list_without_worktrees(void)
{
	git_repository *repo;
	git_strarray wts;

	repo = cl_git_sandbox_init("testrepo2");
	cl_git_pass(git_worktree_list(&wts, repo));
	cl_assert_equal_i(wts.count, 0);

	git_repository_free(repo);
}
99 100 101 102

void test_worktree_worktree__lookup(void)
{
	git_worktree *wt;
103
	git_str gitdir_path = GIT_STR_INIT;
104 105 106

	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));

107
	cl_git_pass(git_str_joinpath(&gitdir_path, fixture.repo->commondir, "worktrees/testrepo-worktree/"));
108 109

	cl_assert_equal_s(wt->gitdir_path, gitdir_path.ptr);
110
	cl_assert_equal_s(wt->parent_path, fixture.repo->workdir);
111
	cl_assert_equal_s(wt->gitlink_path, fixture.worktree->gitlink);
112
	cl_assert_equal_s(wt->commondir_path, fixture.repo->gitdir);
113 114
	cl_assert_equal_s(wt->commondir_path, fixture.repo->commondir);

115
	git_str_dispose(&gitdir_path);
116 117 118 119 120 121 122 123 124 125
	git_worktree_free(wt);
}

void test_worktree_worktree__lookup_nonexistent_worktree(void)
{
	git_worktree *wt;

	cl_git_fail(git_worktree_lookup(&wt, fixture.repo, "nonexistent"));
	cl_assert_equal_p(wt, NULL);
}
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145

void test_worktree_worktree__open(void)
{
	git_worktree *wt;
	git_repository *repo;

	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));

	cl_git_pass(git_repository_open_from_worktree(&repo, wt));
	cl_assert_equal_s(git_repository_workdir(repo),
		git_repository_workdir(fixture.worktree));

	git_repository_free(repo);
	git_worktree_free(wt);
}

void test_worktree_worktree__open_invalid_commondir(void)
{
	git_worktree *wt;
	git_repository *repo;
146
	git_str buf = GIT_STR_INIT, path = GIT_STR_INIT;
147

148 149
	cl_git_pass(git_str_sets(&buf, "/path/to/nonexistent/commondir"));
	cl_git_pass(git_str_joinpath(&path,
150 151
	            fixture.repo->commondir,
	            "worktrees/testrepo-worktree/commondir"));
152 153 154 155 156
	cl_git_pass(git_futils_writebuffer(&buf, path.ptr, O_RDWR, 0644));

	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
	cl_git_fail(git_repository_open_from_worktree(&repo, wt));

157 158
	git_str_dispose(&buf);
	git_str_dispose(&path);
159 160 161 162 163 164 165
	git_worktree_free(wt);
}

void test_worktree_worktree__open_invalid_gitdir(void)
{
	git_worktree *wt;
	git_repository *repo;
166
	git_str buf = GIT_STR_INIT, path = GIT_STR_INIT;
167

168 169
	cl_git_pass(git_str_sets(&buf, "/path/to/nonexistent/gitdir"));
	cl_git_pass(git_str_joinpath(&path,
170 171
	            fixture.repo->commondir,
	            "worktrees/testrepo-worktree/gitdir"));
172 173 174 175 176
	cl_git_pass(git_futils_writebuffer(&buf, path.ptr, O_RDWR, 0644));

	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
	cl_git_fail(git_repository_open_from_worktree(&repo, wt));

177 178
	git_str_dispose(&buf);
	git_str_dispose(&path);
179 180 181 182 183 184 185
	git_worktree_free(wt);
}

void test_worktree_worktree__open_invalid_parent(void)
{
	git_worktree *wt;
	git_repository *repo;
186
	git_str buf = GIT_STR_INIT;
187

188
	cl_git_pass(git_str_sets(&buf, "/path/to/nonexistent/gitdir"));
189
	cl_git_pass(git_futils_writebuffer(&buf,
190
		    fixture.worktree->gitlink, O_RDWR, 0644));
191 192 193 194

	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
	cl_git_fail(git_repository_open_from_worktree(&repo, wt));

195
	git_str_dispose(&buf);
196 197
	git_worktree_free(wt);
}
198

199 200 201 202 203
void test_worktree_worktree__init(void)
{
	git_worktree *wt;
	git_repository *repo;
	git_reference *branch;
204
	git_str path = GIT_STR_INIT;
205

206
	cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-new"));
207
	cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-new", path.ptr, NULL));
208 209 210

	/* Open and verify created repo */
	cl_git_pass(git_repository_open(&repo, path.ptr));
211
	cl_assert(git__suffixcmp(git_repository_workdir(repo), "worktree-new/") == 0);
212 213
	cl_git_pass(git_branch_lookup(&branch, repo, "worktree-new", GIT_BRANCH_LOCAL));

214
	git_str_dispose(&path);
215 216 217 218 219
	git_worktree_free(wt);
	git_reference_free(branch);
	git_repository_free(repo);
}

220 221 222 223 224
void test_worktree_worktree__add_locked(void)
{
	git_worktree *wt;
	git_repository *repo;
	git_reference *branch;
225
	git_str path = GIT_STR_INIT;
226 227 228 229
	git_worktree_add_options opts = GIT_WORKTREE_ADD_OPTIONS_INIT;

	opts.lock = 1;

230
	cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-locked"));
231 232 233 234 235 236 237 238
	cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-locked", path.ptr, &opts));

	/* Open and verify created repo */
	cl_assert(git_worktree_is_locked(NULL, wt));
	cl_git_pass(git_repository_open(&repo, path.ptr));
	cl_assert(git__suffixcmp(git_repository_workdir(repo), "worktree-locked/") == 0);
	cl_git_pass(git_branch_lookup(&branch, repo, "worktree-locked", GIT_BRANCH_LOCAL));

239
	git_str_dispose(&path);
240 241 242 243 244
	git_worktree_free(wt);
	git_reference_free(branch);
	git_repository_free(repo);
}

245 246 247 248 249
void test_worktree_worktree__init_existing_branch(void)
{
	git_reference *head, *branch;
	git_commit *commit;
	git_worktree *wt;
250
	git_str path = GIT_STR_INIT;
251 252 253 254 255

	cl_git_pass(git_repository_head(&head, fixture.repo));
	cl_git_pass(git_commit_lookup(&commit, fixture.repo, &head->target.oid));
	cl_git_pass(git_branch_create(&branch, fixture.repo, "worktree-new", commit, false));

256
	cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-new"));
257
	cl_git_fail(git_worktree_add(&wt, fixture.repo, "worktree-new", path.ptr, NULL));
258

259
	git_str_dispose(&path);
260 261 262 263 264
	git_commit_free(commit);
	git_reference_free(head);
	git_reference_free(branch);
}

265 266 267 268 269 270
void test_worktree_worktree__add_with_explicit_branch(void)
{
	git_reference *head, *branch, *wthead;
	git_commit *commit;
	git_worktree *wt;
	git_repository *wtrepo;
271
	git_str path = GIT_STR_INIT;
272 273 274 275 276 277 278 279
	git_worktree_add_options opts = GIT_WORKTREE_ADD_OPTIONS_INIT;

	cl_git_pass(git_repository_head(&head, fixture.repo));
	cl_git_pass(git_commit_lookup(&commit, fixture.repo, &head->target.oid));
	cl_git_pass(git_branch_create(&branch, fixture.repo, "worktree-with-ref", commit, false));

	opts.ref = branch;

280
	cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-with-different-name"));
281 282 283 284 285
	cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-with-different-name", path.ptr, &opts));
	cl_git_pass(git_repository_open_from_worktree(&wtrepo, wt));
	cl_git_pass(git_repository_head(&wthead, wtrepo));
	cl_assert_equal_s(git_reference_name(wthead), "refs/heads/worktree-with-ref");

286
	git_str_dispose(&path);
287 288 289 290 291
	git_commit_free(commit);
	git_reference_free(head);
	git_reference_free(branch);
	git_reference_free(wthead);
	git_repository_free(wtrepo);
292
	git_worktree_free(wt);
293 294
}

295 296 297 298 299
void test_worktree_worktree__add_no_checkout(void)
{
	git_worktree *wt;
	git_repository *wtrepo;
	git_index *index;
300
	git_str path = GIT_STR_INIT;
301 302
	git_worktree_add_options opts = GIT_WORKTREE_ADD_OPTIONS_INIT;

303
	opts.checkout_options.checkout_strategy = GIT_CHECKOUT_NONE;
304

305
	cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-no-checkout"));
306 307 308 309 310 311
	cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-no-checkout", path.ptr, &opts));

	cl_git_pass(git_repository_open(&wtrepo, path.ptr));
	cl_git_pass(git_repository_index(&index, wtrepo));
	cl_assert_equal_i(git_index_entrycount(index), 0);

312
	git_str_dispose(&path);
313
	git_worktree_free(wt);
314
	git_index_free(index);
315 316
	git_repository_free(wtrepo);
}
317

318 319 320
void test_worktree_worktree__init_existing_worktree(void)
{
	git_worktree *wt;
321
	git_str path = GIT_STR_INIT;
322

323
	cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-new"));
324
	cl_git_fail(git_worktree_add(&wt, fixture.repo, "testrepo-worktree", path.ptr, NULL));
325 326

	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
327
	cl_assert_equal_s(wt->gitlink_path, fixture.worktree->gitlink);
328

329
	git_str_dispose(&path);
330 331 332 333 334 335 336
	git_worktree_free(wt);
}

void test_worktree_worktree__init_existing_path(void)
{
	const char *wtfiles[] = { "HEAD", "commondir", "gitdir", "index" };
	git_worktree *wt;
337
	git_str path = GIT_STR_INIT;
338 339 340 341 342
	unsigned i;

	/* Delete files to verify they have not been created by
	 * the init call */
	for (i = 0; i < ARRAY_SIZE(wtfiles); i++) {
343
		cl_git_pass(git_str_joinpath(&path,
344
			    fixture.worktree->gitdir, wtfiles[i]));
345 346 347
		cl_git_pass(p_unlink(path.ptr));
	}

348
	cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../testrepo-worktree"));
349
	cl_git_fail(git_worktree_add(&wt, fixture.repo, "worktree-new", path.ptr, NULL));
350 351 352

	/* Verify files have not been re-created */
	for (i = 0; i < ARRAY_SIZE(wtfiles); i++) {
353
		cl_git_pass(git_str_joinpath(&path,
354
			    fixture.worktree->gitdir, wtfiles[i]));
355
		cl_assert(!git_fs_path_exists(path.ptr));
356 357
	}

358
	git_str_dispose(&path);
359 360
}

361 362 363 364
void test_worktree_worktree__init_submodule(void)
{
	git_repository *repo, *sm, *wt;
	git_worktree *worktree;
365
	git_str path = GIT_STR_INIT;
366 367 368 369

	cleanup_fixture_worktree(&fixture);
	repo = setup_fixture_submod2();

370
	cl_git_pass(git_str_joinpath(&path, repo->workdir, "sm_unchanged"));
371
	cl_git_pass(git_repository_open(&sm, path.ptr));
372
	cl_git_pass(git_str_joinpath(&path, repo->workdir, "../worktree/"));
373
	cl_git_pass(git_worktree_add(&worktree, sm, "repo-worktree", path.ptr, NULL));
374 375
	cl_git_pass(git_repository_open_from_worktree(&wt, worktree));

376
	cl_git_pass(git_fs_path_prettify_dir(&path, path.ptr, NULL));
377
	cl_assert_equal_s(path.ptr, wt->workdir);
378
	cl_git_pass(git_fs_path_prettify_dir(&path, sm->commondir, NULL));
379 380
	cl_assert_equal_s(sm->commondir, wt->commondir);

381
	cl_git_pass(git_str_joinpath(&path, sm->gitdir, "worktrees/repo-worktree/"));
382 383
	cl_assert_equal_s(path.ptr, wt->gitdir);

384
	git_str_dispose(&path);
385 386 387 388 389
	git_worktree_free(worktree);
	git_repository_free(sm);
	git_repository_free(wt);
}

390 391 392 393 394 395 396 397 398 399
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);
}

400 401 402 403 404 405
void test_worktree_worktree__name(void)
{
	git_worktree *wt;

	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
	cl_assert_equal_s(git_worktree_name(wt), "testrepo-worktree");
406

407 408 409 410 411 412
	git_worktree_free(wt);
}

void test_worktree_worktree__path(void)
{
	git_worktree *wt;
413
	git_str expected_path = GIT_STR_INIT;
414

415
	cl_git_pass(git_str_joinpath(&expected_path, clar_sandbox_path(), "testrepo-worktree"));
416 417
	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
	cl_assert_equal_s(git_worktree_path(wt), expected_path.ptr);
418

419
	git_str_dispose(&expected_path);
420 421 422
	git_worktree_free(wt);
}

423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
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);
}
462 463 464 465 466 467 468 469 470 471 472 473 474 475

void test_worktree_worktree__lock_with_reason(void)
{
	git_worktree *wt;
	git_buf reason = GIT_BUF_INIT;

	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));

	cl_assert(!git_worktree_is_locked(NULL, wt));
	cl_git_pass(git_worktree_lock(wt, "because"));
	cl_assert(git_worktree_is_locked(&reason, wt) > 0);
	cl_assert_equal_s(reason.ptr, "because");
	cl_assert(wt->locked);

476
	git_buf_dispose(&reason);
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
	git_worktree_free(wt);
}

void test_worktree_worktree__lock_without_reason(void)
{
	git_worktree *wt;
	git_buf reason = GIT_BUF_INIT;

	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));

	cl_assert(!git_worktree_is_locked(NULL, wt));
	cl_git_pass(git_worktree_lock(wt, NULL));
	cl_assert(git_worktree_is_locked(&reason, wt) > 0);
	cl_assert_equal_i(reason.size, 0);
	cl_assert(wt->locked);

493
	git_buf_dispose(&reason);
494 495 496 497 498 499 500 501 502
	git_worktree_free(wt);
}

void test_worktree_worktree__unlock_unlocked_worktree(void)
{
	git_worktree *wt;

	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
	cl_assert(!git_worktree_is_locked(NULL, wt));
503
	cl_assert_equal_i(1, git_worktree_unlock(wt));
504 505 506 507 508 509 510 511 512 513 514 515
	cl_assert(!wt->locked);

	git_worktree_free(wt);
}

void test_worktree_worktree__unlock_locked_worktree(void)
{
	git_worktree *wt;

	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
	cl_git_pass(git_worktree_lock(wt, NULL));
	cl_assert(git_worktree_is_locked(NULL, wt));
516
	cl_assert_equal_i(0, git_worktree_unlock(wt));
517 518 519 520
	cl_assert(!wt->locked);

	git_worktree_free(wt);
}
521

522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
void test_worktree_worktree__prune_without_opts_fails(void)
{
	git_worktree *wt;
	git_repository *repo;

	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
	cl_git_fail(git_worktree_prune(wt, NULL));

	/* Assert the repository is still valid */
	cl_git_pass(git_repository_open_from_worktree(&repo, wt));

	git_worktree_free(wt);
	git_repository_free(repo);
}

537 538
void test_worktree_worktree__prune_valid(void)
{
539
	git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
540 541 542
	git_worktree *wt;
	git_repository *repo;

543 544
	opts.flags = GIT_WORKTREE_PRUNE_VALID;

545
	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
546
	cl_git_pass(git_worktree_prune(wt, &opts));
547 548 549 550 551 552 553 554 555 556

	/* 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)
{
557
	git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
558 559 560 561 562 563
	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));

564 565
	opts.flags = GIT_WORKTREE_PRUNE_VALID;
	cl_git_fail(git_worktree_prune(wt, &opts));
566 567 568
	/* Assert the repository is still valid */
	cl_git_pass(git_repository_open_from_worktree(&repo, wt));

569 570 571
	opts.flags = GIT_WORKTREE_PRUNE_VALID|GIT_WORKTREE_PRUNE_LOCKED;
	cl_git_pass(git_worktree_prune(wt, &opts));

572 573 574 575
	git_worktree_free(wt);
	git_repository_free(repo);
}

576
void test_worktree_worktree__prune_gitdir_only(void)
577
{
578
	git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
579 580
	git_worktree *wt;

581
	opts.flags = GIT_WORKTREE_PRUNE_VALID;
582
	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
583
	cl_git_pass(git_worktree_prune(wt, &opts));
584

585 586
	cl_assert(!git_fs_path_exists(wt->gitdir_path));
	cl_assert(git_fs_path_exists(wt->gitlink_path));
587 588 589 590

	git_worktree_free(wt);
}

591
void test_worktree_worktree__prune_worktree(void)
592
{
593
	git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
594 595
	git_worktree *wt;

596 597
	opts.flags = GIT_WORKTREE_PRUNE_VALID|GIT_WORKTREE_PRUNE_WORKING_TREE;

598
	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
599
	cl_git_pass(git_worktree_prune(wt, &opts));
600

601 602
	cl_assert(!git_fs_path_exists(wt->gitdir_path));
	cl_assert(!git_fs_path_exists(wt->gitlink_path));
603 604 605

	git_worktree_free(wt);
}
606

607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
static int foreach_worktree_cb(git_repository *worktree, void *payload)
{
	int *counter = (int *)payload;

	switch (*counter) {
	case 0:
		cl_assert_equal_s(git_repository_path(fixture.repo),
				  git_repository_path(worktree));
		cl_assert(!git_repository_is_worktree(worktree));
		break;
	case 1:
		cl_assert_equal_s(git_repository_path(fixture.worktree),
				  git_repository_path(worktree));
		cl_assert(git_repository_is_worktree(worktree));
		break;
	default:
		cl_fail("more worktrees found than expected");
	}

	(*counter)++;

	return 0;
}

void test_worktree_worktree__foreach_worktree_lists_all_worktrees(void)
{
	int counter = 0;
	cl_git_pass(git_repository_foreach_worktree(fixture.repo, foreach_worktree_cb, &counter));
}
636 637 638 639 640 641

void test_worktree_worktree__validate_invalid_worktreedir(void)
{
	git_worktree *wt;

	cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
642
	p_rename("testrepo-worktree", "testrepo-worktree-tmp");
643
	cl_git_fail(git_worktree_validate(wt));
644
	p_rename("testrepo-worktree-tmp", "testrepo-worktree");
645 646 647

	git_worktree_free(wt);
}