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);