Skip to content

Commit 35dad0e

Browse files
author
Matthieu CODRON
committed
add --only-enabled option to installer
1 parent 32b5738 commit 35dad0e

File tree

7 files changed

+247
-4
lines changed

7 files changed

+247
-4
lines changed

src/Console/Command/Install.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ protected function configure(): void
5050
'You can specify multiple hooks with comma as delimiter. ' .
5151
'By default all hooks get installed.'
5252
)
53+
->addOption(
54+
'only-enabled',
55+
null,
56+
InputOption::VALUE_NONE,
57+
'Limit the hooks you want to install to those enabled in your conf. By default all hooks get installed.'
58+
)
5359
->addOption(
5460
'force',
5561
'f',
@@ -122,6 +128,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
122128
$installer->setForce(IOUtil::argToBool($input->getOption('force')))
123129
->setSkipExisting(IOUtil::argToBool($input->getOption('skip-existing')))
124130
->setMoveExistingTo(IOUtil::argToString($input->getOption('move-existing-to')))
131+
->setOnlyEnabled(IOUtil::argToBool($input->getOption('only-enabled')))
125132
->setHook(IOUtil::argToString($input->getArgument('hook')))
126133
->run();
127134

src/Runner/Installer.php

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

5959
/**
60-
* Hooks that should be handled.
60+
* Install only enabled hooks
61+
*
62+
* @var bool
63+
*/
64+
private $onlyEnabled = false;
65+
66+
/**
6167
*
6268
* @var array<int, string>
6369
*/
@@ -129,6 +135,20 @@ public function setMoveExistingTo(string $backup): Installer
129135
return $this;
130136
}
131137

138+
/**
139+
* @param bool $onlyEnabled
140+
* @return \CaptainHook\App\Runner\Installer
141+
*/
142+
public function setOnlyEnabled(bool $onlyEnabled): Installer
143+
{
144+
if ($onlyEnabled && !empty($this->hooksToHandle)) {
145+
throw new RuntimeException('choose --only-enabled or specific hooks');
146+
}
147+
148+
$this->onlyEnabled = $onlyEnabled;
149+
return $this;
150+
}
151+
132152
/**
133153
* Hook setter
134154
*
@@ -142,6 +162,10 @@ public function setHook(string $hook): Installer
142162
return $this;
143163
}
144164

165+
if ($this->onlyEnabled) {
166+
throw new RuntimeException('choose --only-enabled or specific hooks');
167+
}
168+
145169
/** @var array<string> $hooks */
146170
$hooks = explode(',', $hook);
147171
$hooks = array_map('trim', $hooks);
@@ -189,9 +213,18 @@ public function getHooksToInstall(): array
189213
// to make sure the user will be asked to confirm every hook installation
190214
// unless the user provided the force or skip option
191215
// if specific hooks are set, the use has actively chosen it, so don't ask for permission anymore
192-
return empty($this->hooksToHandle)
193-
? array_map(fn ($hook) => true, Hooks::nativeHooks())
194-
: array_map(fn ($hook) => false, array_flip($this->hooksToHandle));
216+
if (!empty($this->hooksToHandle)) {
217+
return array_map(fn($hook) => false, array_flip($this->hooksToHandle));
218+
}
219+
$hooks = Hooks::nativeHooks();
220+
if($this->onlyEnabled) {
221+
$hooks = array_filter(
222+
$hooks,
223+
fn($hook) => $this->config->isHookEnabled($hook),
224+
ARRAY_FILTER_USE_KEY
225+
);
226+
}
227+
return array_map(fn($hook) => true, $hooks);
195228
}
196229

