139 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?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;
 | 
						|
use Symfony\Component\Console\Question\ChoiceQuestion;
 | 
						|
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
 | 
						|
use NoccyLabs\Hotfix\Hotfix\Loader;
 | 
						|
use NoccyLabs\Hotfix\Hotfix\Hotfix;
 | 
						|
use NoccyLabs\Hotfix\System\Facts;
 | 
						|
use NoccyLabs\Hotfix\Runner\RunnerFactory;
 | 
						|
use NoccyLabs\Hotfix\Hotfix\HotfixLoader;
 | 
						|
 | 
						|
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!");
 | 
						|
        $this->addOption("preview", "p", InputOption::VALUE_NONE, "Only preview the hotfix script, don't apply anything");
 | 
						|
 | 
						|
        $this->addArgument("hotfix", InputArgument::OPTIONAL, "The identifier or filename of the hotfix");
 | 
						|
    }
 | 
						|
 | 
						|
    protected function execute(InputInterface $input, OutputInterface $output)
 | 
						|
    {
 | 
						|
        $this->output = $output;
 | 
						|
 | 
						|
        $fix = $input->getArgument("hotfix");
 | 
						|
 | 
						|
        if (!$fix) {
 | 
						|
            $output->writeln("No hotfix specified.");
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        //$loader = new Loader();
 | 
						|
        $output->writeln("Reading hotfix <comment>{$fix}</comment>...");
 | 
						|
        try {
 | 
						|
            $hotfix = HotfixLoader::load($fix);
 | 
						|
            //$hotfix = $loader->load($fix, $insecure);
 | 
						|
        } catch (\Exception $e) {
 | 
						|
            $output->writeln("<error>Error: ".$e->getMessage()."</error>");
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        $output->writeln("");
 | 
						|
 | 
						|
        $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));
 | 
						|
        $info = "<comment>".join("</comment>\n           <comment>", $info)."</comment>";
 | 
						|
        $output->writeln("  Info:    ".$info);
 | 
						|
        $output->writeln("");
 | 
						|
 | 
						|
        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("");
 | 
						|
 | 
						|
        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;
 | 
						|
        }
 | 
						|
        
 | 
						|
        $helper = $this->getHelper("question");
 | 
						|
        $question = new ConfirmationQuestion("Do you want to apply this hotfix? [y/N] ", false);
 | 
						|
        
 | 
						|
        if (!$helper->ask($input, $output, $question)) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        
 | 
						|
        $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>");
 | 
						|
    }
 | 
						|
 | 
						|
    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;
 | 
						|
        
 | 
						|
    }
 | 
						|
 | 
						|
}
 |