2016-04-19 15:54:03 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace NoccyLabs\Hotfix\Command;
|
|
|
|
|
|
|
|
use Symfony\Component\Console\Command\Command;
|
|
|
|
|
|
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
|
|
use Symfony\Component\Console\Input\InputArgument;
|
|
|
|
use Symfony\Component\Console\Input\InputOption;
|
|
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
|
|
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
2016-04-19 22:55:09 +02:00
|
|
|
use Symfony\Component\Console\Question\ChoiceQuestion;
|
2016-12-02 15:23:03 +01:00
|
|
|
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
2016-04-19 15:54:03 +02:00
|
|
|
use NoccyLabs\Hotfix\Hotfix\Loader;
|
2016-12-11 22:36:27 +01:00
|
|
|
use NoccyLabs\Hotfix\Hotfix\Hotfix;
|
2016-12-02 15:23:03 +01:00
|
|
|
use NoccyLabs\Hotfix\System\Facts;
|
2016-12-11 22:36:27 +01:00
|
|
|
use NoccyLabs\Hotfix\Runner\RunnerFactory;
|
|
|
|
use NoccyLabs\Hotfix\Hotfix\HotfixLoader;
|
2016-04-19 15:54:03 +02:00
|
|
|
|
|
|
|
class ApplyCommand extends Command
|
|
|
|
{
|
|
|
|
|
|
|
|
protected function configure()
|
|
|
|
{
|
|
|
|
$this->setName("apply");
|
|
|
|
$this->setDescription("Apply a hotfix from a file or the Internet");
|
|
|
|
|
|
|
|
$this->addOption("insecure", "I", InputOption::VALUE_NONE, "Disable signature checks. Don't use unless you know what you are doing!");
|
2016-04-19 22:55:09 +02:00
|
|
|
$this->addOption("preview", "p", InputOption::VALUE_NONE, "Only preview the hotfix script, don't apply anything");
|
2016-04-19 15:54:03 +02:00
|
|
|
|
2016-12-11 22:36:27 +01:00
|
|
|
$this->addArgument("hotfix", InputArgument::OPTIONAL, "The identifier or filename of the hotfix");
|
2016-04-19 15:54:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output)
|
|
|
|
{
|
|
|
|
$this->output = $output;
|
|
|
|
|
|
|
|
$fix = $input->getArgument("hotfix");
|
2016-04-19 22:55:09 +02:00
|
|
|
|
|
|
|
if (!$fix) {
|
2016-12-11 22:36:27 +01:00
|
|
|
$output->writeln("No hotfix specified.");
|
2016-04-19 22:55:09 +02:00
|
|
|
return;
|
|
|
|
}
|
2016-04-19 15:54:03 +02:00
|
|
|
|
2016-12-11 22:36:27 +01:00
|
|
|
//$loader = new Loader();
|
2016-04-19 15:54:03 +02:00
|
|
|
$output->writeln("Reading hotfix <comment>{$fix}</comment>...");
|
|
|
|
try {
|
2016-12-11 22:36:27 +01:00
|
|
|
$hotfix = HotfixLoader::load($fix);
|
|
|
|
//$hotfix = $loader->load($fix, $insecure);
|
2016-04-19 15:54:03 +02:00
|
|
|
} catch (\Exception $e) {
|
|
|
|
$output->writeln("<error>Error: ".$e->getMessage()."</error>");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$output->writeln("");
|
2016-12-02 15:23:03 +01:00
|
|
|
|
2016-12-11 22:36:27 +01:00
|
|
|
$header = $hotfix->getHeader();
|
|
|
|
$output->writeln(" Hotfix: <fg=yellow;options=bold>".$header->getName()."</fg=yellow;options=bold>");
|
|
|
|
$output->writeln(" Author: <comment>".$header->getAuthor()."</comment>");
|
|
|
|
$info = explode("\n",wordwrap(trim($header->getInfo()), 60));
|
2016-04-19 22:55:09 +02:00
|
|
|
$info = "<comment>".join("</comment>\n <comment>", $info)."</comment>";
|
|
|
|
$output->writeln(" Info: ".$info);
|
2016-04-19 15:54:03 +02:00
|
|
|
$output->writeln("");
|
2016-12-11 22:36:27 +01:00
|
|
|
|
|
|
|
if (!$this->checkSignature($hotfix, $output)) {
|
|
|
|
if (!$input->getOption('insecure')) {
|
|
|
|
$output->writeln("<error>Hotfix can not be authenticated. Aborting!</error>");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!$this->checkRequirements($hotfix, $output)) {
|
|
|
|
$output->writeln("<error>Error: This hotfix it not compatible with the current distribution</>");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$output->writeln("");
|
|
|
|
|
2016-04-19 22:55:09 +02:00
|
|
|
if ($input->getOption("preview")) {
|
|
|
|
$output->writeln("This is the script that will be executed:");
|
|
|
|
$body = $hotfix->getBody();
|
|
|
|
$body = "<fg=cyan> ".join("\n ", explode("\n",$body))."</fg=cyan>";
|
|
|
|
$output->writeln($body);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-04-19 15:54:03 +02:00
|
|
|
$helper = $this->getHelper("question");
|
|
|
|
$question = new ConfirmationQuestion("Do you want to apply this hotfix? [y/N] ", false);
|
|
|
|
|
|
|
|
if (!$helper->ask($input, $output, $question)) {
|
|
|
|
return;
|
|
|
|
}
|
2016-12-11 22:36:27 +01:00
|
|
|
|
2016-04-19 15:54:03 +02:00
|
|
|
|
|
|
|
$output->writeln("\n<info>Applying hotfix...</info>\n");
|
|
|
|
try {
|
|
|
|
$hotfix->apply();
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
$output->writeln("\n<error>Error: ".$e->getMessage()."</error>");
|
|
|
|
}
|
|
|
|
$output->writeln("\n<info>Hotfix applied successfully</info>");
|
|
|
|
}
|
|
|
|
|
2016-12-11 22:36:27 +01:00
|
|
|
private function checkSignature(Hotfix $hotfix, OutputInterface $output)
|
|
|
|
{
|
|
|
|
$signature = $hotfix->getSignature();
|
|
|
|
if ($signature->isValid()) {
|
|
|
|
$keyid = $signature->getKeyId();
|
|
|
|
$signer = $signature->getSigner();
|
|
|
|
$output->writeln("Hotfix has good signature from <fg=green;options=bold>{$signer}</fg=green;options=bold> (keyid <info>{$keyid}</info>)");
|
|
|
|
} else {
|
|
|
|
$error = $signature->getError();
|
|
|
|
$output->writeln("<fg=red;options=bold>Warning: {$error}</fg=red;options=bold>");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private function checkRequirements(Hotfix $hotfix, OutputInterface $output)
|
|
|
|
{
|
|
|
|
$requires = $hotfix->getHeader()->getRequirements();
|
|
|
|
if (count($requires)>0) {
|
|
|
|
$engine = new ExpressionLanguage();
|
|
|
|
$facts = Facts::getSystemFacts()->getFacts();
|
|
|
|
while (true) {
|
|
|
|
$expr = array_shift($requires);
|
|
|
|
$ret = $engine->evaluate($expr, $facts);
|
|
|
|
if ($ret) {
|
|
|
|
//$output->writeln("<fg=green;options=bold>Hotfix is compatible with the current distribution</>");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (count($requires)==0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-04-19 15:54:03 +02:00
|
|
|
}
|