197230
/**
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"post-change": {
3+
"enabled": true,
4+
"actions": []
5+
},
6+
"post-merge": {
7+
"enabled": false,
8+
"actions": []
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"post-change": {
3+
"enabled": true,
4+
"actions": []
5+
},
6+
"post-merge": {
7+
"enabled": true,
8+
"actions": []
9+
}
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"post-change": {
3+
"enabled": true,
4+
"actions": []
5+
},
6+
"pre-commit": {
7+
"enabled": true,
8+
"actions": []
9+
}
10+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"post-change": {
3+
"enabled": true,
4+
"actions": []
5+
}
6+
}

tests/unit/Console/Command/InstallTest.php

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,4 +209,171 @@ public function testInstallMultipleHooksWithMultipleWrong(): void
209209
$install = new Install(new Resolver(CH_PATH_FILES . '/bin/captainhook'));
210210
$install->run($input, $output);
211211
}
212+
213+
/**
214+
* Tests Install::run
215+
*
216+
* @throws \Exception
217+
*/
218+
public function testInstallOnlyEnabled(): void
219+
{
220+
$repo = new DummyRepo();
221+
$output = new NullOutput();
222+
$input = new ArrayInput(
223+
[
224+
'--only-enabled' => true,
225+
'--force' => true,
226+
'--configuration' => CH_PATH_FILES . '/template/captainhook.json',
227+
'--git-directory' => $repo->getGitDir()
228+
]
229+
);
230+
231+
$install = new Install(new Resolver(CH_PATH_FILES . '/bin/captainhook'));
232+
$install->run($input, $output);
233+
234+
$this->assertTrue($repo->hookExists('prepare-commit-msg'));
235+
$this->assertTrue($repo->hookExists('commit-msg'));
236+
$this->assertTrue($repo->hookExists('pre-commit'));
237+
$this->assertFalse($repo->hookExists('pre-push'));
238+
$this->assertFalse($repo->hookExists('post-commit'));
239+
}
240+
241+
/**
242+
* Tests Install::run
243+
*
244+
* @throws \Exception
245+
*/
246+
public function testInstallOnlyEnabledOnlyVirtual(): void
247+
{
248+
$repo = new DummyRepo();
249+
$output = new NullOutput();
250+
$input = new ArrayInput(
251+
[
252+
'--only-enabled' => true,
253+
'--force' => true,
254+
'--configuration' => CH_PATH_FILES . '/template/captainhook-post-change.json',
255+
'--git-directory' => $repo->getGitDir()
256+
]
257+
);
258+
259+
$install = new Install(new Resolver(CH_PATH_FILES . '/bin/captainhook'));
260+
$install->run($input, $output);
261+
262+
$this->assertTrue($repo->hookExists('post-checkout'));
263+
$this->assertTrue($repo->hookExists('post-merge'));
264+
$this->assertTrue($repo->hookExists('post-rewrite'));
265+
$this->assertFalse($repo->hookExists('pre-commit'));
266+
$this->assertFalse($repo->hookExists('pre-push'));
267+
$this->assertFalse($repo->hookExists('post-commit'));
268+
}
269+
270+
/**
271+
* Tests Install::run
272+
*
273+
* @throws \Exception
274+
*/
275+
public function testInstallOnlyEnabledNotOnlyVirtual(): void
276+
{
277+
$repo = new DummyRepo();
278+
$output = new NullOutput();
279+
$input = new ArrayInput(
280+
[
281+
'--only-enabled' => true,
282+
'--force' => true,
283+
'--configuration' => CH_PATH_FILES . '/template/captainhook-post-change-pre-commit.json',
284+
'--git-directory' => $repo->getGitDir()
285+
]
286+
);
287+
288+
$install = new Install(new Resolver(CH_PATH_FILES . '/bin/captainhook'));
289+
$install->run($input, $output);
290+
291+
$this->assertTrue($repo->hookExists('post-checkout'));
292+
$this->assertTrue($repo->hookExists('post-merge'));
293+
$this->assertTrue($repo->hookExists('post-rewrite'));
294+
$this->assertTrue($repo->hookExists('pre-commit'));
295+
$this->assertFalse($repo->hookExists('pre-push'));
296+
$this->assertFalse($repo->hookExists('post-commit'));
297+
}
298+
299+
/**
300+
* Tests Install::run
301+
*
302+
* @throws \Exception
303+
*/
304+
public function testInstallOnlyEnabledNotOnlyVirtualOverlaps(): void
305+
{
306+
$repo = new DummyRepo();
307+
$output = new NullOutput();
308+
$input = new ArrayInput(
309+
[
310+
'--only-enabled' => true,
311+
'--force' => true,
312+
'--configuration' => CH_PATH_FILES . '/template/captainhook-post-change-post-merge.json',
313+
'--git-directory' => $repo->getGitDir()
314+
]
315+
);
316+
317+
$install = new Install(new Resolver(CH_PATH_FILES . '/bin/captainhook'));
318+
$install->run($input, $output);
319+
320+
$this->assertTrue($repo->hookExists('post-checkout'));
321+
$this->assertTrue($repo->hookExists('post-merge'));
322+
$this->assertTrue($repo->hookExists('post-rewrite'));
323+
$this->assertFalse($repo->hookExists('pre-commit'));
324+
$this->assertFalse($repo->hookExists('pre-push'));
325+
$this->assertFalse($repo->hookExists('post-commit'));
326+
}
327+
328+
/**
329+
* Tests Install::run
330+
*
331+
* @throws \Exception
332+
*/
333+
public function testInstallOnlyEnabledNotOnlyVirtualOverlapsDisabled(): void
334+
{
335+
$repo = new DummyRepo();
336+
$output = new NullOutput();
337+
$input = new ArrayInput(
338+
[
339+
'--only-enabled' => true,
340+
'--force' => true,
341+
'--configuration' => CH_PATH_FILES . '/template/captainhook-post-change-post-merge-disabled.json',
342+
'--git-directory' => $repo->getGitDir()
343+
]
344+
);
345+
346+
$install = new Install(new Resolver(CH_PATH_FILES . '/bin/captainhook'));
347+
$install->run($input, $output);
348+
349+
$this->assertTrue($repo->hookExists('post-checkout'));
350+
$this->assertTrue($repo->hookExists('post-merge'));
351+
$this->assertTrue($repo->hookExists('post-rewrite'));
352+
$this->assertFalse($repo->hookExists('pre-commit'));
353+
$this->assertFalse($repo->hookExists('pre-push'));
354+
$this->assertFalse($repo->hookExists('post-commit'));
355+
}
356+
357+
/**
358+
* Tests Install::run
359+
*
360+
* @throws \Exception
361+
*/
362+
public function testInstallOnlyEnabledAndHook(): void
363+
{
364+
$this->expectException(\RuntimeException::class);
365+
$repo = new DummyRepo();
366+
$output = new NullOutput();
367+
$input = new ArrayInput(
368+
[
369+
'hook' => 'pre-commit',
370+
'--only-enabled' => true,
371+
'--configuration' => CH_PATH_FILES . '/template/captainhook.json',
372+
'--git-directory' => $repo->getGitDir(),
373+
]
374+
);
375+
376+
$install = new Install(new Resolver(CH_PATH_FILES . '/bin/captainhook'));
377+
$install->run($input, $output);
378+
}
212379
}

0 commit comments

Comments
 (0)