]> git.proxmox.com Git - libgit2.git/blob - tests/worktree/worktree.c
New upstream version 1.3.0+dfsg.1
[libgit2.git] / tests / worktree / worktree.c
1 #include "clar_libgit2.h"
2 #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 #define COMMON_REPO "testrepo"
10 #define WORKTREE_REPO "testrepo-worktree"
11
12 static worktree_fixture fixture =
13 WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO);
14
15 void test_worktree_worktree__initialize(void)
16 {
17 setup_fixture_worktree(&fixture);
18 }
19
20 void test_worktree_worktree__cleanup(void)
21 {
22 cleanup_fixture_worktree(&fixture);
23 }
24
25 void test_worktree_worktree__list(void)
26 {
27 git_strarray wts;
28
29 cl_git_pass(git_worktree_list(&wts, fixture.repo));
30 cl_assert_equal_i(wts.count, 1);
31 cl_assert_equal_s(wts.strings[0], "testrepo-worktree");
32
33 git_strarray_dispose(&wts);
34 }
35
36 void test_worktree_worktree__list_with_invalid_worktree_dirs(void)
37 {
38 const char *filesets[3][2] = {
39 { "gitdir", "commondir" },
40 { "gitdir", "HEAD" },
41 { "HEAD", "commondir" },
42 };
43 git_buf path = GIT_BUF_INIT;
44 git_strarray wts;
45 size_t i, j, len;
46
47 cl_git_pass(git_buf_joinpath(&path,
48 fixture.repo->commondir,
49 "worktrees/invalid"));
50 cl_git_pass(p_mkdir(path.ptr, 0755));
51
52 len = path.size;
53
54 for (i = 0; i < ARRAY_SIZE(filesets); i++) {
55
56 for (j = 0; j < ARRAY_SIZE(filesets[i]); j++) {
57 git_buf_truncate(&path, len);
58 cl_git_pass(git_buf_joinpath(&path, path.ptr, filesets[i][j]));
59 cl_git_pass(p_close(p_creat(path.ptr, 0644)));
60 }
61
62 cl_git_pass(git_worktree_list(&wts, fixture.worktree));
63 cl_assert_equal_i(wts.count, 1);
64 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 git_buf_truncate(&path, len);
69 cl_git_pass(git_buf_joinpath(&path, path.ptr, filesets[i][j]));
70 p_unlink(path.ptr);
71 }
72 }
73
74 git_buf_dispose(&path);
75 }
76
77 void test_worktree_worktree__list_in_worktree_repo(void)
78 {
79 git_strarray wts;
80
81 cl_git_pass(git_worktree_list(&wts, fixture.worktree));
82 cl_assert_equal_i(wts.count, 1);
83 cl_assert_equal_s(wts.strings[0], "testrepo-worktree");
84
85 git_strarray_dispose(&wts);
86 }
87
88 void test_worktree_worktree__list_without_worktrees(void)
89 {
90 git_repository *repo;
91 git_strarray wts;
92
93 repo = cl_git_sandbox_init("testrepo2");
94 cl_git_pass(git_worktree_list(&wts, repo));
95 cl_assert_equal_i(wts.count, 0);
96
97 git_repository_free(repo);
98 }
99
100 void test_worktree_worktree__lookup(void)
101 {
102 git_worktree *wt;
103 git_buf gitdir_path = GIT_BUF_INIT;
104
105 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
106
107 cl_git_pass(git_buf_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 cl_assert_equal_s(wt->commondir_path, fixture.repo->commondir);
114
115 git_buf_dispose(&gitdir_path);
116 git_worktree_free(wt);
117 }
118
119 void test_worktree_worktree__lookup_nonexistent_worktree(void)
120 {
121 git_worktree *wt;
122
123 cl_git_fail(git_worktree_lookup(&wt, fixture.repo, "nonexistent"));
124 cl_assert_equal_p(wt, NULL);
125 }
126
127 void test_worktree_worktree__open(void)
128 {
129 git_worktree *wt;
130 git_repository *repo;
131
132 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
133
134 cl_git_pass(git_repository_open_from_worktree(&repo, wt));
135 cl_assert_equal_s(git_repository_workdir(repo),
136 git_repository_workdir(fixture.worktree));
137
138 git_repository_free(repo);
139 git_worktree_free(wt);
140 }
141
142 void test_worktree_worktree__open_invalid_commondir(void)
143 {
144 git_worktree *wt;
145 git_repository *repo;
146 git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
147
148 cl_git_pass(git_buf_sets(&buf, "/path/to/nonexistent/commondir"));
149 cl_git_pass(git_buf_joinpath(&path,
150 fixture.repo->commondir,
151 "worktrees/testrepo-worktree/commondir"));
152 cl_git_pass(git_futils_writebuffer(&buf, path.ptr, O_RDWR, 0644));
153
154 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
155 cl_git_fail(git_repository_open_from_worktree(&repo, wt));
156
157 git_buf_dispose(&buf);
158 git_buf_dispose(&path);
159 git_worktree_free(wt);
160 }
161
162 void test_worktree_worktree__open_invalid_gitdir(void)
163 {
164 git_worktree *wt;
165 git_repository *repo;
166 git_buf buf = GIT_BUF_INIT, path = GIT_BUF_INIT;
167
168 cl_git_pass(git_buf_sets(&buf, "/path/to/nonexistent/gitdir"));
169 cl_git_pass(git_buf_joinpath(&path,
170 fixture.repo->commondir,
171 "worktrees/testrepo-worktree/gitdir"));
172 cl_git_pass(git_futils_writebuffer(&buf, path.ptr, O_RDWR, 0644));
173
174 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
175 cl_git_fail(git_repository_open_from_worktree(&repo, wt));
176
177 git_buf_dispose(&buf);
178 git_buf_dispose(&path);
179 git_worktree_free(wt);
180 }
181
182 void test_worktree_worktree__open_invalid_parent(void)
183 {
184 git_worktree *wt;
185 git_repository *repo;
186 git_buf buf = GIT_BUF_INIT;
187
188 cl_git_pass(git_buf_sets(&buf, "/path/to/nonexistent/gitdir"));
189 cl_git_pass(git_futils_writebuffer(&buf,
190 fixture.worktree->gitlink, O_RDWR, 0644));
191
192 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
193 cl_git_fail(git_repository_open_from_worktree(&repo, wt));
194
195 git_buf_dispose(&buf);
196 git_worktree_free(wt);
197 }
198
199 void test_worktree_worktree__init(void)
200 {
201 git_worktree *wt;
202 git_repository *repo;
203 git_reference *branch;
204 git_buf path = GIT_BUF_INIT;
205
206 cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-new"));
207 cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-new", path.ptr, NULL));
208
209 /* Open and verify created repo */
210 cl_git_pass(git_repository_open(&repo, path.ptr));
211 cl_assert(git__suffixcmp(git_repository_workdir(repo), "worktree-new/") == 0);
212 cl_git_pass(git_branch_lookup(&branch, repo, "worktree-new", GIT_BRANCH_LOCAL));
213
214 git_buf_dispose(&path);
215 git_worktree_free(wt);
216 git_reference_free(branch);
217 git_repository_free(repo);
218 }
219
220 void test_worktree_worktree__add_locked(void)
221 {
222 git_worktree *wt;
223 git_repository *repo;
224 git_reference *branch;
225 git_buf path = GIT_BUF_INIT;
226 git_worktree_add_options opts = GIT_WORKTREE_ADD_OPTIONS_INIT;
227
228 opts.lock = 1;
229
230 cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-locked"));
231 cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-locked", path.ptr, &opts));
232
233 /* Open and verify created repo */
234 cl_assert(git_worktree_is_locked(NULL, wt));
235 cl_git_pass(git_repository_open(&repo, path.ptr));
236 cl_assert(git__suffixcmp(git_repository_workdir(repo), "worktree-locked/") == 0);
237 cl_git_pass(git_branch_lookup(&branch, repo, "worktree-locked", GIT_BRANCH_LOCAL));
238
239 git_buf_dispose(&path);
240 git_worktree_free(wt);
241 git_reference_free(branch);
242 git_repository_free(repo);
243 }
244
245 void test_worktree_worktree__init_existing_branch(void)
246 {
247 git_reference *head, *branch;
248 git_commit *commit;
249 git_worktree *wt;
250 git_buf path = GIT_BUF_INIT;
251
252 cl_git_pass(git_repository_head(&head, fixture.repo));
253 cl_git_pass(git_commit_lookup(&commit, fixture.repo, &head->target.oid));
254 cl_git_pass(git_branch_create(&branch, fixture.repo, "worktree-new", commit, false));
255
256 cl_git_pass(git_buf_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_buf_dispose(&path);
260 git_commit_free(commit);
261 git_reference_free(head);
262 git_reference_free(branch);
263 }
264
265 void test_worktree_worktree__add_with_explicit_branch(void)
266 {
267 git_reference *head, *branch, *wthead;
268 git_commit *commit;
269 git_worktree *wt;
270 git_repository *wtrepo;
271 git_buf path = GIT_BUF_INIT;
272 git_worktree_add_options opts = GIT_WORKTREE_ADD_OPTIONS_INIT;
273
274 cl_git_pass(git_repository_head(&head, fixture.repo));
275 cl_git_pass(git_commit_lookup(&commit, fixture.repo, &head->target.oid));
276 cl_git_pass(git_branch_create(&branch, fixture.repo, "worktree-with-ref", commit, false));
277
278 opts.ref = branch;
279
280 cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-with-different-name"));
281 cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-with-different-name", path.ptr, &opts));
282 cl_git_pass(git_repository_open_from_worktree(&wtrepo, wt));
283 cl_git_pass(git_repository_head(&wthead, wtrepo));
284 cl_assert_equal_s(git_reference_name(wthead), "refs/heads/worktree-with-ref");
285
286 git_buf_dispose(&path);
287 git_commit_free(commit);
288 git_reference_free(head);
289 git_reference_free(branch);
290 git_reference_free(wthead);
291 git_repository_free(wtrepo);
292 git_worktree_free(wt);
293 }
294
295
296 void test_worktree_worktree__init_existing_worktree(void)
297 {
298 git_worktree *wt;
299 git_buf path = GIT_BUF_INIT;
300
301 cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../worktree-new"));
302 cl_git_fail(git_worktree_add(&wt, fixture.repo, "testrepo-worktree", path.ptr, NULL));
303
304 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
305 cl_assert_equal_s(wt->gitlink_path, fixture.worktree->gitlink);
306
307 git_buf_dispose(&path);
308 git_worktree_free(wt);
309 }
310
311 void test_worktree_worktree__init_existing_path(void)
312 {
313 const char *wtfiles[] = { "HEAD", "commondir", "gitdir", "index" };
314 git_worktree *wt;
315 git_buf path = GIT_BUF_INIT;
316 unsigned i;
317
318 /* Delete files to verify they have not been created by
319 * the init call */
320 for (i = 0; i < ARRAY_SIZE(wtfiles); i++) {
321 cl_git_pass(git_buf_joinpath(&path,
322 fixture.worktree->gitdir, wtfiles[i]));
323 cl_git_pass(p_unlink(path.ptr));
324 }
325
326 cl_git_pass(git_buf_joinpath(&path, fixture.repo->workdir, "../testrepo-worktree"));
327 cl_git_fail(git_worktree_add(&wt, fixture.repo, "worktree-new", path.ptr, NULL));
328
329 /* Verify files have not been re-created */
330 for (i = 0; i < ARRAY_SIZE(wtfiles); i++) {
331 cl_git_pass(git_buf_joinpath(&path,
332 fixture.worktree->gitdir, wtfiles[i]));
333 cl_assert(!git_path_exists(path.ptr));
334 }
335
336 git_buf_dispose(&path);
337 }
338
339 void test_worktree_worktree__init_submodule(void)
340 {
341 git_repository *repo, *sm, *wt;
342 git_worktree *worktree;
343 git_buf path = GIT_BUF_INIT;
344
345 cleanup_fixture_worktree(&fixture);
346 repo = setup_fixture_submod2();
347
348 cl_git_pass(git_buf_joinpath(&path, repo->workdir, "sm_unchanged"));
349 cl_git_pass(git_repository_open(&sm, path.ptr));
350 cl_git_pass(git_buf_joinpath(&path, repo->workdir, "../worktree/"));
351 cl_git_pass(git_worktree_add(&worktree, sm, "repo-worktree", path.ptr, NULL));
352 cl_git_pass(git_repository_open_from_worktree(&wt, worktree));
353
354 cl_git_pass(git_path_prettify_dir(&path, path.ptr, NULL));
355 cl_assert_equal_s(path.ptr, wt->workdir);
356 cl_git_pass(git_path_prettify_dir(&path, sm->commondir, NULL));
357 cl_assert_equal_s(sm->commondir, wt->commondir);
358
359 cl_git_pass(git_buf_joinpath(&path, sm->gitdir, "worktrees/repo-worktree/"));
360 cl_assert_equal_s(path.ptr, wt->gitdir);
361
362 git_buf_dispose(&path);
363 git_worktree_free(worktree);
364 git_repository_free(sm);
365 git_repository_free(wt);
366 }
367
368 void test_worktree_worktree__validate(void)
369 {
370 git_worktree *wt;
371
372 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
373 cl_git_pass(git_worktree_validate(wt));
374
375 git_worktree_free(wt);
376 }
377
378 void test_worktree_worktree__name(void)
379 {
380 git_worktree *wt;
381
382 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
383 cl_assert_equal_s(git_worktree_name(wt), "testrepo-worktree");
384
385 git_worktree_free(wt);
386 }
387
388 void test_worktree_worktree__path(void)
389 {
390 git_worktree *wt;
391 git_buf expected_path = GIT_BUF_INIT;
392
393 cl_git_pass(git_buf_joinpath(&expected_path, clar_sandbox_path(), "testrepo-worktree"));
394 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
395 cl_assert_equal_s(git_worktree_path(wt), expected_path.ptr);
396
397 git_buf_dispose(&expected_path);
398 git_worktree_free(wt);
399 }
400
401 void test_worktree_worktree__validate_invalid_commondir(void)
402 {
403 git_worktree *wt;
404
405 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
406 git__free(wt->commondir_path);
407 wt->commondir_path = "/path/to/invalid/commondir";
408
409 cl_git_fail(git_worktree_validate(wt));
410
411 wt->commondir_path = NULL;
412 git_worktree_free(wt);
413 }
414
415 void test_worktree_worktree__validate_invalid_gitdir(void)
416 {
417 git_worktree *wt;
418
419 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
420 git__free(wt->gitdir_path);
421 wt->gitdir_path = "/path/to/invalid/gitdir";
422 cl_git_fail(git_worktree_validate(wt));
423
424 wt->gitdir_path = NULL;
425 git_worktree_free(wt);
426 }
427
428 void test_worktree_worktree__validate_invalid_parent(void)
429 {
430 git_worktree *wt;
431
432 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
433 git__free(wt->parent_path);
434 wt->parent_path = "/path/to/invalid/parent";
435 cl_git_fail(git_worktree_validate(wt));
436
437 wt->parent_path = NULL;
438 git_worktree_free(wt);
439 }
440
441 void test_worktree_worktree__lock_with_reason(void)
442 {
443 git_worktree *wt;
444 git_buf reason = GIT_BUF_INIT;
445
446 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
447
448 cl_assert(!git_worktree_is_locked(NULL, wt));
449 cl_git_pass(git_worktree_lock(wt, "because"));
450 cl_assert(git_worktree_is_locked(&reason, wt) > 0);
451 cl_assert_equal_s(reason.ptr, "because");
452 cl_assert(wt->locked);
453
454 git_buf_dispose(&reason);
455 git_worktree_free(wt);
456 }
457
458 void test_worktree_worktree__lock_without_reason(void)
459 {
460 git_worktree *wt;
461 git_buf reason = GIT_BUF_INIT;
462
463 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
464
465 cl_assert(!git_worktree_is_locked(NULL, wt));
466 cl_git_pass(git_worktree_lock(wt, NULL));
467 cl_assert(git_worktree_is_locked(&reason, wt) > 0);
468 cl_assert_equal_i(reason.size, 0);
469 cl_assert(wt->locked);
470
471 git_buf_dispose(&reason);
472 git_worktree_free(wt);
473 }
474
475 void test_worktree_worktree__unlock_unlocked_worktree(void)
476 {
477 git_worktree *wt;
478
479 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
480 cl_assert(!git_worktree_is_locked(NULL, wt));
481 cl_assert_equal_i(1, git_worktree_unlock(wt));
482 cl_assert(!wt->locked);
483
484 git_worktree_free(wt);
485 }
486
487 void test_worktree_worktree__unlock_locked_worktree(void)
488 {
489 git_worktree *wt;
490
491 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
492 cl_git_pass(git_worktree_lock(wt, NULL));
493 cl_assert(git_worktree_is_locked(NULL, wt));
494 cl_assert_equal_i(0, git_worktree_unlock(wt));
495 cl_assert(!wt->locked);
496
497 git_worktree_free(wt);
498 }
499
500 void test_worktree_worktree__prune_without_opts_fails(void)
501 {
502 git_worktree *wt;
503 git_repository *repo;
504
505 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
506 cl_git_fail(git_worktree_prune(wt, NULL));
507
508 /* Assert the repository is still valid */
509 cl_git_pass(git_repository_open_from_worktree(&repo, wt));
510
511 git_worktree_free(wt);
512 git_repository_free(repo);
513 }
514
515 void test_worktree_worktree__prune_valid(void)
516 {
517 git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
518 git_worktree *wt;
519 git_repository *repo;
520
521 opts.flags = GIT_WORKTREE_PRUNE_VALID;
522
523 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
524 cl_git_pass(git_worktree_prune(wt, &opts));
525
526 /* Assert the repository is not valid anymore */
527 cl_git_fail(git_repository_open_from_worktree(&repo, wt));
528
529 git_worktree_free(wt);
530 git_repository_free(repo);
531 }
532
533 void test_worktree_worktree__prune_locked(void)
534 {
535 git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
536 git_worktree *wt;
537 git_repository *repo;
538
539 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
540 cl_git_pass(git_worktree_lock(wt, NULL));
541
542 opts.flags = GIT_WORKTREE_PRUNE_VALID;
543 cl_git_fail(git_worktree_prune(wt, &opts));
544 /* Assert the repository is still valid */
545 cl_git_pass(git_repository_open_from_worktree(&repo, wt));
546
547 opts.flags = GIT_WORKTREE_PRUNE_VALID|GIT_WORKTREE_PRUNE_LOCKED;
548 cl_git_pass(git_worktree_prune(wt, &opts));
549
550 git_worktree_free(wt);
551 git_repository_free(repo);
552 }
553
554 void test_worktree_worktree__prune_gitdir_only(void)
555 {
556 git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
557 git_worktree *wt;
558
559 opts.flags = GIT_WORKTREE_PRUNE_VALID;
560 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
561 cl_git_pass(git_worktree_prune(wt, &opts));
562
563 cl_assert(!git_path_exists(wt->gitdir_path));
564 cl_assert(git_path_exists(wt->gitlink_path));
565
566 git_worktree_free(wt);
567 }
568
569 void test_worktree_worktree__prune_worktree(void)
570 {
571 git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
572 git_worktree *wt;
573
574 opts.flags = GIT_WORKTREE_PRUNE_VALID|GIT_WORKTREE_PRUNE_WORKING_TREE;
575
576 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
577 cl_git_pass(git_worktree_prune(wt, &opts));
578
579 cl_assert(!git_path_exists(wt->gitdir_path));
580 cl_assert(!git_path_exists(wt->gitlink_path));
581
582 git_worktree_free(wt);
583 }
584
585 static int foreach_worktree_cb(git_repository *worktree, void *payload)
586 {
587 int *counter = (int *)payload;
588
589 switch (*counter) {
590 case 0:
591 cl_assert_equal_s(git_repository_path(fixture.repo),
592 git_repository_path(worktree));
593 cl_assert(!git_repository_is_worktree(worktree));
594 break;
595 case 1:
596 cl_assert_equal_s(git_repository_path(fixture.worktree),
597 git_repository_path(worktree));
598 cl_assert(git_repository_is_worktree(worktree));
599 break;
600 default:
601 cl_fail("more worktrees found than expected");
602 }
603
604 (*counter)++;
605
606 return 0;
607 }
608
609 void test_worktree_worktree__foreach_worktree_lists_all_worktrees(void)
610 {
611 int counter = 0;
612 cl_git_pass(git_repository_foreach_worktree(fixture.repo, foreach_worktree_cb, &counter));
613 }
614
615 void test_worktree_worktree__validate_invalid_worktreedir(void)
616 {
617 git_worktree *wt;
618
619 cl_git_pass(git_worktree_lookup(&wt, fixture.repo, "testrepo-worktree"));
620 p_rename("testrepo-worktree", "testrepo-worktree-tmp");
621 cl_git_fail(git_worktree_validate(wt));
622 p_rename("testrepo-worktree-tmp", "testrepo-worktree");
623
624 git_worktree_free(wt);
625 }