Make sure the plugins can use InstalledVersions to introspect themselves when being activated right after initial install

main
Jordi Boggiano 3 years ago
parent d4073a40f9
commit cf324ee664
No known key found for this signature in database
GPG Key ID: 7BBD42C429EC80BC

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

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

@ -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', '<?php return '.var_export($versions, true).';'."\n");
$installedVersionsClass = file_get_contents(__DIR__.'/../InstalledVersions.php');
// while not strictly needed since https://github.com/composer/composer/pull/9635 - we keep this for BC
// and overall broader compatibility with people that may not use Composer's ClassLoader. They can
// simply include InstalledVersions.php manually and have it working in a basic way.
$installedVersionsClass = str_replace('private static $installed;', 'private static $installed = '.var_export($versions, true).';', $installedVersionsClass);
$fs->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', '<?php return '.var_export($versions, true).';'."\n");
$installedVersionsClass = file_get_contents(__DIR__.'/../InstalledVersions.php');
// while not strictly needed since https://github.com/composer/composer/pull/9635 - we keep this for BC
// and overall broader compatibility with people that may not use Composer's ClassLoader. They can
// simply include InstalledVersions.php manually and have it working in a basic way.
$installedVersionsClass = str_replace('private static $installed;', 'private static $installed = '.var_export($versions, true).';', $installedVersionsClass);
$fs->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;
}
}

Loading…
Cancel
Save