Skip to content

Commit e1b064d

Browse files
Check for broken symlinks
Fixes issue #272
1 parent 39162eb commit e1b064d

File tree

3 files changed

+89
-0
lines changed

3 files changed

+89
-0
lines changed

src/Runner/Installer.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ private function writeHookFile(string $hook): void
238238
if ($doIt) {
239239
$code = $this->getHookSourceCode($hook);
240240
$file = new File($hookFile);
241+
$this->checkForBrokenSymlink($file);
241242
$file->write($code);
242243
chmod($hookFile, 0755);
243244
$this->io->write(IOUtil::PREFIX_OK . ' <comment>' . $hook . '</comment> installed');
@@ -256,4 +257,23 @@ private function getHookSourceCode(string $hook): string
256257
{
257258
return $this->template->getCode($hook);
258259
}
260+
261+
/**
262+
* Checks if the provided file is a broken symbolic link
263+
*
264+
* @param File $file The File object representing the file.
265+
* @return void
266+
* @throws RuntimeException If the file is determined to be a broken symbolic link.
267+
*/
268+
protected function checkForBrokenSymlink(File $file): void
269+
{
270+
if ($file->isLink()) {
271+
if (!is_dir(dirname($file->linkTarget()))) {
272+
throw new RuntimeException(
273+
'The hook at \'' . $file->getPath() . '\' is a broken symbolic link. ' . PHP_EOL .
274+
'Please remove the symbolic link and try again.'
275+
);
276+
}
277+
}
278+
}
259279
}

tests/unit/Runner/FakeInstaller.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/**
4+
* This file is part of CaptainHook.
5+
*
6+
* (c) Sebastian Feldmann <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace CaptainHook\App\Runner;
13+
14+
use CaptainHook\App\Storage\File;
15+
16+
class FakeInstaller extends Installer
17+
{
18+
public function checkSymlink(File $file): void
19+
{
20+
$this->checkForBrokenSymlink($file);
21+
}
22+
}

tests/unit/Runner/InstallerTest.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
namespace CaptainHook\App\Runner;
1313

1414
use CaptainHook\App\Config\Mockery as ConfigMockery;
15+
use CaptainHook\App\Console\IO\DefaultIO;
1516
use CaptainHook\App\Console\IO\Mockery as IOMockery;
1617
use CaptainHook\App\Exception\InvalidHookName;
1718
use CaptainHook\App\Git\DummyRepo;
1819
use CaptainHook\App\Hook\Mockery as HookMockery;
1920
use CaptainHook\App\Mockery as CHMockery;
21+
use CaptainHook\App\Storage\File;
2022
use Exception;
2123
use org\bovigo\vfs\vfsStream;
2224
use PHPUnit\Framework\TestCase;
@@ -171,6 +173,51 @@ public function testWriteHook(): void
171173
$this->assertFileExists($fakeRepo->getHookDir() . '/pre-commit');
172174
}
173175

176+
/**
177+
* Tests Installer::checkForBrokenSymlinks
178+
*/
179+
public function testBrokenSymlinkDetectionOnExistingFile(): void
180+
{
181+
$io = $this->createIOMock();
182+
$config = $this->createConfigMock();
183+
$repo = $this->createRepositoryMock();
184+
$template = $this->createTemplateMock();
185+
186+
$file = $this->getMockBuilder(File::class)
187+
->disableOriginalConstructor()
188+
->getMock();
189+
190+
$runner = new FakeInstaller($io, $config, $repo, $template);
191+
$file->method('isLink')->willReturn(true);
192+
$file->method('linkTarget')->willReturn(__FILE__);
193+
194+
$runner->checkSymlink($file);
195+
$this->assertTrue(true);
196+
}
197+
198+
/**
199+
* Tests Installer::checkForBrokenSymlinks
200+
*/
201+
public function testBrokenSymlinkDetectionOnBrokenSymlink(): void
202+
{
203+
$this->expectException(Exception::class);
204+
205+
$io = $this->createIOMock();
206+
$config = $this->createConfigMock();
207+
$repo = $this->createRepositoryMock();
208+
$template = $this->createTemplateMock();
209+
210+
$file = $this->getMockBuilder(File::class)
211+
->disableOriginalConstructor()
212+
->getMock();
213+
214+
$runner = new FakeInstaller($io, $config, $repo, $template);
215+
$file->method('isLink')->willReturn(true);
216+
$file->method('linkTarget')->willReturn('./foo/bar/baz');
217+
218+
$runner->checkSymlink($file);
219+
}
220+
174221
/**
175222
* Tests Installer::run
176223
*/

0 commit comments

Comments
 (0)