Skip to content

Commit 0f0ad22

Browse files
Merge pull request #204 from alexandrmazur96
Allow specifying multiple hooks
2 parents 728fe38 + 2492e3c commit 0f0ad22

File tree

4 files changed

+165
-8
lines changed

4 files changed

+165
-8
lines changed

src/Console/Command/Install.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ protected function configure(): void
4646
->addArgument(
4747
'hook',
4848
InputArgument::OPTIONAL,
49-
'Limit the hook you want to install. By default all hooks get installed.'
49+
'Limit the hooks you want to install. ' .
50+
'You can specify multiple hooks with comma as delimiter. ' .
51+
'By default all hooks get installed.'
5052
)
5153
->addOption(
5254
'force',

src/Runner/Installer.php

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ class Installer extends RepositoryAware
5757
private $moveExistingTo = '';
5858

5959
/**
60-
* Hook that should be handled.
60+
* Hooks that should be handled.
6161
*
62-
* @var string
62+
* @var array<int, string>
6363
*/
64-
protected $hookToHandle;
64+
protected $hooksToHandle;
6565

6666
/**
6767
* Hook template
@@ -138,10 +138,29 @@ public function setMoveExistingTo(string $backup): Installer
138138
*/
139139
public function setHook(string $hook): Installer
140140
{
141-
if (!empty($hook) && !HookUtil::isInstallable($hook)) {
141+
if (empty($hook)) {
142+
return $this;
143+
}
144+
145+
/** @var array<int,string>|false $hooks */
146+
$hooks = explode(',', $hook);
147+
if ($hooks === false) {
142148
throw new Exception\InvalidHookName('Invalid hook name \'' . $hook . '\'');
143149
}
144-
$this->hookToHandle = $hook;
150+
151+
$hooks = array_map('trim', $hooks);
152+
153+
$hooksValidationCallback = static function (string $hook): bool {
154+
return !HookUtil::isInstallable($hook);
155+
};
156+
if (!empty(($invalidHooks = array_filter($hooks, $hooksValidationCallback)))) {
157+
throw new Exception\InvalidHookName(
158+
'Invalid hook name \'' . implode(',', $invalidHooks) . '\''
159+
);
160+
}
161+
162+
$this->hooksToHandle = $hooks;
163+
145164
return $this;
146165
}
147166

@@ -178,9 +197,11 @@ public function getHooksToInstall(): array
178197
return true;
179198
};
180199
// if a specific hook is set, the use has actively chosen it, so don't ask for permission anymore
181-
return empty($this->hookToHandle)
200+
return empty($this->hooksToHandle)
182201
? array_map($callback, Hooks::nativeHooks())
183-
: [$this->hookToHandle => false];
202+
: array_map(static function (): bool {
203+
return false;
204+
}, array_flip($this->hooksToHandle));
184205
}
185206

