Upgrade framework
This commit is contained in:
31
vendor/psy/psysh/src/VersionUpdater/Checker.php
vendored
Normal file
31
vendor/psy/psysh/src/VersionUpdater/Checker.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\VersionUpdater;
|
||||
|
||||
interface Checker
|
||||
{
|
||||
const ALWAYS = 'always';
|
||||
const DAILY = 'daily';
|
||||
const WEEKLY = 'weekly';
|
||||
const MONTHLY = 'monthly';
|
||||
const NEVER = 'never';
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isLatest(): bool;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLatest(): string;
|
||||
}
|
||||
47
vendor/psy/psysh/src/VersionUpdater/Downloader.php
vendored
Normal file
47
vendor/psy/psysh/src/VersionUpdater/Downloader.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\VersionUpdater;
|
||||
|
||||
use Psy\Exception\ErrorException;
|
||||
|
||||
interface Downloader
|
||||
{
|
||||
/**
|
||||
* Set the directory where the download will be written to.
|
||||
*
|
||||
* @param string $tempDir
|
||||
*/
|
||||
public function setTempDir(string $tempDir);
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws ErrorException on failure
|
||||
*/
|
||||
public function download(string $url): bool;
|
||||
|
||||
/**
|
||||
* Get the temporary file name the download was written to.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFilename(): string;
|
||||
|
||||
/**
|
||||
* Delete the downloaded file if it exists.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cleanup();
|
||||
}
|
||||
84
vendor/psy/psysh/src/VersionUpdater/Downloader/CurlDownloader.php
vendored
Normal file
84
vendor/psy/psysh/src/VersionUpdater/Downloader/CurlDownloader.php
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\VersionUpdater\Downloader;
|
||||
|
||||
use Psy\Exception\ErrorException;
|
||||
use Psy\Shell;
|
||||
use Psy\VersionUpdater\Downloader;
|
||||
|
||||
class CurlDownloader implements Downloader
|
||||
{
|
||||
private $tempDir = null;
|
||||
private $outputFile = null;
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function setTempDir(string $tempDir)
|
||||
{
|
||||
$this->tempDir = $tempDir;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function download(string $url): bool
|
||||
{
|
||||
$tempDir = $this->tempDir ?: \sys_get_temp_dir();
|
||||
$this->outputFile = \tempnam($tempDir, 'psysh-archive-');
|
||||
$targetName = $this->outputFile.'.tar.gz';
|
||||
|
||||
if (!\rename($this->outputFile, $targetName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->outputFile = $targetName;
|
||||
|
||||
$outputHandle = \fopen($this->outputFile, 'w');
|
||||
if (!$outputHandle) {
|
||||
return false;
|
||||
}
|
||||
$curl = \curl_init();
|
||||
\curl_setopt_array($curl, [
|
||||
\CURLOPT_FAILONERROR => true,
|
||||
\CURLOPT_HEADER => 0,
|
||||
\CURLOPT_FOLLOWLOCATION => true,
|
||||
\CURLOPT_TIMEOUT => 10,
|
||||
\CURLOPT_FILE => $outputHandle,
|
||||
\CURLOPT_HTTPHEADER => [
|
||||
'User-Agent' => 'PsySH/'.Shell::VERSION,
|
||||
],
|
||||
]);
|
||||
\curl_setopt($curl, \CURLOPT_URL, $url);
|
||||
$result = \curl_exec($curl);
|
||||
$error = \curl_error($curl);
|
||||
\curl_close($curl);
|
||||
|
||||
\fclose($outputHandle);
|
||||
|
||||
if (!$result) {
|
||||
throw new ErrorException('cURL Error: '.$error);
|
||||
}
|
||||
|
||||
return (bool) $result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function getFilename(): string
|
||||
{
|
||||
return $this->outputFile;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function cleanup()
|
||||
{
|
||||
if (\file_exists($this->outputFile)) {
|
||||
\unlink($this->outputFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
33
vendor/psy/psysh/src/VersionUpdater/Downloader/Factory.php
vendored
Normal file
33
vendor/psy/psysh/src/VersionUpdater/Downloader/Factory.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\VersionUpdater\Downloader;
|
||||
|
||||
use Psy\Exception\ErrorException;
|
||||
use Psy\VersionUpdater\Downloader;
|
||||
|
||||
class Factory
|
||||
{
|
||||
/**
|
||||
* @return Downloader
|
||||
*
|
||||
* @throws ErrorException If no downloaders can be used
|
||||
*/
|
||||
public static function getDownloader(): Downloader
|
||||
{
|
||||
if (\extension_loaded('curl')) {
|
||||
return new CurlDownloader();
|
||||
} elseif (\ini_get('allow_url_fopen')) {
|
||||
return new FileDownloader();
|
||||
}
|
||||
throw new ErrorException('No downloader available.');
|
||||
}
|
||||
}
|
||||
56
vendor/psy/psysh/src/VersionUpdater/Downloader/FileDownloader.php
vendored
Normal file
56
vendor/psy/psysh/src/VersionUpdater/Downloader/FileDownloader.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\VersionUpdater\Downloader;
|
||||
|
||||
use Psy\VersionUpdater\Downloader;
|
||||
|
||||
class FileDownloader implements Downloader
|
||||
{
|
||||
private $tempDir = null;
|
||||
private $outputFile = null;
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function setTempDir(string $tempDir)
|
||||
{
|
||||
$this->tempDir = $tempDir;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function download(string $url): bool
|
||||
{
|
||||
$tempDir = $this->tempDir ?: \sys_get_temp_dir();
|
||||
$this->outputFile = \tempnam($tempDir, 'psysh-archive-');
|
||||
$targetName = $this->outputFile.'.tar.gz';
|
||||
|
||||
if (!\rename($this->outputFile, $targetName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->outputFile = $targetName;
|
||||
|
||||
return (bool) \file_put_contents($this->outputFile, \file_get_contents($url));
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function getFilename(): string
|
||||
{
|
||||
return $this->outputFile;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public function cleanup()
|
||||
{
|
||||
if (\file_exists($this->outputFile)) {
|
||||
\unlink($this->outputFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
93
vendor/psy/psysh/src/VersionUpdater/GitHubChecker.php
vendored
Normal file
93
vendor/psy/psysh/src/VersionUpdater/GitHubChecker.php
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\VersionUpdater;
|
||||
|
||||
use Psy\Shell;
|
||||
|
||||
class GitHubChecker implements Checker
|
||||
{
|
||||
const URL = 'https://api.github.com/repos/bobthecow/psysh/releases/latest';
|
||||
|
||||
private $latest;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isLatest(): bool
|
||||
{
|
||||
// version_compare doesn't handle semver completely;
|
||||
// strip pre-release and build metadata before comparing
|
||||
$version = \preg_replace('/[+-]\w+/', '', Shell::VERSION);
|
||||
|
||||
return \version_compare($version, $this->getLatest(), '>=');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLatest(): string
|
||||
{
|
||||
if (!isset($this->latest)) {
|
||||
$this->setLatest($this->getVersionFromTag());
|
||||
}
|
||||
|
||||
return $this->latest;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $version
|
||||
*/
|
||||
public function setLatest(string $version)
|
||||
{
|
||||
$this->latest = $version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
private function getVersionFromTag()
|
||||
{
|
||||
$contents = $this->fetchLatestRelease();
|
||||
if (!$contents || !isset($contents->tag_name)) {
|
||||
throw new \InvalidArgumentException('Unable to check for updates');
|
||||
}
|
||||
$this->setLatest($contents->tag_name);
|
||||
|
||||
return $this->getLatest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to public to make testing easier.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fetchLatestRelease()
|
||||
{
|
||||
$context = \stream_context_create([
|
||||
'http' => [
|
||||
'user_agent' => 'PsySH/'.Shell::VERSION,
|
||||
'timeout' => 1.0,
|
||||
],
|
||||
]);
|
||||
|
||||
\set_error_handler(function () {
|
||||
// Just ignore all errors with this. The checker will throw an exception
|
||||
// if it doesn't work :)
|
||||
});
|
||||
|
||||
$result = @\file_get_contents(self::URL, false, $context);
|
||||
|
||||
\restore_error_handler();
|
||||
|
||||
return \json_decode($result);
|
||||
}
|
||||
}
|
||||
159
vendor/psy/psysh/src/VersionUpdater/Installer.php
vendored
Normal file
159
vendor/psy/psysh/src/VersionUpdater/Installer.php
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\VersionUpdater;
|
||||
|
||||
use Psy\Exception\ErrorException;
|
||||
|
||||
class Installer
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $installLocation;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $tempDirectory;
|
||||
|
||||
public function __construct(string $tempDirectory = null)
|
||||
{
|
||||
$this->tempDirectory = $tempDirectory ?: \sys_get_temp_dir();
|
||||
$this->installLocation = \Phar::running(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public to allow the Downloader to use the temporary directory if it's been set.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTempDirectory(): string
|
||||
{
|
||||
return $this->tempDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the currently installed PsySH phar is writable so it can be replaced.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isInstallLocationWritable(): bool
|
||||
{
|
||||
return \is_writable($this->installLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the temporary directory is writable so downloads and backups can be saved there.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isTempDirectoryWritable(): bool
|
||||
{
|
||||
return \is_writable($this->tempDirectory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the downloaded archive can be extracted with \PharData.
|
||||
*
|
||||
* @param string $sourceArchive
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isValidSource(string $sourceArchive): bool
|
||||
{
|
||||
if (!\class_exists('\PharData')) {
|
||||
return false;
|
||||
}
|
||||
$pharArchive = new \PharData($sourceArchive);
|
||||
|
||||
return $pharArchive->valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the "psysh" phar from the archive and move it, replacing the currently installed phar.
|
||||
*
|
||||
* @param string $sourceArchive
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function install(string $sourceArchive): bool
|
||||
{
|
||||
$pharArchive = new \PharData($sourceArchive);
|
||||
$outputDirectory = \tempnam($this->tempDirectory, 'psysh-');
|
||||
|
||||
// remove the temp file, and replace it with a sub-directory
|
||||
if (!\unlink($outputDirectory) || !\mkdir($outputDirectory, 0700)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pharArchive->extractTo($outputDirectory, ['psysh'], true);
|
||||
|
||||
$renamed = \rename($outputDirectory.'/psysh', $this->installLocation);
|
||||
|
||||
// Remove the sub-directory created to extract the psysh binary/phar
|
||||
\rmdir($outputDirectory);
|
||||
|
||||
return $renamed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a backup of the currently installed PsySH phar in the temporary directory with a version number postfix.
|
||||
*
|
||||
* @param string $version
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function createBackup(string $version): bool
|
||||
{
|
||||
$backupFilename = $this->getBackupFilename($version);
|
||||
|
||||
if (\file_exists($backupFilename) && !\is_writable($backupFilename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return \rename($this->installLocation, $backupFilename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the backup file to the original PsySH install location.
|
||||
*
|
||||
* @param string $version
|
||||
*
|
||||
* @throws ErrorException If the backup file could not be found
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function restoreFromBackup(string $version): bool
|
||||
{
|
||||
$backupFilename = $this->getBackupFilename($version);
|
||||
|
||||
if (!\file_exists($backupFilename)) {
|
||||
throw new ErrorException("Cannot restore from backup. File not found! [{$backupFilename}]");
|
||||
}
|
||||
|
||||
return \rename($backupFilename, $this->installLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full path for the backup target file location.
|
||||
*
|
||||
* @param string $version
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBackupFilename(string $version): string
|
||||
{
|
||||
$installFilename = \basename($this->installLocation);
|
||||
|
||||
return \sprintf('%s/%s.%s', $this->tempDirectory, $installFilename, $version);
|
||||
}
|
||||
}
|
||||
72
vendor/psy/psysh/src/VersionUpdater/IntervalChecker.php
vendored
Normal file
72
vendor/psy/psysh/src/VersionUpdater/IntervalChecker.php
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\VersionUpdater;
|
||||
|
||||
class IntervalChecker extends GitHubChecker
|
||||
{
|
||||
private $cacheFile;
|
||||
private $interval;
|
||||
|
||||
public function __construct($cacheFile, $interval)
|
||||
{
|
||||
$this->cacheFile = $cacheFile;
|
||||
$this->interval = $interval;
|
||||
}
|
||||
|
||||
public function fetchLatestRelease()
|
||||
{
|
||||
// Read the cached file
|
||||
$cached = \json_decode(@\file_get_contents($this->cacheFile, false));
|
||||
if ($cached && isset($cached->last_check) && isset($cached->release)) {
|
||||
$now = new \DateTime();
|
||||
$lastCheck = new \DateTime($cached->last_check);
|
||||
if ($lastCheck >= $now->sub($this->getDateInterval())) {
|
||||
return $cached->release;
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to fetching from GitHub
|
||||
$release = parent::fetchLatestRelease();
|
||||
if ($release && isset($release->tag_name)) {
|
||||
$this->updateCache($release);
|
||||
}
|
||||
|
||||
return $release;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \RuntimeException if interval passed to constructor is not supported
|
||||
*/
|
||||
private function getDateInterval(): \DateInterval
|
||||
{
|
||||
switch ($this->interval) {
|
||||
case Checker::DAILY:
|
||||
return new \DateInterval('P1D');
|
||||
case Checker::WEEKLY:
|
||||
return new \DateInterval('P1W');
|
||||
case Checker::MONTHLY:
|
||||
return new \DateInterval('P1M');
|
||||
}
|
||||
|
||||
throw new \RuntimeException('Invalid interval configured');
|
||||
}
|
||||
|
||||
private function updateCache($release)
|
||||
{
|
||||
$data = [
|
||||
'last_check' => \date(\DATE_ATOM),
|
||||
'release' => $release,
|
||||
];
|
||||
|
||||
\file_put_contents($this->cacheFile, \json_encode($data));
|
||||
}
|
||||
}
|
||||
36
vendor/psy/psysh/src/VersionUpdater/NoopChecker.php
vendored
Normal file
36
vendor/psy/psysh/src/VersionUpdater/NoopChecker.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\VersionUpdater;
|
||||
|
||||
use Psy\Shell;
|
||||
|
||||
/**
|
||||
* A version checker stub which always thinks the current version is up to date.
|
||||
*/
|
||||
class NoopChecker implements Checker
|
||||
{
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isLatest(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getLatest(): string
|
||||
{
|
||||
return Shell::VERSION;
|
||||
}
|
||||
}
|
||||
192
vendor/psy/psysh/src/VersionUpdater/SelfUpdate.php
vendored
Normal file
192
vendor/psy/psysh/src/VersionUpdater/SelfUpdate.php
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Psy Shell.
|
||||
*
|
||||
* (c) 2012-2022 Justin Hileman
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Psy\VersionUpdater;
|
||||
|
||||
use Psy\Exception\ErrorException;
|
||||
use Psy\Shell;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Self update command.
|
||||
*
|
||||
* If a new version is available, this command will download it and replace the currently installed version
|
||||
*/
|
||||
class SelfUpdate
|
||||
{
|
||||
const URL_PREFIX = 'https://github.com/bobthecow/psysh/releases/download';
|
||||
const SUCCESS = 0;
|
||||
const FAILURE = 1;
|
||||
|
||||
/** @var Checker */
|
||||
private $checker;
|
||||
|
||||
/** @var Installer */
|
||||
private $installer;
|
||||
|
||||
/** @var Downloader */
|
||||
private $downloader;
|
||||
|
||||
public function __construct(Checker $checker, Installer $installer)
|
||||
{
|
||||
$this->checker = $checker;
|
||||
$this->installer = $installer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow the downloader to be injected for testing.
|
||||
*
|
||||
* @param Downloader $downloader
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDownloader(Downloader $downloader)
|
||||
{
|
||||
$this->downloader = $downloader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently set Downloader or create one based on the capabilities of the php environment.
|
||||
*
|
||||
* @return Downloader
|
||||
*
|
||||
* @throws ErrorException if a downloader cannot be created for the php environment
|
||||
*/
|
||||
private function getDownloader(): Downloader
|
||||
{
|
||||
if (!isset($this->downloader)) {
|
||||
return Downloader\Factory::getDownloader();
|
||||
}
|
||||
|
||||
return $this->downloader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the download URL for the latest release.
|
||||
*
|
||||
* The file name used in the URL will include the flavour postfix extracted from the current version
|
||||
* if it's present
|
||||
*
|
||||
* @param string $latestVersion
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getAssetUrl(string $latestVersion): string
|
||||
{
|
||||
$versionPostfix = '';
|
||||
if (\strpos(Shell::VERSION, '+')) {
|
||||
$versionPostfix = '-'.\substr(Shell::VERSION, \strpos(Shell::VERSION, '+') + 1);
|
||||
}
|
||||
$downloadFilename = \sprintf('psysh-%s%s.tar.gz', $latestVersion, $versionPostfix);
|
||||
|
||||
// check if latest release data contains an asset matching the filename?
|
||||
|
||||
return \sprintf('%s/%s/%s', self::URL_PREFIX, $latestVersion, $downloadFilename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the self-update process.
|
||||
*
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
*
|
||||
* @throws ErrorException if the current version is not restored when installation fails
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function run(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$currentVersion = Shell::VERSION;
|
||||
|
||||
// already have the latest version?
|
||||
if ($this->checker->isLatest()) {
|
||||
// current version is latest version...
|
||||
$output->writeln('<info>Current version is up-to-date.</info>');
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
// can overwrite current version?
|
||||
if (!$this->installer->isInstallLocationWritable()) {
|
||||
$output->writeln('<error>Installed version is not writable.</error>');
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
// can download to, and create a backup in the temp directory?
|
||||
if (!$this->installer->isTempDirectoryWritable()) {
|
||||
$output->writeln('<error>Temporary directory is not writable.</error>');
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$latestVersion = $this->checker->getLatest();
|
||||
$downloadUrl = $this->getAssetUrl($latestVersion);
|
||||
|
||||
$output->write("Downloading PsySH $latestVersion ...");
|
||||
|
||||
try {
|
||||
$downloader = $this->getDownloader();
|
||||
$downloader->setTempDir($this->installer->getTempDirectory());
|
||||
$downloaded = $downloader->download($downloadUrl);
|
||||
} catch (ErrorException $e) {
|
||||
$output->write(' <error>Failed.</error>');
|
||||
$output->writeln(\sprintf('<error>%s</error>', $e->getMessage()));
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
if (!$downloaded) {
|
||||
$output->writeln('<error>Download failed.</error>');
|
||||
$downloader->cleanup();
|
||||
|
||||
return self::FAILURE;
|
||||
} else {
|
||||
$output->write(' <info>OK</info>'.\PHP_EOL);
|
||||
}
|
||||
|
||||
$downloadedFile = $downloader->getFilename();
|
||||
|
||||
if (!$this->installer->isValidSource($downloadedFile)) {
|
||||
$downloader->cleanup();
|
||||
$output->writeln('<error>Downloaded file is not a valid archive.</error>');
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
// create backup as bin.old-version in the temporary directory
|
||||
$backupCreated = $this->installer->createBackup($currentVersion);
|
||||
if (!$backupCreated) {
|
||||
$downloader->cleanup();
|
||||
$output->writeln('<error>Failed to create a backup of the current version.</error>');
|
||||
|
||||
return self::FAILURE;
|
||||
} elseif ($input->getOption('verbose')) {
|
||||
$backupFilename = $this->installer->getBackupFilename($currentVersion);
|
||||
$output->writeln('Created backup of current version: '.$backupFilename);
|
||||
}
|
||||
|
||||
if (!$this->installer->install($downloadedFile)) {
|
||||
$this->installer->restoreFromBackup($currentVersion);
|
||||
$downloader->cleanup();
|
||||
$output->writeln("<error>Failed to install new PsySH version $latestVersion.</error>");
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
// Remove the downloaded archive file from the temporary directory
|
||||
$downloader->cleanup();
|
||||
|
||||
$output->writeln("Updated PsySH from $currentVersion to <info>$latestVersion</info>");
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user