mirror of
				https://github.com/getgrav/grav.git
				synced 2025-11-03 20:05:49 +01: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)) {
 | 
			
		||||
            // Use empty placeholders to preserve directory structure without duplicating data.
 | 
			
		||||
            Folder::create($stage);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Folder::create(dirname($stage));
 | 
			
		||||
            Folder::rcopy($live, $stage, true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -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