Skip to content

Commit

Permalink
Optimized error reporting (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tobias Kündig committed May 24, 2016
1 parent a5495c2 commit ddf8eb0
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 23 deletions.
70 changes: 61 additions & 9 deletions src/Console/InstallCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,21 @@ class InstallCommand extends Command
{
use UsesTemplate;

/**
* Exit code for processes
*/
const EXIT_CODE_OK = 0;

/**
* @var
*/
public $config;

/**
* @var OutputInterface
*/
protected $output;

/**
* Configure the command options.
*
Expand All @@ -51,16 +61,21 @@ protected function configure()
* @param InputInterface $input
* @param OutputInterface $output
*
* @throws RuntimeException
* @throws LogicException
* @return mixed
* @throws \Symfony\Component\Process\Exception\RuntimeException
* @throws \Symfony\Component\Process\Exception\InvalidArgumentException
* @throws LogicException
* @throws RuntimeException
* @throws InvalidArgumentException
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if ( ! class_exists('ZipArchive')) {
throw new RuntimeException('The Zip PHP extension is not installed. Please install it and try again.');
}

$this->output = $output;

$configFile = getcwd() . DS . 'october.yaml';
if ( ! file_exists($configFile)) {
return $output->writeln('<comment>october.yaml not found. Run october init first.</comment>');
Expand All @@ -78,27 +93,27 @@ protected function execute(InputInterface $input, OutputInterface $output)
$this->writeConfig();

$output->writeln('<info>Migrating Database...</info>');
(new Process('php artisan october:up'))->run();
$this->runProcess('php artisan october:up', 'Migrations failed!');

$output->writeln('<info>Removing demo data...</info>');
(new Process('php artisan october:fresh'))->run();
$this->runProcess('php artisan october:fresh', 'Failed to remove demo data!');

$output->writeln('<info>Clearing cache...</info>');
(new Process('php artisan clear-compiled'))->run();
(new Process('php artisan cache:clear'))->run();

$this->runProcess('php artisan clear-compiled', 'Failed to clear compiled files!');
$this->runProcess('php artisan cache:clear', 'Failed to clear cache!');
$output->writeln('<info>Installing Theme...</info>');
try {
(new ThemeInstaller($this->config))->install();
} catch (\RuntimeException $e) {
$output->writeln("<error>${e}</error>");
$output->writeln("<error>" . $e->getMessage() . "</error>");
}

$output->writeln('<info>Installing Plugins...</info>');
try {
(new PluginInstaller($this->config))->install();
} catch (\RuntimeException $e) {
$output->writeln("<error>${e}</error>");
$output->writeln("<error>" . $e->getMessage() . "</error>");
}

$output->writeln('<info>Setting up deployments...</info>');
Expand Down Expand Up @@ -162,4 +177,41 @@ protected function cleanup()
@unlink(getcwd() . DS . $file);
}
}

/**
* Runs a process and checks it's result.
* Prints an error message if necessary.
*
* @param $command
* @param $errorMessage
*
* @return bool
* @throws \Symfony\Component\Process\Exception\RuntimeException
* @throws \Symfony\Component\Process\Exception\LogicException
*/
protected function runProcess($command, $errorMessage)
{
$exitCode = (new Process($command))->run();

return $this->checkResult($exitCode, $errorMessage);
}

/**
* Checks the result of a process.
*
* @param $exitCode
* @param $message
*
* @return bool
*/
protected function checkResult($exitCode, $message)
{
if ($exitCode !== $this::EXIT_CODE_OK) {
$this->output->writeln('<error>' . $message . '</error>');

return false;
}

return true;
}
}
4 changes: 4 additions & 0 deletions src/Installer/BaseInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

abstract class BaseInstaller
{
/**
* Exit code for processes
*/
const EXIT_CODE_OK = 0;

public abstract function install();

Expand Down
35 changes: 29 additions & 6 deletions src/Installer/PluginInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@


use GitElephant\Repository;
use Symfony\Component\Process\Exception\LogicException;
use Symfony\Component\Process\Exception\RuntimeException;
use Symfony\Component\Process\Process;

/**
Expand All @@ -12,12 +14,11 @@
*/
class PluginInstaller extends BaseInstaller
{

/**
*
* @throws \RuntimeException
* @throws \Symfony\Component\Process\Exception\LogicException
* @throws \Symfony\Component\Process\Exception\RuntimeException
* @throws LogicException
* @throws RuntimeException
* @throws \Symfony\Component\Process\Exception\InvalidArgumentException
*/
public function install()
Expand All @@ -35,7 +36,7 @@ public function install()
$plugin = strtolower($plugin);

if ($remote === false) {
(new Process("php artisan plugin:install {$vendor}.{$plugin}"))->run();
$this->installViaArtisan($vendor, $plugin);
continue;
}

Expand All @@ -47,8 +48,8 @@ public function install()
$repo = Repository::open($pluginDir);
try {
$repo->cloneFrom($remote, $pluginDir);
} catch (\RuntimeException $e) {
throw new \RuntimeException('Error while cloning plugin repo: ' . $e->getMessage());
} catch (RuntimeException $e) {
throw new RuntimeException('Error while cloning plugin repo: ' . $e->getMessage());
}

(new Process("php artisan plugin:refresh {$vendor}.{$plugin}"))->run();
Expand Down Expand Up @@ -89,4 +90,26 @@ protected function createVendorDir($vendor)

return $this->mkdir($pluginDir);
}

/**
* Installs a plugin via artisan command.
*
* @param $vendor
* @param $plugin
*
* @throws LogicException
* @throws RuntimeException
*/
protected function installViaArtisan($vendor, $plugin)
{
$exitCode = (new Process("php artisan plugin:install {$vendor}.{$plugin}"))->run();

if ($exitCode !== $this::EXIT_CODE_OK) {
throw new RuntimeException(
sprintf('Error while installing plugin %s via artisan. Is your database set up correctly?',
$vendor . '.' . $plugin
)
);
}
}
}
57 changes: 49 additions & 8 deletions src/Installer/ThemeInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@


use GitElephant\Repository;
use Symfony\Component\Process\Exception\InvalidArgumentException;
use Symfony\Component\Process\Exception\LogicException;
use Symfony\Component\Process\Exception\RuntimeException;
use Symfony\Component\Process\Process;

/**
Expand All @@ -14,9 +17,10 @@ class ThemeInstaller extends BaseInstaller
{
/**
*
* @throws \Symfony\Component\Process\Exception\LogicException
* @throws \Symfony\Component\Process\Exception\RuntimeException
* @throws \Symfony\Component\Process\Exception\InvalidArgumentException
* @throws LogicException
* @throws RuntimeException
* @throws InvalidArgumentException
* @throws \RuntimeException
*/
public function install()
{
Expand All @@ -29,19 +33,23 @@ public function install()

list($theme, $remote) = $this->parse($config);
if ($remote === false) {
(new Process("php artisan theme:install {$theme}"))->run();

return true;
return $this->installViaArtisan($theme);
}

$themeDir = getcwd() . DS . implode(DS, ['themes', $theme]);
$this->mkdir($themeDir);

if ( ! $this->isEmpty($themeDir)) {
throw new RuntimeException(
sprintf('Your theme directory "%s" is not empty. Cannot clone your repo into it.', $themeDir)
);
}

$repo = Repository::open($themeDir);
try {
$repo->cloneFrom($remote, $themeDir);
} catch (\RuntimeException $e) {
throw new \RuntimeException('Error while cloning theme repo: ' . $e->getMessage());
} catch (RuntimeException $e) {
throw new RuntimeException('Error while cloning theme repo: ' . $e->getMessage());
}

$this->cleanup($themeDir);
Expand All @@ -67,4 +75,37 @@ protected function parse($theme)

return $matches;
}

/**
* Installs a theme via artisan command.
*
* @param $theme
*
* @return bool
*
* @throws LogicException
* @throws RuntimeException
*/
protected function installViaArtisan($theme)
{
$exitCode = (new Process("php artisan theme:install {$theme}"))->run();

if ($exitCode !== $this::EXIT_CODE_OK) {
throw new RuntimeException(sprintf('Error while installing theme "%s" via artisan.', $theme));
}

return true;
}

/**
* Checks if a directory is empty.
*
* @param $themeDir
*
* @return bool
*/
protected function isEmpty($themeDir)
{
return count(glob($themeDir . '/*')) === 0;
}
}

0 comments on commit ddf8eb0

Please sign in to comment.