186207
/**

tests/unit/Console/Command/InstallTest.php

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,99 @@ public function testInstallPreCommitHook(): void
114114

115115
$this->assertTrue($repo->hookExists('pre-commit'));
116116
}
117+
118+
/**
119+
* Tests Install::run
120+
*
121+
* @throws \Exception
122+
*/
123+
public function testInstallMultipleHooks(): void
124+
{
125+
$repo = new DummyRepo();
126+
$output = new NullOutput();
127+
$input = new ArrayInput(
128+
[
129+
'hook' => 'pre-commit,pre-push,post-checkout',
130+
'--configuration' => CH_PATH_FILES . '/template/captainhook.json',
131+
'--git-directory' => $repo->getGitDir(),
132+
]
133+
);
134+
135+
$install = new Install(new Resolver(CH_PATH_FILES . '/bin/captainhook'));
136+
$install->run($input, $output);
137+
138+
$this->assertTrue($repo->hookExists('pre-commit'));
139+
$this->assertTrue($repo->hookExists('pre-push'));
140+
$this->assertTrue($repo->hookExists('post-checkout'));
141+
}
142+
143+
/**
144+
* Tests Install::run
145+
*
146+
* @throws \Exception
147+
*/
148+
public function testInstallMultipleHooksWithSpacesAfterAndBetweenSeparator(): void
149+
{
150+
$repo = new DummyRepo();
151+
$output = new NullOutput();
152+
$input = new ArrayInput(
153+
[
154+
'hook' => ' pre-commit , pre-push , post-checkout, post-commit',
155+
'--configuration' => CH_PATH_FILES . '/template/captainhook.json',
156+
'--git-directory' => $repo->getGitDir(),
157+
]
158+
);
159+
160+
$install = new Install(new Resolver(CH_PATH_FILES . '/bin/captainhook'));
161+
$install->run($input, $output);
162+
163+
$this->assertTrue($repo->hookExists('pre-commit'));
164+
$this->assertTrue($repo->hookExists('pre-push'));
165+
$this->assertTrue($repo->hookExists('post-checkout'));
166+
}
167+
168+
/**
169+
* Tests Install::run
170+
*
171+
* @throws \Exception
172+
*/
173+
public function testInstallMultipleHooksWithOneWrong(): void
174+
{
175+
$this->expectException(\CaptainHook\App\Exception\InvalidHookName::class);
176+
$repo = new DummyRepo();
177+
$output = new NullOutput();
178+
$input = new ArrayInput(
179+
[
180+
'hook' => 'pre-commit,pre-push,post-checkout,something-wrong',
181+
'--configuration' => CH_PATH_FILES . '/template/captainhook.json',
182+
'--git-directory' => $repo->getGitDir(),
183+
]
184+
);
185+
186+
$install = new Install(new Resolver(CH_PATH_FILES . '/bin/captainhook'));
187+
$install->run($input, $output);
188+
}
189+
190+
191+
/**
192+
* Tests Install::run
193+
*
194+
* @throws \Exception
195+
*/
196+
public function testInstallMultipleHooksWithMultipleWrong(): void
197+
{
198+
$this->expectException(\CaptainHook\App\Exception\InvalidHookName::class);
199+
$repo = new DummyRepo();
200+
$output = new NullOutput();
201+
$input = new ArrayInput(
202+
[
203+
'hook' => 'pre-commit,pre-push,post-checkout,something-wrong1,something-wrong2',
204+
'--configuration' => CH_PATH_FILES . '/template/captainhook.json',
205+
'--git-directory' => $repo->getGitDir(),
206+
]
207+
);
208+
209+
$install = new Install(new Resolver(CH_PATH_FILES . '/bin/captainhook'));
210+
$install->run($input, $output);
211+
}
117212
}

tests/unit/Runner/InstallerTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,24 @@ public function testSetInvalidHook(): void
4747
$runner->setHook('itDoNotExist');
4848
}
4949

50+
/**
51+
* Tests Installer::setHook
52+
*
53+
* @throws \CaptainHook\App\Exception\InvalidHookName
54+
*/
55+
public function testSetMultipleInvalidHooks(): void
56+
{
57+
$this->expectException(InvalidHookName::class);
58+
59+
$io = $this->createIOMock();
60+
$config = $this->createConfigMock();
61+
$repo = $this->createRepositoryMock();
62+
$template = $this->createTemplateMock();
63+
64+
$runner = new Installer($io, $config, $repo, $template);
65+
$runner->setHook('itDoNotExist1,itDoNotExist2,itDontExist3');
66+
}
67+
5068
/**
5169
* Tests Installer::setHook
5270
*
@@ -132,6 +150,27 @@ public function testWriteHook(): void
132150
$this->assertFileExists($fakeRepo->getHookDir() . '/pre-commit');
133151
}
134152

153+
/**
154+
* Tests Installer::run
155+
*/
156+
public function testWriteMultipleHooks(): void
157+
{
158+
$fakeRepo = new DummyRepo();
159+
160+
$io = $this->createIOMock();
161+
$config = $this->createConfigMock();
162+
$repo = $this->createRepositoryMock($fakeRepo->getRoot());
163+
$template = $this->createTemplateMock();
164+
165+
$runner = new Installer($io, $config, $repo, $template);
166+
$runner->setHook('pre-commit,pre-push,post-checkout');
167+
$runner->run();
168+
169+
$this->assertFileExists($fakeRepo->getHookDir() . '/pre-commit');
170+
$this->assertFileExists($fakeRepo->getHookDir() . '/pre-push');
171+
$this->assertFileExists($fakeRepo->getHookDir() . '/post-checkout');
172+
}
173+
135174
/**
136175
* Tests Installer::run
137176
*/

0 commit comments

Comments
 (0)