-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6140181
commit f2c0432
Showing
3 changed files
with
241 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
<?php | ||
|
||
/** | ||
* This file is part of CaptainHook | ||
* | ||
* (c) Sebastian Feldmann <sf@sebastian-feldmann.info> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace CaptainHook\HookInstaller; | ||
|
||
use RuntimeException; | ||
|
||
/** | ||
* DotGit | ||
* | ||
* @package CaptainHook | ||
* @author Sebastian Feldmann <sf@sebastian-feldmann.info> | ||
* @link https://github.com/captainhookphp/captainhook | ||
* @since Class available since Release 0.9.4 | ||
*/ | ||
class DotGit | ||
{ | ||
/** | ||
* Path to the .git file or directory | ||
* | ||
* @var string | ||
*/ | ||
private string $dotGit = ''; | ||
|
||
/** | ||
* Path to the real .git directory | ||
* | ||
* @var string | ||
*/ | ||
private string $gitDir = ''; | ||
|
||
/** | ||
* Is just an additional worktree | ||
* | ||
* @var bool | ||
*/ | ||
private bool $isAdditionalWorktree = false; | ||
|
||
/** | ||
* Constructor | ||
* | ||
* @param string $pathToDotGit | ||
* @throws \RuntimeException | ||
*/ | ||
private function __construct(string $pathToDotGit) | ||
{ | ||
// default repository with a .git directory | ||
if (is_dir($pathToDotGit)) { | ||
$this->gitDir = $pathToDotGit; | ||
return; | ||
} | ||
// additional worktree with a .git file referencing the original .git directory | ||
if (is_file($pathToDotGit)) { | ||
$dotGitContent = file_get_contents($pathToDotGit); | ||
$match = []; | ||
preg_match('#^gitdir: (?<gitdir>.*\.git)#', $dotGitContent, $match); | ||
$dir = $match['gitdir'] ?? ''; | ||
if (is_dir($dir)) { | ||
$this->gitDir = $dir; | ||
$this->isAdditionalWorktree = true; | ||
return; | ||
} | ||
} | ||
throw new RuntimeException('invalid .git path'); | ||
} | ||
|
||
/** | ||
* Returns the path to the .git file or directory | ||
* | ||
* @return string | ||
*/ | ||
public function path(): string | ||
{ | ||
return $this->dotGit; | ||
} | ||
|
||
/** | ||
* Always returns the path .git repository directory | ||
* | ||
* @return string | ||
*/ | ||
public function gitDirectory(): string | ||
{ | ||
return $this->gitDir; | ||
} | ||
|
||
/** | ||
* Returns true if the .git file indicated that we are in an additional worktree | ||
* | ||
* @return bool | ||
*/ | ||
public function isAdditionalWorktree(): bool | ||
{ | ||
return $this->isAdditionalWorktree; | ||
} | ||
|
||
/** | ||
* Looks for a .git file or directory from a given path in all parent directories | ||
* | ||
* @param string $path | ||
* @return \CaptainHook\HookInstaller\DotGit | ||
* @throws \RuntimeException | ||
*/ | ||
public static function searchInPath(string $path): DotGit | ||
{ | ||
while (file_exists($path)) { | ||
$dotGitPath = $path . '/.git'; | ||
if (file_exists($dotGitPath)) { | ||
return new self($dotGitPath); | ||
} | ||
// if we checked the root directory already, break to prevent endless loop | ||
if ($path === dirname($path)) { | ||
break; | ||
} | ||
$path = dirname($path); | ||
} | ||
throw new RuntimeException('git directory not found'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
<?php | ||
|
||
/** | ||
* This file is part of CaptainHook | ||
* | ||
* (c) Sebastian Feldmann <sf@sebastian-feldmann.info> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace CaptainHook\HookInstaller; | ||
|
||
use Composer\IO\IOInterface; | ||
use RuntimeException; | ||
|
||
class Installer | ||
{ | ||
/** | ||
* Path to CaptainHook phar file | ||
* | ||
* @var string | ||
*/ | ||
private string $executable; | ||
|
||
/** | ||
* Path to the CaptainHook configuration file | ||
* | ||
* @var string | ||
*/ | ||
private string $configuration; | ||
|
||
/** | ||
* Path to the .git directory | ||
* | ||
* @var string | ||
*/ | ||
private string $gitDirectory; | ||
|
||
/** | ||
* Captain constructor | ||
* | ||
* @param string $executable | ||
* @param string $configuration | ||
* @param string $gitDirectory | ||
*/ | ||
public function __construct(string $executable, string $configuration, string $gitDirectory) | ||
{ | ||
$this->executable = $executable; | ||
$this->configuration = $configuration; | ||
$this->gitDirectory = $gitDirectory; | ||
} | ||
|
||
/** | ||
* Install the hooks by executing the Cap'n | ||
* | ||
* @param \Composer\IO\IOInterface $io | ||
* @param bool $force | ||
* @return void | ||
*/ | ||
public function install(IOInterface $io, bool $force): void | ||
{ | ||
// Respect composer CLI settings | ||
$ansi = $io->isDecorated() ? ' --ansi' : ' --no-ansi'; | ||
$executable = escapeshellarg($this->executable); | ||
|
||
// captainhook config and repository settings | ||
$configuration = ' -c ' . escapeshellarg($this->configuration); | ||
$repository = ' -g ' . escapeshellarg($this->gitDirectory); | ||
$forceOrSkip = $force ? ' -f' : ' -s'; | ||
|
||
// sub process settings | ||
$cmd = PHP_BINARY . ' ' . $executable . ' install' | ||
. $ansi . ' --no-interaction' . $forceOrSkip | ||
. $configuration . $repository; | ||
$pipes = []; | ||
$spec = [ | ||
0 => ['file', 'php://stdin', 'r'], | ||
1 => ['file', 'php://stdout', 'w'], | ||
2 => ['file', 'php://stderr', 'w'], | ||
]; | ||
|
||
$process = @proc_open($cmd, $spec, $pipes); | ||
|
||
if (!is_resource($process)) { | ||
throw new RuntimeException('no-process'); | ||
} | ||
|
||
// Loop on process until it exits | ||
do { | ||
$status = proc_get_status($process); | ||
} while ($status && $status['running']); | ||
$exitCode = $status['exitcode'] ?? -1; | ||
proc_close($process); | ||
if ($exitCode !== 0) { | ||
throw new RuntimeException('installation process failed'); | ||
} | ||
} | ||
} |