mirror of
https://github.com/getgrav/grav.git
synced 2025-10-26 00:46:07 +02:00
more refactoring of safe install
Signed-off-by: Andy Miller <rhuk@mac.com>
This commit is contained in:
@@ -171,7 +171,8 @@ class SafeUpgradeService
|
||||
Folder::create(dirname($packagePath));
|
||||
|
||||
$this->reportProgress('installing', 'Preparing staged package...', null);
|
||||
$this->stageExtractedPackage($extractedPath, $packagePath);
|
||||
$stagingMode = $this->stageExtractedPackage($extractedPath, $packagePath);
|
||||
$this->reportProgress('installing', 'Preparing staged package...', null, ['mode' => $stagingMode]);
|
||||
|
||||
$this->carryOverRootDotfiles($packagePath);
|
||||
|
||||
@@ -186,7 +187,6 @@ class SafeUpgradeService
|
||||
|
||||
$this->reportProgress('snapshot', 'Creating backup snapshot...', null);
|
||||
$this->createBackupSnapshot($entries, $backupPath);
|
||||
$this->syncGitDirectory($this->rootPath, $backupPath);
|
||||
|
||||
$manifest = $this->buildManifest($stageId, $targetVersion, $packagePath, $backupPath, $entries);
|
||||
$manifestPath = $stagePath . DIRECTORY_SEPARATOR . 'manifest.json';
|
||||
@@ -199,12 +199,10 @@ class SafeUpgradeService
|
||||
$this->copyEntries($entries, $packagePath, $this->rootPath, 'installing', 'Deploying');
|
||||
} catch (Throwable $e) {
|
||||
$this->copyEntries($entries, $backupPath, $this->rootPath, 'installing', 'Restoring');
|
||||
$this->syncGitDirectory($backupPath, $this->rootPath);
|
||||
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();
|
||||
Folder::delete($stagePath);
|
||||
@@ -234,20 +232,22 @@ class SafeUpgradeService
|
||||
return $entries;
|
||||
}
|
||||
|
||||
private function stageExtractedPackage(string $sourcePath, string $packagePath): void
|
||||
private function stageExtractedPackage(string $sourcePath, string $packagePath): string
|
||||
{
|
||||
if (is_dir($packagePath)) {
|
||||
Folder::delete($packagePath);
|
||||
}
|
||||
|
||||
if (@rename($sourcePath, $packagePath)) {
|
||||
return;
|
||||
return 'move';
|
||||
}
|
||||
|
||||
Folder::create($packagePath);
|
||||
$entries = $this->collectPackageEntries($sourcePath);
|
||||
$this->copyEntries($entries, $sourcePath, $packagePath, 'installing', 'Staging');
|
||||
Folder::delete($sourcePath);
|
||||
|
||||
return 'copy';
|
||||
}
|
||||
|
||||
private function createBackupSnapshot(array $entries, string $backupPath): void
|
||||
@@ -360,7 +360,6 @@ class SafeUpgradeService
|
||||
|
||||
$this->reportProgress('rollback', 'Restoring snapshot...', null);
|
||||
$this->copyEntries($entries, $backupPath, $this->rootPath, 'rollback', 'Restoring');
|
||||
$this->syncGitDirectory($backupPath, $this->rootPath);
|
||||
$this->markRollback($manifest['id']);
|
||||
|
||||
return $manifest;
|
||||
@@ -552,14 +551,8 @@ class SafeUpgradeService
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip caches to avoid stale data.
|
||||
if (in_array($relative, ['cache', 'tmp'], true)) {
|
||||
Folder::create($stage);
|
||||
continue;
|
||||
}
|
||||
|
||||
Folder::create(dirname($stage));
|
||||
Folder::rcopy($live, $stage, true);
|
||||
// Use empty placeholders to preserve directory structure without duplicating data.
|
||||
Folder::create($stage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -713,25 +706,6 @@ class SafeUpgradeService
|
||||
* @param string $destination
|
||||
* @return void
|
||||
*/
|
||||
private function syncGitDirectory(string $source, string $destination): void
|
||||
{
|
||||
if (!$source || !$destination) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sourceGit = rtrim($source, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '.git';
|
||||
if (!is_dir($sourceGit)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$destinationGit = rtrim($destination, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '.git';
|
||||
if (is_dir($destinationGit)) {
|
||||
Folder::delete($destinationGit);
|
||||
}
|
||||
|
||||
Folder::rcopy($sourceGit, $destinationGit, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist manifest into Grav data directory.
|
||||
*
|
||||
|
||||
@@ -46,6 +46,14 @@ class SelfupgradeCommand extends GpmCommand
|
||||
private $upgrader;
|
||||
/** @var string|null */
|
||||
private $lastProgressMessage = null;
|
||||
/** @var float|null */
|
||||
private $operationTimerStart = null;
|
||||
/** @var string|null */
|
||||
private $currentProgressStage = null;
|
||||
/** @var float|null */
|
||||
private $currentStageStartedAt = null;
|
||||
/** @var array */
|
||||
private $currentStageExtras = [];
|
||||
|
||||
/** @var string */
|
||||
protected $all_yes;
|
||||
@@ -235,6 +243,7 @@ class SelfupgradeCommand extends GpmCommand
|
||||
$this->file = $this->download($update);
|
||||
|
||||
$io->write(' |- Installing upgrade... ');
|
||||
$this->operationTimerStart = microtime(true);
|
||||
$installation = $this->upgrade();
|
||||
|
||||
$error = 0;
|
||||
@@ -443,6 +452,13 @@ class SelfupgradeCommand extends GpmCommand
|
||||
$this->lastProgressMessage = null;
|
||||
|
||||
$this->upgradeGrav($this->file);
|
||||
$this->finalizeStageTracking();
|
||||
|
||||
$elapsed = null;
|
||||
if (null !== $this->operationTimerStart) {
|
||||
$elapsed = microtime(true) - $this->operationTimerStart;
|
||||
$this->operationTimerStart = null;
|
||||
}
|
||||
|
||||
$errorCode = Installer::lastErrorCode();
|
||||
if ($errorCode) {
|
||||
@@ -454,6 +470,10 @@ class SelfupgradeCommand extends GpmCommand
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null !== $elapsed) {
|
||||
$io->writeln(sprintf(' |- Safe upgrade staging completed in %s', $this->formatDuration($elapsed)));
|
||||
}
|
||||
|
||||
$io->write("\x0D");
|
||||
// extra white spaces to clear out the buffer properly
|
||||
$io->writeln(' |- Installing upgrade... <green>ok</green> ');
|
||||
@@ -528,13 +548,19 @@ class SelfupgradeCommand extends GpmCommand
|
||||
|
||||
private function handleServiceProgress(string $stage, string $message, ?int $percent = null, array $extra = []): void
|
||||
{
|
||||
$this->trackStageProgress($stage, $message, $extra);
|
||||
|
||||
if ($this->lastProgressMessage === $message) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->lastProgressMessage = $message;
|
||||
$io = $this->getIO();
|
||||
$io->writeln(sprintf(' |- %s', $message));
|
||||
$suffix = '';
|
||||
if (null !== $percent) {
|
||||
$suffix = sprintf(' (%d%%)', $percent);
|
||||
}
|
||||
$io->writeln(sprintf(' |- %s%s', $message, $suffix));
|
||||
}
|
||||
|
||||
private function ensureExecutablePermissions(): void
|
||||
@@ -560,4 +586,69 @@ class SelfupgradeCommand extends GpmCommand
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function trackStageProgress(string $stage, string $message, array $extra = []): void
|
||||
{
|
||||
$now = microtime(true);
|
||||
|
||||
if (null !== $this->currentProgressStage && $stage !== $this->currentProgressStage && null !== $this->currentStageStartedAt) {
|
||||
$elapsed = $now - $this->currentStageStartedAt;
|
||||
$this->emitStageSummary($this->currentProgressStage, $elapsed, $this->currentStageExtras);
|
||||
$this->currentStageExtras = [];
|
||||
}
|
||||
|
||||
if ($stage !== $this->currentProgressStage) {
|
||||
$this->currentProgressStage = $stage;
|
||||
$this->currentStageStartedAt = $now;
|
||||
$this->currentStageExtras = [];
|
||||
}
|
||||
|
||||
if (!isset($this->currentStageExtras['label'])) {
|
||||
$this->currentStageExtras['label'] = $message;
|
||||
}
|
||||
|
||||
if ($extra) {
|
||||
$this->currentStageExtras = array_merge($this->currentStageExtras, $extra);
|
||||
}
|
||||
}
|
||||
|
||||
private function finalizeStageTracking(): void
|
||||
{
|
||||
if (null !== $this->currentProgressStage && null !== $this->currentStageStartedAt) {
|
||||
$elapsed = microtime(true) - $this->currentStageStartedAt;
|
||||
$this->emitStageSummary($this->currentProgressStage, $elapsed, $this->currentStageExtras);
|
||||
}
|
||||
|
||||
$this->currentProgressStage = null;
|
||||
$this->currentStageStartedAt = null;
|
||||
$this->currentStageExtras = [];
|
||||
}
|
||||
|
||||
private function emitStageSummary(string $stage, float $seconds, array $extra = []): void
|
||||
{
|
||||
$io = $this->getIO();
|
||||
$label = $extra['label'] ?? ucfirst($stage);
|
||||
$modeText = '';
|
||||
if (isset($extra['mode'])) {
|
||||
$modeText = sprintf(' [%s]', $extra['mode']);
|
||||
}
|
||||
|
||||
$io->writeln(sprintf(' |- %s completed in %s%s', $label, $this->formatDuration($seconds), $modeText));
|
||||
}
|
||||
|
||||
private function formatDuration(float $seconds): string
|
||||
{
|
||||
if ($seconds < 1) {
|
||||
return sprintf('%0.3fs', $seconds);
|
||||
}
|
||||
|
||||
$minutes = (int)floor($seconds / 60);
|
||||
$remaining = $seconds - ($minutes * 60);
|
||||
|
||||
if ($minutes === 0) {
|
||||
return sprintf('%0.1fs', $remaining);
|
||||
}
|
||||
|
||||
return sprintf('%dm %0.1fs', $minutes, $remaining);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user