mirror of
https://github.com/getgrav/grav.git
synced 2025-10-26 07:56:07 +01:00
more granular install for self upgrade
Signed-off-by: Andy Miller <rhuk@mac.com>
This commit is contained in:
@@ -71,6 +71,8 @@ class SafeUpgradeService
|
||||
'cache',
|
||||
'user',
|
||||
];
|
||||
/** @var callable|null */
|
||||
private $progressCallback = null;
|
||||
|
||||
/**
|
||||
* @param array $options
|
||||
@@ -170,6 +172,7 @@ class SafeUpgradeService
|
||||
|
||||
// Copy extracted package into staging area.
|
||||
Folder::rcopy($extractedPath, $packagePath, true);
|
||||
$this->reportProgress('installing', 'Preparing staged package...', null);
|
||||
|
||||
$this->carryOverRootDotfiles($packagePath);
|
||||
|
||||
@@ -182,6 +185,7 @@ class SafeUpgradeService
|
||||
throw new RuntimeException('Staged package does not contain any files to promote.');
|
||||
}
|
||||
|
||||
$this->reportProgress('snapshot', 'Creating backup snapshot...', null);
|
||||
$this->createBackupSnapshot($entries, $backupPath);
|
||||
$this->syncGitDirectory($this->rootPath, $backupPath);
|
||||
|
||||
@@ -190,6 +194,8 @@ class SafeUpgradeService
|
||||
Folder::create(dirname($manifestPath));
|
||||
file_put_contents($manifestPath, json_encode($manifest, JSON_PRETTY_PRINT));
|
||||
|
||||
$this->reportProgress('installing', 'Copying update files...', null);
|
||||
|
||||
try {
|
||||
$this->copyEntries($entries, $packagePath, $this->rootPath);
|
||||
} catch (Throwable $e) {
|
||||
@@ -198,6 +204,7 @@ class SafeUpgradeService
|
||||
throw new RuntimeException('Failed to promote staged Grav release.', 0, $e);
|
||||
}
|
||||
|
||||
$this->reportProgress('finalizing', 'Finalizing upgrade...', null);
|
||||
$this->syncGitDirectory($backupPath, $this->rootPath);
|
||||
$this->persistManifest($manifest);
|
||||
$this->pruneOldSnapshots();
|
||||
@@ -274,6 +281,20 @@ class SafeUpgradeService
|
||||
}
|
||||
}
|
||||
|
||||
public function setProgressCallback(?callable $callback): self
|
||||
{
|
||||
$this->progressCallback = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function reportProgress(string $stage, string $message, ?int $percent = null, array $extra = []): void
|
||||
{
|
||||
if ($this->progressCallback) {
|
||||
($this->progressCallback)($stage, $message, $percent, $extra);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll back to the most recent snapshot.
|
||||
*
|
||||
@@ -300,6 +321,7 @@ class SafeUpgradeService
|
||||
throw new RuntimeException('Rollback snapshot entries are missing from the manifest.');
|
||||
}
|
||||
|
||||
$this->reportProgress('rollback', 'Restoring snapshot...', null);
|
||||
$this->copyEntries($entries, $backupPath, $this->rootPath);
|
||||
$this->syncGitDirectory($backupPath, $this->rootPath);
|
||||
$this->markRollback($manifest['id']);
|
||||
|
||||
@@ -44,6 +44,8 @@ class SelfupgradeCommand extends GpmCommand
|
||||
private $tmp;
|
||||
/** @var Upgrader */
|
||||
private $upgrader;
|
||||
/** @var string|null */
|
||||
private $lastProgressMessage = null;
|
||||
|
||||
/** @var string */
|
||||
protected $all_yes;
|
||||
@@ -438,6 +440,7 @@ class SelfupgradeCommand extends GpmCommand
|
||||
private function upgrade(): bool
|
||||
{
|
||||
$io = $this->getIO();
|
||||
$this->lastProgressMessage = null;
|
||||
|
||||
$this->upgradeGrav($this->file);
|
||||
|
||||
@@ -496,14 +499,24 @@ class SelfupgradeCommand extends GpmCommand
|
||||
*/
|
||||
private function upgradeGrav(string $zip): void
|
||||
{
|
||||
$io = $this->getIO();
|
||||
|
||||
try {
|
||||
$io->write("\x0D |- Extracting update... ");
|
||||
$folder = Installer::unZip($zip, $this->tmp . '/zip');
|
||||
if ($folder === false) {
|
||||
throw new RuntimeException(Installer::lastErrorMsg());
|
||||
}
|
||||
$io->write("\x0D");
|
||||
$io->writeln(' |- Extracting update... <green>ok</green> ');
|
||||
|
||||
$script = $folder . '/system/install.php';
|
||||
if ((file_exists($script) && $install = include $script) && is_callable($install)) {
|
||||
if (is_object($install) && method_exists($install, 'setProgressCallback')) {
|
||||
$install->setProgressCallback(function (string $stage, string $message, ?int $percent = null, array $extra = []) {
|
||||
$this->handleServiceProgress($stage, $message, $percent);
|
||||
});
|
||||
}
|
||||
$install($zip);
|
||||
} else {
|
||||
throw new RuntimeException('Uploaded archive file is not a valid Grav update package');
|
||||
@@ -513,6 +526,17 @@ class SelfupgradeCommand extends GpmCommand
|
||||
}
|
||||
}
|
||||
|
||||
private function handleServiceProgress(string $stage, string $message, ?int $percent = null, array $extra = []): void
|
||||
{
|
||||
if ($this->lastProgressMessage === $message) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->lastProgressMessage = $message;
|
||||
$io = $this->getIO();
|
||||
$io->writeln(sprintf(' |- %s', $message));
|
||||
}
|
||||
|
||||
private function ensureExecutablePermissions(): void
|
||||
{
|
||||
$executables = [
|
||||
|
||||
@@ -122,6 +122,8 @@ final class Install
|
||||
|
||||
/** @var static */
|
||||
private static $instance;
|
||||
/** @var callable|null */
|
||||
private $progressCallback = null;
|
||||
|
||||
/**
|
||||
* @return static
|
||||
@@ -187,6 +189,20 @@ ERR;
|
||||
$this->finalize();
|
||||
}
|
||||
|
||||
public function setProgressCallback(?callable $callback): self
|
||||
{
|
||||
$this->progressCallback = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function relayProgress(string $stage, string $message, ?int $percent = null): void
|
||||
{
|
||||
if ($this->progressCallback) {
|
||||
($this->progressCallback)($stage, $message, $percent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: This method can only be called after $grav['plugins']->init().
|
||||
*
|
||||
@@ -273,6 +289,11 @@ ERR;
|
||||
}
|
||||
|
||||
$service = new SafeUpgradeService($options);
|
||||
if ($this->progressCallback) {
|
||||
$service->setProgressCallback(function (string $stage, string $message, ?int $percent = null, array $extra = []) {
|
||||
$this->relayProgress($stage, $message, $percent);
|
||||
});
|
||||
}
|
||||
$service->promote($this->location, $this->getVersion(), $this->ignores);
|
||||
Installer::setError(Installer::OK);
|
||||
} else {
|
||||
|
||||
@@ -91,10 +91,9 @@ class SafeUpgradeServiceTest extends \Codeception\TestCase\Test
|
||||
|
||||
public function testPromoteAndRollback(): void
|
||||
{
|
||||
[$root, $staging, $manifestStore] = $this->prepareLiveEnvironment();
|
||||
[$root, $manifestStore] = $this->prepareLiveEnvironment();
|
||||
$service = new SafeUpgradeService([
|
||||
'root' => $root,
|
||||
'staging_root' => $staging,
|
||||
'manifest_store' => $manifestStore,
|
||||
]);
|
||||
|
||||
@@ -102,7 +101,7 @@ class SafeUpgradeServiceTest extends \Codeception\TestCase\Test
|
||||
$manifest = $service->promote($package, '1.8.0', ['backup', 'cache', 'images', 'logs', 'tmp', 'user']);
|
||||
|
||||
self::assertFileExists($root . '/system/new.txt');
|
||||
self::assertFileDoesNotExist($root . '/ORIGINAL');
|
||||
self::assertFileExists($root . '/ORIGINAL');
|
||||
|
||||
$manifestFile = $manifestStore . '/' . $manifest['id'] . '.json';
|
||||
self::assertFileExists($manifestFile);
|
||||
@@ -112,17 +111,14 @@ class SafeUpgradeServiceTest extends \Codeception\TestCase\Test
|
||||
self::assertFileExists($root . '/ORIGINAL');
|
||||
self::assertFileDoesNotExist($root . '/system/new.txt');
|
||||
|
||||
$snapshots = glob($staging . '/snapshot-*');
|
||||
self::assertNotEmpty($snapshots);
|
||||
self::assertEmpty(glob($staging . '/stage-*'));
|
||||
self::assertDirectoryExists($manifest['backup_path']);
|
||||
}
|
||||
|
||||
public function testPrunesOldSnapshots(): void
|
||||
{
|
||||
[$root, $staging, $manifestStore] = $this->prepareLiveEnvironment();
|
||||
[$root, $manifestStore] = $this->prepareLiveEnvironment();
|
||||
$service = new SafeUpgradeService([
|
||||
'root' => $root,
|
||||
'staging_root' => $staging,
|
||||
'manifest_store' => $manifestStore,
|
||||
]);
|
||||
|
||||
@@ -148,7 +144,6 @@ class SafeUpgradeServiceTest extends \Codeception\TestCase\Test
|
||||
|
||||
$service = new SafeUpgradeService([
|
||||
'root' => $root,
|
||||
'staging_root' => $this->tmpDir . '/staging',
|
||||
]);
|
||||
|
||||
$method = new ReflectionMethod(SafeUpgradeService::class, 'detectPsrLogConflicts');
|
||||
@@ -177,7 +172,6 @@ PHP;
|
||||
|
||||
$service = new SafeUpgradeService([
|
||||
'root' => $root,
|
||||
'staging_root' => $this->tmpDir . '/staging',
|
||||
]);
|
||||
|
||||
$method = new ReflectionMethod(SafeUpgradeService::class, 'detectMonologConflicts');
|
||||
@@ -198,7 +192,6 @@ PHP;
|
||||
|
||||
$service = new SafeUpgradeService([
|
||||
'root' => $root,
|
||||
'staging_root' => $this->tmpDir . '/staging',
|
||||
]);
|
||||
$service->clearRecoveryFlag();
|
||||
|
||||
@@ -206,12 +199,11 @@ PHP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{0:string,1:string,2:string}
|
||||
* @return array{0:string,1:string}
|
||||
*/
|
||||
private function prepareLiveEnvironment(): array
|
||||
{
|
||||
$root = $this->tmpDir . '/root';
|
||||
$staging = $this->tmpDir . '/staging';
|
||||
$manifestStore = $root . '/user/data/upgrades';
|
||||
|
||||
Folder::create($root . '/user/plugins/sample');
|
||||
@@ -221,7 +213,7 @@ PHP;
|
||||
file_put_contents($root . '/user/plugins/sample/blueprints.yaml', "name: Sample Plugin\nversion: 1.0.0\n");
|
||||
file_put_contents($root . '/user/plugins/sample/composer.json', json_encode(['require' => ['php' => '^8.0']], JSON_PRETTY_PRINT));
|
||||
|
||||
return [$root, $staging, $manifestStore];
|
||||
return [$root, $manifestStore];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user