Skip to content

Commit 6e95a02

Browse files
authored
Merge pull request #1008 from bart-jaskulski/master
Fix retrieving git worktree path
2 parents d846988 + 21b9a55 commit 6e95a02

File tree

2 files changed

+51
-5
lines changed

2 files changed

+51
-5
lines changed

src/Locator/GitRepositoryDirLocator.php

+44-2
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,55 @@ public function locate(string $gitDir): string
3535

3636
$gitRepositoryDir = $matches[1];
3737

38-
if ($this->filesystem->isAbsolutePath($gitRepositoryDir)) {
39-
return $gitRepositoryDir;
38+
if ($this->isWorktree($gitRepositoryDir)) {
39+
return $this->locateWorktreeRoot($gitRepositoryDir);
4040
}
4141

4242
return $this->filesystem->buildPath(
4343
dirname($gitDir),
4444
$gitRepositoryDir
4545
);
4646
}
47+
48+
/**
49+
* If a given path (from gitdir value) is absolute and there is a commondir file, it is
50+
* a worktree.
51+
*/
52+
private function isWorktree(string $gitDir): bool
53+
{
54+
return $this->filesystem->isAbsolutePath($gitDir)
55+
&& $this->filesystem->isFile($gitDir.DIRECTORY_SEPARATOR.'commondir');
56+
}
57+
58+
/**
59+
* Retreiving repository dir for worktree nominally returns path to the configured worktree,
60+
* which does not hold hooks. We need to resolve the actual repository root.
61+
*
62+
* Example directory structure:
63+
* ```
64+
* /project
65+
* .git/
66+
* .git/hooks/
67+
* .git/worktrees/
68+
* worktree1
69+
* commondir: relative path to /project/.git
70+
* /worktree1
71+
* .git: file with path to /project/.git/worktrees/worktree1
72+
* ```
73+
*/
74+
private function locateWorktreeRoot(string $gitRepositoryDir): string
75+
{
76+
$worktreeRelativeRoot = trim(
77+
$this->filesystem->readPath(
78+
$gitRepositoryDir.DIRECTORY_SEPARATOR.'commondir'
79+
)
80+
);
81+
82+
return $this->filesystem->realpath(
83+
$this->filesystem->makePathAbsolute(
84+
$worktreeRelativeRoot,
85+
$gitRepositoryDir
86+
)
87+
);
88+
}
4789
}

test/Unit/Locator/GitRepositoryDirLocatorTest.php

+7-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ protected function setUp(): void
3131

3232
$this->filesystem = new Filesystem();
3333
$this->locator = new GitRepositoryDirLocator($this->filesystem);
34-
$this->gitDir = $this->workspace . DIRECTORY_SEPARATOR . '.git';
34+
$this->gitDir = $this->workspace . DIRECTORY_SEPARATOR . '.git';
3535
}
3636

3737
/**
@@ -69,7 +69,11 @@ public function it_can_passthrough_git_dir_path_if_file_is_not_parseable(): void
6969
*/
7070
public function it_can_locate_git_dir_in_workspaces(): void
7171
{
72-
$this->filesystem->dumpFile($this->gitDir, 'gitdir: /dev/null');
73-
$this->assertEquals('/dev/null', $this->locator->locate($this->gitDir));
72+
$ourWorktreeProject = $this->workspace.'/project1/';
73+
$worktreeGitRoot = $this->gitDir.'/worktrees/worktree1/';
74+
mkdir($worktreeGitRoot, 0777, true);
75+
$this->filesystem->dumpFile($worktreeGitRoot.'/commondir', '../..');
76+
$this->filesystem->dumpFile($ourWorktreeProject.'/.git', 'gitdir: '.$this->gitDir.'/worktrees/worktree1');
77+
$this->assertEquals($this->gitDir, $this->locator->locate($this->gitDir));
7478
}
7579
}

0 commit comments

Comments
 (0)