Skip to content

Commit caca564

Browse files
committed
Merge branch 'cw/worktree-relative' into seen
An extra worktree attached to a repository points at each other to allow finding the repository from the worktree and vice versa possible. Turn this linkage to relative paths. * cw/worktree-relative: worktree: add test for path handling in linked worktrees worktree: link worktrees with relative paths worktree: refactor infer_backlink() to use *strbuf
2 parents 92da836 + 08830ac commit caca564

File tree

6 files changed

+265
-74
lines changed

6 files changed

+265
-74
lines changed

builtin/worktree.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,8 @@ static int add_worktree(const char *path, const char *refname,
414414
const struct add_opts *opts)
415415
{
416416
struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;
417-
struct strbuf sb = STRBUF_INIT, realpath = STRBUF_INIT;
417+
struct strbuf sb = STRBUF_INIT, sb_tmp = STRBUF_INIT;
418+
struct strbuf sb_path_realpath = STRBUF_INIT, sb_repo_realpath = STRBUF_INIT;
418419
const char *name;
419420
struct strvec child_env = STRVEC_INIT;
420421
unsigned int counter = 0;
@@ -490,11 +491,10 @@ static int add_worktree(const char *path, const char *refname,
490491

491492
strbuf_reset(&sb);
492493
strbuf_addf(&sb, "%s/gitdir", sb_repo.buf);
493-
strbuf_realpath(&realpath, sb_git.buf, 1);
494-
write_file(sb.buf, "%s", realpath.buf);
495-
strbuf_realpath(&realpath, repo_get_common_dir(the_repository), 1);
496-
write_file(sb_git.buf, "gitdir: %s/worktrees/%s",
497-
realpath.buf, name);
494+
strbuf_realpath(&sb_path_realpath, path, 1);
495+
strbuf_realpath(&sb_repo_realpath, sb_repo.buf, 1);
496+
write_file(sb.buf, "%s/.git", relative_path(sb_path_realpath.buf, sb_repo_realpath.buf, &sb_tmp));
497+
write_file(sb_git.buf, "gitdir: %s", relative_path(sb_repo_realpath.buf, sb_path_realpath.buf, &sb_tmp));
498498
strbuf_reset(&sb);
499499
strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
500500
write_file(sb.buf, "../..");
@@ -578,11 +578,13 @@ static int add_worktree(const char *path, const char *refname,
578578

579579
strvec_clear(&child_env);
580580
strbuf_release(&sb);
581+
strbuf_release(&sb_tmp);
581582
strbuf_release(&symref);
582583
strbuf_release(&sb_repo);
584+
strbuf_release(&sb_repo_realpath);
583585
strbuf_release(&sb_git);
586+
strbuf_release(&sb_path_realpath);
584587
strbuf_release(&sb_name);
585-
strbuf_release(&realpath);
586588
free_worktree(wt);
587589
return ret;
588590
}

setup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2420,7 +2420,7 @@ static void separate_git_dir(const char *git_dir, const char *git_link)
24202420

24212421
if (rename(src, git_dir))
24222422
die_errno(_("unable to move %s to %s"), src, git_dir);
2423-
repair_worktrees(NULL, NULL);
2423+
repair_worktrees_after_gitdir_move(src);
24242424
}
24252425

24262426
write_file(git_link, "gitdir: %s", git_dir);

t/t2401-worktree-prune.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,23 @@ test_expect_success 'prune duplicate (main/linked)' '
120120
! test -d .git/worktrees/wt
121121
'
122122

123+
test_expect_success 'not prune proper worktrees when run inside linked worktree' '
124+
test_when_finished rm -rf repo wt_ext &&
125+
git init repo &&
126+
(
127+
cd repo &&
128+
echo content >file &&
129+
git add file &&
130+
git commit -m msg &&
131+
git worktree add ../wt_ext &&
132+
git worktree add wt_int &&
133+
cd wt_int &&
134+
git worktree prune -v >out &&
135+
test_must_be_empty out &&
136+
cd ../../wt_ext &&
137+
git worktree prune -v >out &&
138+
test_must_be_empty out
139+
)
140+
'
141+
123142
test_done

t/t2408-worktree-relative.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/sh
2+
3+
test_description='test worktrees linked with relative paths'
4+
5+
TEST_PASSES_SANITIZE_LEAK=true
6+
. ./test-lib.sh
7+
8+
test_expect_success 'links worktrees with relative paths' '
9+
test_when_finished rm -rf repo &&
10+
git init repo &&
11+
(
12+
cd repo &&
13+
test_commit initial &&
14+
git worktree add wt1 &&
15+
echo "../../../wt1/.git" >expected_gitdir &&
16+
cat .git/worktrees/wt1/gitdir >actual_gitdir &&
17+
echo "gitdir: ../.git/worktrees/wt1" >expected_git &&
18+
cat wt1/.git >actual_git &&
19+
test_cmp expected_gitdir actual_gitdir &&
20+
test_cmp expected_git actual_git
21+
)
22+
'
23+
24+
test_expect_success 'move repo without breaking relative internal links' '
25+
test_when_finished rm -rf repo moved &&
26+
git init repo &&
27+
(
28+
cd repo &&
29+
test_commit initial &&
30+
git worktree add wt1 &&
31+
cd .. &&
32+
mv repo moved &&
33+
cd moved/wt1 &&
34+
git status >out 2>err &&
35+
test_must_be_empty err
36+
)
37+
'
38+
39+
test_done

0 commit comments

Comments
 (0)