diff --git a/system/src/Grav/Console/Gpm/InstallCommand.php b/system/src/Grav/Console/Gpm/InstallCommand.php index e4fbbfe12..cf98d4bf6 100644 --- a/system/src/Grav/Console/Gpm/InstallCommand.php +++ b/system/src/Grav/Console/Gpm/InstallCommand.php @@ -51,6 +51,8 @@ class InstallCommand extends GpmCommand protected $demo_processing = []; /** @var string */ protected $all_yes; + /** @var array */ + protected $requested_versions = []; /** * @return void @@ -81,7 +83,7 @@ class InstallCommand extends GpmCommand ->addArgument( 'package', InputArgument::IS_ARRAY | InputArgument::REQUIRED, - 'Package(s) to install. Use "bin/gpm index" to list packages. Use "bin/gpm direct-install" to install a specific version' + 'Package(s) to install. Use "bin/gpm index" to list packages. Append :version to install a specific version (e.g., typhoon:2.4.8)' ) ->setDescription('Performs the installation of plugins and themes') ->setHelp('The install command allows to install plugins and themes'); @@ -121,6 +123,18 @@ class InstallCommand extends GpmCommand $this->destination = realpath($input->getOption('destination')); $packages = array_map('strtolower', $input->getArgument('package')); + + // Parse package:version syntax (e.g., typhoon:2.4.8) + $this->requested_versions = []; + foreach ($packages as &$package) { + if (str_contains($package, ':')) { + [$slug, $version] = explode(':', $package, 2); + $package = $slug; + $this->requested_versions[$slug] = ltrim($version, 'v'); + } + } + unset($package); + $this->data = $this->gpm->findPackages($packages); $this->loadLocalConfig(); @@ -528,6 +542,43 @@ class InstallCommand extends GpmCommand { $io = $this->getIO(); + // Handle specific version request (e.g., typhoon:2.4.8) + $requestedVersion = $this->requested_versions[$package->slug] ?? null; + if ($requestedVersion) { + $changelog = $package->getChangelog(); + $versionValid = version_compare($package->version, $requestedVersion, '=='); + + if (!$versionValid && $changelog) { + foreach ($changelog as $changelogVersion => $entry) { + preg_match("/[\w\-.]+/", (string) $changelogVersion, $cleanVersion); + if ($cleanVersion && version_compare($cleanVersion[0], $requestedVersion, '==')) { + $versionValid = true; + break; + } + } + } + + if (!$versionValid) { + $io->writeln("Version {$requestedVersion} not found for {$package->name}"); + if ($changelog) { + $versions = []; + foreach ($changelog as $v => $entry) { + preg_match("/[\w\-.]+/", (string) $v, $clean); + if ($clean) { + $versions[] = $clean[0]; + } + } + $io->writeln('Known versions: ' . implode(', ', $versions) . ''); + } + $io->newLine(); + return false; + } + + // Override version and download URL for the specific version + $package->zipball_url = "https://getgrav.org/download/{$package->package_type}/{$package->slug}/{$requestedVersion}"; + $package->version = $requestedVersion; + } + $version = $package->available ?? $package->version; $license = Licenses::get($package->slug);