diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index 01148583a..bdcabcd80 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -467,7 +467,11 @@ class InstallationManager { $package = $operation->getPackage(); $installer = $this->getInstaller($package->getType()); - $promise = $installer->install($repo, $package); + if ($installer instanceof PluginInstaller) { + $promise = $installer->install($repo, $package, $this); + } else { + $promise = $installer->install($repo, $package); + } $this->markForNotification($package); return $promise; @@ -489,7 +493,11 @@ class InstallationManager if ($initialType === $targetType) { $installer = $this->getInstaller($initialType); - $promise = $installer->update($repo, $initial, $target); + if ($installer instanceof PluginInstaller) { + $promise = $installer->update($repo, $initial, $target, $this); + } else { + $promise = $installer->update($repo, $initial, $target); + } $this->markForNotification($target); } else { $promise = $this->getInstaller($initialType)->uninstall($repo, $initial); @@ -497,8 +505,12 @@ class InstallationManager $promise = \React\Promise\resolve(); } + $installManager = $this; $installer = $this->getInstaller($targetType); - $promise->then(function () use ($installer, $repo, $target) { + $promise->then(function () use ($installer, $repo, $target, $installManager) { + if ($installer instanceof PluginInstaller) { + return $installer->install($repo, $target, $installManager); + } return $installer->install($repo, $target); }); } diff --git a/src/Composer/Installer/PluginInstaller.php b/src/Composer/Installer/PluginInstaller.php index ba009ab1b..d13364cef 100644 --- a/src/Composer/Installer/PluginInstaller.php +++ b/src/Composer/Installer/PluginInstaller.php @@ -17,6 +17,7 @@ use Composer\IO\IOInterface; use Composer\Repository\InstalledRepositoryInterface; use Composer\Package\PackageInterface; use Composer\Util\Filesystem; +use Composer\Installer\InstallationManager; use React\Promise\PromiseInterface; /** @@ -62,7 +63,7 @@ class PluginInstaller extends LibraryInstaller /** * {@inheritDoc} */ - public function install(InstalledRepositoryInterface $repo, PackageInterface $package) + public function install(InstalledRepositoryInterface $repo, PackageInterface $package, InstallationManager $installationManager = null) { $promise = parent::install($repo, $package); if (!$promise instanceof PromiseInterface) { @@ -72,8 +73,11 @@ class PluginInstaller extends LibraryInstaller $pluginManager = $this->composer->getPluginManager(); $self = $this; - return $promise->then(function () use ($self, $pluginManager, $package, $repo) { + return $promise->then(function () use ($self, $pluginManager, $package, $repo, $installationManager) { try { + if ($installationManager) { + $self->updateInstalledVersions($repo, $installationManager); + } $pluginManager->registerPackage($package, true); } catch (\Exception $e) { $self->rollbackInstall($e, $repo, $package); @@ -84,7 +88,7 @@ class PluginInstaller extends LibraryInstaller /** * {@inheritDoc} */ - public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) + public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target, InstallationManager $installationManager = null) { $promise = parent::update($repo, $initial, $target); if (!$promise instanceof PromiseInterface) { @@ -94,9 +98,12 @@ class PluginInstaller extends LibraryInstaller $pluginManager = $this->composer->getPluginManager(); $self = $this; - return $promise->then(function () use ($self, $pluginManager, $initial, $target, $repo) { + return $promise->then(function () use ($self, $pluginManager, $initial, $target, $repo, $installationManager) { try { $pluginManager->deactivatePackage($initial, true); + if ($installationManager) { + $self->updateInstalledVersions($repo, $installationManager); + } $pluginManager->registerPackage($target, true); } catch (\Exception $e) { $self->rollbackInstall($e, $repo, $target); @@ -121,4 +128,16 @@ class PluginInstaller extends LibraryInstaller parent::uninstall($repo, $package); throw $e; } + + /** + * TODO v3 should make this private once we can drop PHP 5.3 support + * @private + */ + public function updateInstalledVersions(InstalledRepositoryInterface $repo, InstallationManager $installationManager) + { + $versions = $repo->generateInstalledVersions($installationManager); + if ($versions) { + \Composer\InstalledVersions::reload($versions); + } + } } diff --git a/src/Composer/Repository/FilesystemRepository.php b/src/Composer/Repository/FilesystemRepository.php index 2823e6ec9..5c5eb33da 100644 --- a/src/Composer/Repository/FilesystemRepository.php +++ b/src/Composer/Repository/FilesystemRepository.php @@ -123,100 +123,110 @@ class FilesystemRepository extends WritableArrayRepository $this->file->write($data); + if ($this->dumpVersions) { - $versions = array('versions' => array()); - $packages = $this->getPackages(); - $packages[] = $rootPackage = $this->rootPackage; - while ($rootPackage instanceof AliasPackage) { - $rootPackage = $rootPackage->getAliasOf(); - $packages[] = $rootPackage; - } + $versions = $this->generateInstalledVersions($installationManager); - // add real installed packages - foreach ($packages as $package) { - if ($package instanceof AliasPackage) { - continue; - } + $fs->filePutContentsIfModified($repoDir.'/installed.php', 'filePutContentsIfModified($repoDir.'/InstalledVersions.php', $installedVersionsClass); - $reference = null; - if ($package->getInstallationSource()) { - $reference = $package->getInstallationSource() === 'source' ? $package->getSourceReference() : $package->getDistReference(); - } - if (null === $reference) { - $reference = ($package->getSourceReference() ?: $package->getDistReference()) ?: null; - } + \Composer\InstalledVersions::reload($versions); + } + } - $versions['versions'][$package->getName()] = array( - 'pretty_version' => $package->getPrettyVersion(), - 'version' => $package->getVersion(), - 'aliases' => array(), - 'reference' => $reference, - ); - if ($package instanceof RootPackageInterface) { - $versions['root'] = $versions['versions'][$package->getName()]; - $versions['root']['name'] = $package->getName(); - } + /** + * @return ?array + * @internal + */ + public function generateInstalledVersions(InstallationManager $installationManager) + { + if (!$this->dumpVersions) { + return null; + } + + $versions = array('versions' => array()); + $packages = $this->getPackages(); + $packages[] = $rootPackage = $this->rootPackage; + while ($rootPackage instanceof AliasPackage) { + $rootPackage = $rootPackage->getAliasOf(); + $packages[] = $rootPackage; + } + + // add real installed packages + foreach ($packages as $package) { + if ($package instanceof AliasPackage) { + continue; } - // add provided/replaced packages - foreach ($packages as $package) { - foreach ($package->getReplaces() as $replace) { - // exclude platform replaces as when they are really there we can not check for their presence - if (PlatformRepository::isPlatformPackage($replace->getTarget())) { - continue; - } - $replaced = $replace->getPrettyConstraint(); - if ($replaced === 'self.version') { - $replaced = $package->getPrettyVersion(); - } - if (!isset($versions['versions'][$replace->getTarget()]['replaced']) || !in_array($replaced, $versions['versions'][$replace->getTarget()]['replaced'], true)) { - $versions['versions'][$replace->getTarget()]['replaced'][] = $replaced; - } + $reference = null; + if ($package->getInstallationSource()) { + $reference = $package->getInstallationSource() === 'source' ? $package->getSourceReference() : $package->getDistReference(); + } + if (null === $reference) { + $reference = ($package->getSourceReference() ?: $package->getDistReference()) ?: null; + } + + $versions['versions'][$package->getName()] = array( + 'pretty_version' => $package->getPrettyVersion(), + 'version' => $package->getVersion(), + 'aliases' => array(), + 'reference' => $reference, + ); + if ($package instanceof RootPackageInterface) { + $versions['root'] = $versions['versions'][$package->getName()]; + $versions['root']['name'] = $package->getName(); + } + } + + // add provided/replaced packages + foreach ($packages as $package) { + foreach ($package->getReplaces() as $replace) { + // exclude platform replaces as when they are really there we can not check for their presence + if (PlatformRepository::isPlatformPackage($replace->getTarget())) { + continue; } - foreach ($package->getProvides() as $provide) { - // exclude platform provides as when they are really there we can not check for their presence - if (PlatformRepository::isPlatformPackage($provide->getTarget())) { - continue; - } - $provided = $provide->getPrettyConstraint(); - if ($provided === 'self.version') { - $provided = $package->getPrettyVersion(); - } - if (!isset($versions['versions'][$provide->getTarget()]['provided']) || !in_array($provided, $versions['versions'][$provide->getTarget()]['provided'], true)) { - $versions['versions'][$provide->getTarget()]['provided'][] = $provided; - } + $replaced = $replace->getPrettyConstraint(); + if ($replaced === 'self.version') { + $replaced = $package->getPrettyVersion(); + } + if (!isset($versions['versions'][$replace->getTarget()]['replaced']) || !in_array($replaced, $versions['versions'][$replace->getTarget()]['replaced'], true)) { + $versions['versions'][$replace->getTarget()]['replaced'][] = $replaced; } } - - // add aliases - foreach ($packages as $package) { - if (!$package instanceof AliasPackage) { + foreach ($package->getProvides() as $provide) { + // exclude platform provides as when they are really there we can not check for their presence + if (PlatformRepository::isPlatformPackage($provide->getTarget())) { continue; } - $versions['versions'][$package->getName()]['aliases'][] = $package->getPrettyVersion(); - if ($package instanceof RootPackageInterface) { - $versions['root']['aliases'][] = $package->getPrettyVersion(); + $provided = $provide->getPrettyConstraint(); + if ($provided === 'self.version') { + $provided = $package->getPrettyVersion(); + } + if (!isset($versions['versions'][$provide->getTarget()]['provided']) || !in_array($provided, $versions['versions'][$provide->getTarget()]['provided'], true)) { + $versions['versions'][$provide->getTarget()]['provided'][] = $provided; } } + } - ksort($versions['versions']); - ksort($versions); - - $fs->filePutContentsIfModified($repoDir.'/installed.php', 'filePutContentsIfModified($repoDir.'/InstalledVersions.php', $installedVersionsClass); - - // make sure the InstalledVersions class is loaded and has the latest state - // not using the autoloader here to avoid loading the one from Composer's vendor dir - if (!class_exists('Composer\InstalledVersions', false)) { - include $repoDir.'/InstalledVersions.php'; - } else { - \Composer\InstalledVersions::reload($versions); + // add aliases + foreach ($packages as $package) { + if (!$package instanceof AliasPackage) { + continue; + } + $versions['versions'][$package->getName()]['aliases'][] = $package->getPrettyVersion(); + if ($package instanceof RootPackageInterface) { + $versions['root']['aliases'][] = $package->getPrettyVersion(); } } + + ksort($versions['versions']); + ksort($versions); + + return $versions; } }