Skip to content

Commit

Permalink
Merge pull request #13 from fr3nch13/dev
Browse files Browse the repository at this point in the history
Fix for issue with finding the application root.
  • Loading branch information
fr3nch13 committed Jun 17, 2023
2 parents 126a09e + 4819bc6 commit 408cb84
Show file tree
Hide file tree
Showing 7 changed files with 598 additions and 411 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
- name: Composer install
run: |
composer config github-oauth.github.com ${{ secrets.ACTIONS_TOKEN }}
composer install
composer update
- name: Run PHP CodeSniffer
run: composer run-script cs-checkstyle | vendor/bin/cs2pr
Expand Down Expand Up @@ -64,7 +64,7 @@ jobs:
- name: Composer install
run: |
composer config github-oauth.github.com ${{ secrets.ACTIONS_TOKEN }}
composer install
composer update
- name: Run PHP Analyzer
run: composer run-script phpstan
Expand Down Expand Up @@ -93,7 +93,7 @@ jobs:
- name: Composer install
run: |
composer config github-oauth.github.com ${{ secrets.ACTIONS_TOKEN }}
composer install
composer update
- name: Run PHPUnit
run: composer run-script test
Expand Down Expand Up @@ -122,7 +122,7 @@ jobs:
- name: Composer install
run: |
composer config github-oauth.github.com ${{ secrets.ACTIONS_TOKEN }}
composer install
composer update
- name: Run PHPUnit
run: composer run-script coverage-clover
Expand Down
12 changes: 8 additions & 4 deletions src/Command/PackagesCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOption
$parser->addOption('path', [
'short' => 'p',
'help' => __('The directory where the composer.lock file is located.'),
'default' => getenv('LOCK_DIR') ? getenv('LOCK_DIR') : getenv('ROOT'),
'default' => getenv('LOCK_DIR') ?: (getenv('ROOT') ?: ROOT),
]);
$parser->addOption('command', [
'short' => 'c',
Expand Down Expand Up @@ -79,15 +79,15 @@ public static function getDescription(): string
*/
public function execute(Arguments $args, ConsoleIo $io): int
{
$path = getenv('LOCK_DIR') ? getenv('LOCK_DIR') : getenv('ROOT');
$path = getenv('LOCK_DIR') ?: (getenv('ROOT') ?: ROOT);
if ($args->getOption('path')) {
$path = $args->getOption('path');
}
$this->View = new View();
$config = ['rootDir' => $path];
if ($args->getOption('verbose')) {
$io->verbose(__("Using path:\t{0}", [$path]));
$io->verbose(__("Using command:\t{0}", [$args->getOption('command')]));
$io->verbose(__("Initially Using path:\t{0}", [$path]));
$io->verbose(__("Initially Using command:\t{0}", [$args->getOption('command')]));
$io->hr();
}
try {
Expand All @@ -98,6 +98,10 @@ public function execute(Arguments $args, ConsoleIo $io): int
$e->getMessage(),
]));
}
if ($args->getOption('verbose')) {
$io->verbose(__("Using derived path:\t{0}", [$this->Versions->getRootDir()]));
$io->hr();
}
// see which command to run.
switch ($args->getOption('command')) {
case 'all':
Expand Down
153 changes: 116 additions & 37 deletions src/View/Helper/VersionsHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Cake\View\View;
use ComposerLockParser\ComposerInfo;
use ComposerLockParser\PackagesCollection;
use Fr3nch13\Utilities\Exception\UtilitiesException;

/**
* Versions Helper
Expand Down Expand Up @@ -55,60 +56,84 @@ class VersionsHelper extends Helper
*/
protected $gitCmd = null;

/**
* The root directory of the application
*
* @var string
*/
public $rootDir = '';

/**
* Initialize the helper
*
* @param \Cake\View\View $View The view object
* @param array<string, mixed> $config Helper config settings
* @return void
* @throws \Exception when we can't find some of the commands.
* @TODO Use more specific exceptions
* @throws \Fr3nch13\Utilities\Exception\UtilitiesException when we can't find some of the commands.
*/
public function __construct(View $View, array $config = [])
{
parent::__construct($View, $config);
// get the git command
$output = [];
$result_code = 0;
if (isset($config['git'])) {
$this->gitCmd = $config['git'];
} else {
try {
exec('which git', $output);
} catch (\Throwable $e) {
throw new \Exception(__('Unable to find the `which` command.'));
}
if (isset($output[0])) {
$this->gitCmd = $output[0];
$this->exec('which git', $output, $result_code);
if ($result_code) {
throw new UtilitiesException(__('Unable to find the `which` command. Result: {0}', [
implode(' ', $output),
]), 404);
} else {
throw new \Exception(__('Unable to find the `git` command.'));
if (isset($output[0])) {
$this->gitCmd = $output[0];
} else {
throw new UtilitiesException(__('Unable to find the `git` command.'), 404);
}
}
}
// use an environment vairable if set like in config/.env
// otherwise use the constant ROOT from the source application
$rootDir = getenv('LOCK_DIR') ? getenv('LOCK_DIR') : (getenv('ROOT') ?: ROOT);
$this->rootDir = getenv('LOCK_DIR') ?: (getenv('ROOT') ?: ROOT);
if (isset($config['rootDir'])) {
$rootDir = $config['rootDir'];
$this->rootDir = $config['rootDir'];
}
$this->composerPath = $rootDir . DS . 'composer.lock';

$this->composerPath = $this->getRootDir() . DS . 'composer.lock';
if (isset($config['composerPath'])) {
$this->composerPath = $config['composerPath'];
}

if (!is_file($this->composerPath)) {
throw new \Exception(__('Unable to find the composer.lock file at: {0}', [
throw new UtilitiesException(__('Unable to find the composer.lock file at: {0}', [
$this->composerPath,
]));
]), 404);
}
try {
$this->ComposerInfo = new ComposerInfo($this->composerPath);
$this->ComposerInfo->getPackages();
} catch (\Throwable $e) {
throw new \Exception(__('Unable to parse the composer.lock file at: {0}', [
throw new UtilitiesException(__('Unable to parse the composer.lock file at: {0} Msg: {1}', [
$this->composerPath,
]));
$e->getMessage(),
]), 500, $e);
}
}

/**
* Here so I can mock it mainly.
*
* @param string $command The external command to run.
* @param array<int, string> $output The full output of the command, each line an entry in an array
* @param int $result_code The exit code of the command
* @return false|string The last line of the output, or false if the command failed.
*/
protected function exec(string $command, &$output = [], &$result_code = 0)
{
return \exec($command, $output, $result_code);
}

/**
* Gets the version of this app using git
*
Expand Down Expand Up @@ -139,7 +164,8 @@ public function app(): ?string
if (isset($results[0])) {
$out = $results[0];
}
} catch (\Exception $e) {
} catch (UtilitiesException $e) {
// Don't throw an exception, just return the output of the command.
}
}

Expand All @@ -151,17 +177,17 @@ public function app(): ?string
*
* @param string $name The full name of the composer package ex: fr3nch13/utilities
* @return object the object that has the info of that package
* @throws \Exception throws an exception if the package info can't be found.
* @throws \Fr3nch13\Utilities\Exception\UtilitiesException throws an exception if the package info can't be found.
* @TODO Use more specific exceptions
*/
public function package(string $name): object
{
try {
return $this->ComposerInfo->getPackages()->getByName($name);
} catch (\Throwable $e) {
throw new \Exception(__('Unable to find info on {0}.', [
throw new UtilitiesException(__('Unable to find info on {0}.', [
$name,
]));
]), 404, $e);
}
}

Expand Down Expand Up @@ -209,36 +235,89 @@ public function getTypes(): array
return $types;
}

/**
* Gets the root path of the application.
* Also verifies that it's correct each time this function is ran.
*
* @return string The path to the root folder
* @throws \Fr3nch13\Utilities\Exception\UtilitiesException If we can't find cakephp as this means nothing is installed yet.
*/
public function getRootDir(): string
{
$findRoot = function ($root): string {
$verifier = DS . implode(DS, [
'vendor',
'cakephp',
'cakephp',
]);

if (is_dir($root . $verifier)) {
/** @var string $path */
$path = realpath($root);

return $path;
}

do {
$lastRoot = $root;
$root = dirname($root);
if (is_dir($root . $verifier)) {
/** @var string $path */
$path = realpath($root);

return $path;
}
} while ($root !== $lastRoot);

throw new UtilitiesException(
__('Cannot find the root of the application, unable to get versions.'),
404
);
};

// not set, so see if we can figure out where we are.
if (!$this->rootDir) {
$path = realpath(getcwd() ?: '.');
if (is_string($path)) {
$this->rootDir = $path;
}
}

// Validate the root path
$this->rootDir = $findRoot($this->rootDir);

return $this->rootDir;
}

/**
* Runs the git command with the args
*
* @param array<string> $args List of arguments to pass to the git command
* @return array<int, string> The result of the git command
* @throws \Exception if the git command fails.
* @TODO Use more specific exceptions
* @throws \Fr3nch13\Utilities\Exception\UtilitiesException if the git command fails.
*/
public function runGit(array $args = []): array
{
$cmd = $this->gitCmd . ' ' . implode(' ', $args);
$output = [];
try {
exec($cmd, $output, $result_code);
} catch (\Throwable $e) {
throw new \Exception(__('Unable to find the `which` command.'));
if (!trim($this->gitCmd)) {
throw new UtilitiesException(__('Empty git command.'), 404);
}
$cmd = 'cd ' . $this->getRootDir() . '; ';
$cmd .= $this->gitCmd . ' ' . implode(' ', $args);
$cmd .= ' 2>&1';
$output = [];
// removed the try/catch since I added the 'cd [root]' above,
// which will never make the $cmd emprty, so the exec() will never throw a ValueError.
$last_line = $this->exec($cmd, $output, $result_code);

if ($result_code) {
/** @var string $msg */
$msg = json_encode([
'message' => 'Command failed',
'cmd' => '{0}',
'code' => '{1}',
'output' => '{2}',
'cmd' => $cmd,
'code' => $result_code,
'output' => implode(' ', $output) . ' ' . $last_line,
]);
throw new \Exception(__($msg, [
$cmd,
$result_code,
implode("\n", $output),
]));
throw new UtilitiesException($msg, $result_code);
}
// trim the results
foreach ($output as $i => $value) {
Expand Down
2 changes: 1 addition & 1 deletion tests/TestCase/Command/PackagesCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ public function testOptionBadPath(): void
{
$this->exec('packages -p /does/not/exist');
$this->assertExitCode(\Cake\Command\Command::CODE_ERROR);
$this->assertErrorContains('There was an error when running `all`. Error: `Unable to find the composer.lock file at: /does/not/exist/composer.lock`');
$this->assertErrorContains('There was an error when running `all`. Error: `Cannot find the root of the application, unable to get versions.`');
}

/**
Expand Down

0 comments on commit 408cb84

Please sign in to comment.