Skip to content

Commit 2db212a

Browse files
Improve containerized command detection
Instead of only looking for `docker exec` we check for multiple applications able to run Cap'n inside a container. Current candidates: - docker - docker-compose - podman - sail
1 parent 590d6f0 commit 2db212a

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

src/Hook/Template/Docker.php

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,11 @@ public function getCode(string $hook): string
107107
*/
108108
private function getOptimizeDockerCommand(string $hook): string
109109
{
110-
$command = $this->config->getRunConfig()->getDockerCommand();
111-
$position = strpos($command, 'docker exec');
112-
// add interactive and tty flags if docker exec is used
113-
if ($position !== false) {
114-
$endExec = $position + 11;
110+
$command = $this->config->getRunConfig()->getDockerCommand();
111+
$endExec = $this->endOfExecPositionInCommand($command);
112+
113+
// if the docker command can be identified, add env vars and tty flags
114+
if ($endExec !== -1) {
115115
$executable = substr($command, 0, $endExec);
116116
$options = substr($command, $endExec);
117117

@@ -228,4 +228,30 @@ private function resolveBinaryPath(): string
228228
// you have to use the 'run' 'path' config then
229229
return $this->pathInfo->getExecutablePath();
230230
}
231+
232+
/**
233+
* Look for the docker exec position in the command
234+
*
235+
* The position is necessary to optimize the interactive and env variable settings.
236+
* Returns -1 if nothing can be detected.
237+
*
238+
* This detection works with:
239+
* - docker
240+
* - docker-compose
241+
* - podman
242+
* - sail
243+
*
244+
* @param string $command
245+
* @return int
246+
*/
247+
private function endOfExecPositionInCommand(string $command): int
248+
{
249+
// find the exec command to extract the options later on and improve them
250+
$regex = '~(?:^|[\s;|&])(?:[\w./-]*/)?(docker|docker-compose|podman|sail)\s+exec\b~i';
251+
$matches = [];
252+
if (preg_match($regex, $command, $matches)) {
253+
return strlen($matches[0]);
254+
}
255+
return -1;
256+
}
231257
}

tests/unit/Hook/Template/DockerTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,28 @@ public function testDockerCommandOptimizationWithoutGitMapping(string $exec, str
105105
$this->assertStringContainsString('/usr/local/bin/captainhook', $code);
106106
}
107107

108+
public function testDoesNotOptimizeUnrecognizedCommands(): void
109+
{
110+
$pathInfo = $this->createMock(PathInfo::class);
111+
$pathInfo->method('getExecutablePath')->willReturn('./vendor/bin/captainhook');
112+
$pathInfo->method('getConfigPath')->willReturn('captainhook.json');
113+
114+
$configMock = $this->createConfigMock(false, 'captainhook.json');
115+
$runConfig = new Run([
116+
'mode' => 'docker',
117+
'exec' => 'custom-exec my-container',
118+
'path' => '/usr/local/bin/captainhook'
119+
]);
120+
$configMock->method('getBootstrap')->willReturn('');
121+
$configMock->method('getRunConfig')->willReturn($runConfig);
122+
123+
$template = new Docker($pathInfo, $configMock);
124+
$code = $template->getCode('prepare-commit-msg');
125+
126+
$this->assertStringContainsString('/usr/local/bin/captainhook', $code);
127+
$this->assertStringNotContainsString('GIT_INDEX_FILE', $code);
128+
}
129+
108130
public static function replacementPossibilitiesWithoutGitMapping(): array
109131
{
110132
return [

0 commit comments

Comments
 (0)