+++ /dev/null
-<?php
-
-namespace Robo;
-
-use Symfony\Component\Console\Command\Command;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Filesystem\Filesystem as sfFilesystem;
-
-/**
- * Update the robo.phar from the latest github release
- *
- * @author Alexander Menk <alex.menk@gmail.com>
- */
-class SelfUpdateCommand extends Command
-{
- const SELF_UPDATE_COMMAND_NAME = 'self:update';
-
- protected $gitHubRepository;
-
- protected $currentVersion;
-
- protected $applicationName;
-
- public function __construct($applicationName = null, $currentVersion = null, $gitHubRepository = null)
- {
- $this->applicationName = $applicationName;
- $this->currentVersion = $currentVersion;
- $this->gitHubRepository = $gitHubRepository;
-
- parent::__construct(self::SELF_UPDATE_COMMAND_NAME);
- }
-
- /**
- * {@inheritdoc}
- */
- protected function configure()
- {
- $app = $this->applicationName;
-
- $this
- ->setAliases(array('update'))
- ->setDescription("Updates $app to the latest version.")
- ->setHelp(
- <<<EOT
-The <info>self-update</info> command checks github for newer
-versions of $app and if found, installs the latest.
-EOT
- );
- }
-
- protected function getLatestReleaseFromGithub()
- {
- $opts = [
- 'http' => [
- 'method' => 'GET',
- 'header' => [
- 'User-Agent: ' . $this->applicationName . ' (' . $this->gitHubRepository . ')' . ' Self-Update (PHP)'
- ]
- ]
- ];
-
- $context = stream_context_create($opts);
-
- $releases = file_get_contents('https://api.github.com/repos/' . $this->gitHubRepository . '/releases', false, $context);
- $releases = json_decode($releases);
-
- if (! isset($releases[0])) {
- throw new \Exception('API error - no release found at GitHub repository ' . $this->gitHubRepository);
- }
-
- $version = $releases[0]->tag_name;
- $url = $releases[0]->assets[0]->browser_download_url;
-
- return [ $version, $url ];
- }
-
- /**
- * {@inheritdoc}
- */
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- if (empty(\Phar::running())) {
- throw new \Exception(self::SELF_UPDATE_COMMAND_NAME . ' only works when running the phar version of ' . $this->applicationName . '.');
- }
-
- $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
- $programName = basename($localFilename);
- $tempFilename = dirname($localFilename) . '/' . basename($localFilename, '.phar') . '-temp.phar';
-
- // check for permissions in local filesystem before start connection process
- if (! is_writable($tempDirectory = dirname($tempFilename))) {
- throw new \Exception(
- $programName . ' update failed: the "' . $tempDirectory .
- '" directory used to download the temp file could not be written'
- );
- }
-
- if (! is_writable($localFilename)) {
- throw new \Exception(
- $programName . ' update failed: the "' . $localFilename . '" file could not be written (execute with sudo)'
- );
- }
-
- list( $latest, $downloadUrl ) = $this->getLatestReleaseFromGithub();
-
-
- if ($this->currentVersion == $latest) {
- $output->writeln('No update available');
- return;
- }
-
- $fs = new sfFilesystem();
-
- $output->writeln('Downloading ' . $this->applicationName . ' (' . $this->gitHubRepository . ') ' . $latest);
-
- $fs->copy($downloadUrl, $tempFilename);
-
- $output->writeln('Download finished');
-
- try {
- \error_reporting(E_ALL); // supress notices
-
- @chmod($tempFilename, 0777 & ~umask());
- // test the phar validity
- $phar = new \Phar($tempFilename);
- // free the variable to unlock the file
- unset($phar);
- @rename($tempFilename, $localFilename);
- $output->writeln('<info>Successfully updated ' . $programName . '</info>');
- $this->_exit();
- } catch (\Exception $e) {
- @unlink($tempFilename);
- if (! $e instanceof \UnexpectedValueException && ! $e instanceof \PharException) {
- throw $e;
- }
- $output->writeln('<error>The download is corrupted (' . $e->getMessage() . ').</error>');
- $output->writeln('<error>Please re-run the self-update command to try again.</error>');
- }
- }
-
- /**
- * Stop execution
- *
- * This is a workaround to prevent warning of dispatcher after replacing
- * the phar file.
- *
- * @return void
- */
- protected function _exit()
- {
- exit;
- }
-}