From 3a48e393756e8b0387925aa327f45a30128b4556 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 14 May 2023 13:46:46 +0200 Subject: [PATCH] Return null for install path for metapackages instead of an empty path which then resolves to the root package's path (#11455) Fixes #11389 --- doc/articles/custom-installers.md | 5 +-- src/Composer/Autoload/AutoloadGenerator.php | 6 ++- src/Composer/Command/ShowCommand.php | 38 ++++++++++++++----- src/Composer/Command/StatusCommand.php | 3 ++ src/Composer/Command/ValidateCommand.php | 3 ++ .../Installer/InstallationManager.php | 4 +- src/Composer/Installer/InstallerInterface.php | 2 +- src/Composer/Installer/LibraryInstaller.php | 2 + .../Installer/MetapackageInstaller.php | 4 +- src/Composer/Installer/ProjectInstaller.php | 2 +- src/Composer/Package/Locker.php | 6 ++- src/Composer/Plugin/PluginManager.php | 11 ++++-- 12 files changed, 63 insertions(+), 23 deletions(-) diff --git a/doc/articles/custom-installers.md b/doc/articles/custom-installers.md index 6e2ad8670..28d121297 100644 --- a/doc/articles/custom-installers.md +++ b/doc/articles/custom-installers.md @@ -157,9 +157,8 @@ source for the exact signature): invoked with the update argument. * **uninstall()**, here you can determine the actions that need to be executed when the package needs to be removed. -* **getInstallPath()**, this method should return the location where the - package is to be installed, _relative from the location of composer.json._ - The path _must not end with a slash._ +* **getInstallPath()**, this method should return the absolute path where the + package is to be installed. The path _must not end with a slash._ Example: diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index a16e6b67b..0ff95e042 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -485,10 +485,14 @@ EOF; continue; } $this->validatePackage($package); + $installPath = $installationManager->getInstallPath($package); + if ($installPath === null) { + continue; + } $packageMap[] = [ $package, - $installationManager->getInstallPath($package), + $installPath, ]; } diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 5c07b4605..d7bd2c75a 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -332,7 +332,12 @@ EOT } if ($input->getOption('path')) { $io->write($package->getName(), false); - $io->write(' ' . strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n")); + $path = $composer->getInstallationManager()->getInstallPath($package); + if (is_string($path)) { + $io->write(' ' . strtok(realpath($path), "\r\n")); + } else { + $io->write(' null'); + } return $exitCode; } @@ -509,7 +514,12 @@ EOT $packageViewData['description'] = $package->getDescription(); } if ($writePath) { - $packageViewData['path'] = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n"); + $path = $composer->getInstallationManager()->getInstallPath($package); + if (is_string($path)) { + $packageViewData['path'] = strtok(realpath($path), "\r\n"); + } else { + $packageViewData['path'] = null; + } } $packageIsAbandoned = false; @@ -635,7 +645,7 @@ EOT } /** - * @param array $packages + * @param array $packages */ private function printPackages(IOInterface $io, array $packages, string $indent, bool $writeVersion, bool $writeLatest, bool $writeDescription, int $width, int $versionLength, int $nameLength, int $latestLength): void { @@ -669,8 +679,8 @@ EOT } $io->write(' ' . $description, false); } - if (isset($package['path'])) { - $io->write(' ' . $package['path'], false); + if (array_key_exists('path', $package)) { + $io->write(' '.(is_string($package['path']) ? $package['path'] : 'null'), false); } $io->write(''); if (isset($package['warning'])) { @@ -802,7 +812,12 @@ EOT $io->write('source : ' . sprintf('[%s] %s %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference())); $io->write('dist : ' . sprintf('[%s] %s %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference())); if ($installedRepo->hasPackage($package)) { - $io->write('path : ' . sprintf('%s', realpath($this->requireComposer()->getInstallationManager()->getInstallPath($package)))); + $path = $this->requireComposer()->getInstallationManager()->getInstallPath($package); + if (is_string($path)) { + $io->write('path : ' . realpath($path)); + } else { + $io->write('path : null'); + } } $io->write('names : ' . implode(', ', $package->getNames())); @@ -958,9 +973,14 @@ EOT } if ($installedRepo->hasPackage($package)) { - $path = realpath($this->requireComposer()->getInstallationManager()->getInstallPath($package)); - if ($path !== false) { - $json['path'] = $path; + $path = $this->requireComposer()->getInstallationManager()->getInstallPath($package); + if (is_string($path)) { + $path = realpath($path); + if ($path !== false) { + $json['path'] = $path; + } + } else { + $json['path'] = null; } } diff --git a/src/Composer/Command/StatusCommand.php b/src/Composer/Command/StatusCommand.php index 42c20fcef..780f70031 100644 --- a/src/Composer/Command/StatusCommand.php +++ b/src/Composer/Command/StatusCommand.php @@ -99,6 +99,9 @@ EOT foreach ($installedRepo->getCanonicalPackages() as $package) { $downloader = $dm->getDownloaderForPackage($package); $targetDir = $im->getInstallPath($package); + if ($targetDir === null) { + continue; + } if ($downloader instanceof ChangeReportInterface) { if (is_link($targetDir)) { diff --git a/src/Composer/Command/ValidateCommand.php b/src/Composer/Command/ValidateCommand.php index 92ff158af..a5d1e9c46 100644 --- a/src/Composer/Command/ValidateCommand.php +++ b/src/Composer/Command/ValidateCommand.php @@ -112,6 +112,9 @@ EOT $localRepo = $composer->getRepositoryManager()->getLocalRepository(); foreach ($localRepo->getPackages() as $package) { $path = $composer->getInstallationManager()->getInstallPath($package); + if (null === $path) { + continue; + } $file = $path . '/composer.json'; if (is_dir($path) && file_exists($file)) { [$errors, $publishErrors, $warnings] = $validator->validate($file, $checkAll, $checkVersion); diff --git a/src/Composer/Installer/InstallationManager.php b/src/Composer/Installer/InstallationManager.php index 0fcd462a1..d171139e9 100644 --- a/src/Composer/Installer/InstallationManager.php +++ b/src/Composer/Installer/InstallationManager.php @@ -549,9 +549,9 @@ class InstallationManager /** * Returns the installation path of a package * - * @return string path + * @return string|null absolute path to install to, which does not end with a slash, or null if the package does not have anything installed on disk */ - public function getInstallPath(PackageInterface $package): string + public function getInstallPath(PackageInterface $package): ?string { $installer = $this->getInstaller($package->getType()); diff --git a/src/Composer/Installer/InstallerInterface.php b/src/Composer/Installer/InstallerInterface.php index bfa73e18d..bdf42ec42 100644 --- a/src/Composer/Installer/InstallerInterface.php +++ b/src/Composer/Installer/InstallerInterface.php @@ -112,7 +112,7 @@ interface InstallerInterface /** * Returns the absolute installation path of a package. * - * @return string absolute path to install to, which MUST not end with a slash + * @return string|null absolute path to install to, which MUST not end with a slash, or null if the package does not have anything installed on disk */ public function getInstallPath(PackageInterface $package); } diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index 8fa39bf1e..d87c6e3dc 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -227,6 +227,8 @@ class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface /** * @inheritDoc + * + * @return string */ public function getInstallPath(PackageInterface $package) { diff --git a/src/Composer/Installer/MetapackageInstaller.php b/src/Composer/Installer/MetapackageInstaller.php index 952993e58..f61a537fb 100644 --- a/src/Composer/Installer/MetapackageInstaller.php +++ b/src/Composer/Installer/MetapackageInstaller.php @@ -124,9 +124,11 @@ class MetapackageInstaller implements InstallerInterface /** * @inheritDoc + * + * @return null */ public function getInstallPath(PackageInterface $package) { - return ''; + return null; } } diff --git a/src/Composer/Installer/ProjectInstaller.php b/src/Composer/Installer/ProjectInstaller.php index 3ee3aceaf..ccf439bfa 100644 --- a/src/Composer/Installer/ProjectInstaller.php +++ b/src/Composer/Installer/ProjectInstaller.php @@ -115,7 +115,7 @@ class ProjectInstaller implements InstallerInterface /** * Returns the installation path of a package * - * @return string path + * @return string configured install path */ public function getInstallPath(PackageInterface $package): string { diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index c58947014..f085e5c41 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -473,7 +473,11 @@ class Locker return null; } - $path = realpath($this->installationManager->getInstallPath($package)); + $path = $this->installationManager->getInstallPath($package); + if ($path === null) { + return null; + } + $path = realpath($path); $sourceType = $package->getSourceType(); $datetime = null; diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 65c83c17b..731a5aba0 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -236,8 +236,11 @@ class PluginManager continue; } - $downloadPath = $this->getInstallPath($autoloadPackage, $globalRepo && $globalRepo->hasPackage($autoloadPackage)); - $autoloads[] = [$autoloadPackage, $downloadPath]; + $installPath = $this->getInstallPath($autoloadPackage, $globalRepo && $globalRepo->hasPackage($autoloadPackage)); + if ($installPath === null) { + continue; + } + $autoloads[] = [$autoloadPackage, $installPath]; } $map = $generator->parseAutoloads($autoloads, $rootPackage); @@ -524,9 +527,9 @@ class PluginManager * * @param bool $global Whether this is a global package * - * @return string Install path + * @return string|null Install path */ - private function getInstallPath(PackageInterface $package, bool $global = false): string + private function getInstallPath(PackageInterface $package, bool $global = false): ?string { if (!$global) { return $this->composer->getInstallationManager()->getInstallPath($package);