From a034c6207eca1922804ec186c2da6d55082d63b8 Mon Sep 17 00:00:00 2001 From: Helmut Hummel <typo3@helhum.io> Date: Mon, 13 Sep 2021 18:24:56 +0200 Subject: [PATCH] [BUGFIX] Restrict composer-runtime-api to 2.1 With https://review.typo3.org/c/Packages/TYPO3.CMS/+/71075 usage of InstalledVersions class was introduced. More specifically the install_path of the root package. However install paths of packages are only available in composer-runtime-api 2.1, therefore we need to require this a minimum version. As drive by change the usage of Composer runtime API is encapsulated in the Environment class and path normalisation is put there as well, to not require normalisation for each package. composer req composer-runtime-api:^2.1 composer req composer-runtime-api:^2.1 -d typo3/sysext/core/ --no-update Resolves: #95237 Related: #94996 Related: #95171 Releases: master Change-Id: Ibe8f676830327b1036be8074e0dc38e54743b479 Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/71083 Tested-by: core-ci <typo3@b13.com> Tested-by: Benni Mack <benni@typo3.org> Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de> Reviewed-by: Benni Mack <benni@typo3.org> Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de> --- composer.json | 4 +-- composer.lock | 4 +-- .../Composer/PackageArtifactBuilder.php | 13 +++++---- .../sysext/core/Classes/Core/Environment.php | 27 +++++++++++++++++++ typo3/sysext/core/Classes/Package/Package.php | 7 +++-- typo3/sysext/core/composer.json | 2 +- 6 files changed, 43 insertions(+), 14 deletions(-) diff --git a/composer.json b/composer.json index c22b206bd19c..d49a26ea1b37 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,7 @@ "ext-pcre": "*", "ext-session": "*", "ext-xml": "*", - "composer-runtime-api": "^2.0", + "composer-runtime-api": "^2.1", "bacon/bacon-qr-code": "^2.0", "christian-riesen/base32": "^1.6", "cogpowered/finediff": "~0.3.1", @@ -50,8 +50,8 @@ "egulias/email-validator": "^3.1", "enshrined/svg-sanitize": "^0.14.1", "guzzlehttp/guzzle": "^7.3.0", - "guzzlehttp/psr7": "^1.7.0 || ^2.0", "guzzlehttp/promises": "^1.4.0", + "guzzlehttp/psr7": "^1.7.0 || ^2.0", "nikic/php-parser": "^4.10.4", "phpdocumentor/reflection-docblock": "^5.2", "phpdocumentor/type-resolver": "^1.4", diff --git a/composer.lock b/composer.lock index 994fca3ac938..dfe49e158eb1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e2dcfec64d2bf1cd1df99b52b5c362ca", + "content-hash": "1b0a189cecb7784c25b2a2e33e2de299", "packages": [ { "name": "bacon/bacon-qr-code", @@ -8275,7 +8275,7 @@ "ext-pcre": "*", "ext-session": "*", "ext-xml": "*", - "composer-runtime-api": "^2.0" + "composer-runtime-api": "^2.1" }, "platform-dev": [], "platform-overrides": { diff --git a/typo3/sysext/core/Classes/Composer/PackageArtifactBuilder.php b/typo3/sysext/core/Classes/Composer/PackageArtifactBuilder.php index f05a8edc17b7..2b143f473058 100644 --- a/typo3/sysext/core/Classes/Composer/PackageArtifactBuilder.php +++ b/typo3/sysext/core/Classes/Composer/PackageArtifactBuilder.php @@ -47,6 +47,7 @@ use TYPO3\CMS\Core\Utility\PathUtility; class PackageArtifactBuilder extends PackageManager implements InstallerScript { private Event $event; + private Config $config; /** * Array of package keys that are installed by Composer but have no relation to TYPO3 extension API @@ -78,11 +79,12 @@ class PackageArtifactBuilder extends PackageManager implements InstallerScript public function run(Event $event): bool { $this->event = $event; + $this->config = Config::load($this->event->getComposer(), $this->event->getIO()); $composer = $this->event->getComposer(); $basePath = Config::load($composer)->get('base-dir'); $this->packagesBasePath = $basePath . '/'; foreach ($this->extractPackageMapFromComposer() as [$composerPackage, $path, $extensionKey]) { - $packagePath = PathUtility::sanitizeTrailingSeparator($path ?: $basePath); + $packagePath = PathUtility::sanitizeTrailingSeparator($path); $package = new Package($this, $extensionKey, $packagePath, true); $package->makePathRelative(new Filesystem(), $basePath); $package->getPackageMetaData()->setVersion($composerPackage->getPrettyVersion()); @@ -180,17 +182,18 @@ class PackageArtifactBuilder extends PackageManager implements InstallerScript */ private function handleRootPackage(PackageInterface $rootPackage, string $extensionKey): array { - if ($rootPackage->getType() !== 'typo3-cms-extension' || !file_exists($this->packagesBasePath . 'Resources/Public/')) { - return [$rootPackage, $this->packagesBasePath, $extensionKey]; + $baseDir = $this->config->get('base-dir'); + if ($rootPackage->getType() !== 'typo3-cms-extension' || !file_exists($baseDir . '/Resources/Public/')) { + return [$rootPackage, $baseDir, $extensionKey]; } $composer = $this->event->getComposer(); $typo3ExtensionInstallPath = $composer->getInstallationManager()->getInstaller('typo3-cms-extension')->getInstallPath($rootPackage); $filesystem = new Filesystem(); $filesystem->ensureDirectoryExists(dirname($typo3ExtensionInstallPath)); if (!file_exists($typo3ExtensionInstallPath) && !$filesystem->isSymlinkedDirectory($typo3ExtensionInstallPath)) { - $filesystem->relativeSymlink($this->packagesBasePath, $typo3ExtensionInstallPath); + $filesystem->relativeSymlink($baseDir, $typo3ExtensionInstallPath); } - if (realpath($this->packagesBasePath) !== realpath($typo3ExtensionInstallPath)) { + if (realpath($baseDir) !== realpath($typo3ExtensionInstallPath)) { $this->event->getIO()->warning('The root package is of type "typo3-cms-extension" and has public resources, but could not be linked to typo3conf/ext directory, because target directory already exits.'); } diff --git a/typo3/sysext/core/Classes/Core/Environment.php b/typo3/sysext/core/Classes/Core/Environment.php index 8ce8c9eb3f76..dfe0ac1d5612 100644 --- a/typo3/sysext/core/Classes/Core/Environment.php +++ b/typo3/sysext/core/Classes/Core/Environment.php @@ -17,6 +17,9 @@ declare(strict_types=1); namespace TYPO3\CMS\Core\Core; +use Composer\InstalledVersions; +use TYPO3\CMS\Core\Utility\PathUtility; + /** * This class is initialized once in the SystemEnvironmentBuilder, and can then * be used throughout the application to access common variables @@ -70,6 +73,11 @@ class Environment */ protected static $projectPath; + /** + * @var string + */ + protected static $composerRootPath; + /** * @var string */ @@ -126,6 +134,7 @@ class Environment self::$composerMode = $composerMode; self::$context = $context; self::$projectPath = $projectPath; + self::$composerRootPath = $composerMode ? PathUtility::getCanonicalPath(InstalledVersions::getRootPackage()['install_path']) : ''; self::$publicPath = $publicPath; self::$varPath = $varPath; self::$configPath = $configPath; @@ -181,6 +190,24 @@ class Environment return self::$projectPath; } + /** + * In most cases in composer-mode setups this is the same as project path. + * However since the project path is configurable, the paths may differ. + * In future versions this configurability will go away and this method will be removed. + * This path is only required for some internal path handling regarding package paths until then. + * @internal + * + * @return string The absolute path to the composer root directory without the trailing slash + */ + public static function getComposerRootPath(): string + { + if (self::$composerMode === false) { + throw new \BadMethodCallException('Composer root path is only available in Composer mode', 1631700480); + } + + return self::$composerRootPath; + } + /** * The public web folder where index.php (= the frontend application) is put, without trailing slash. * For non-composer installations, the project path = the public path. diff --git a/typo3/sysext/core/Classes/Package/Package.php b/typo3/sysext/core/Classes/Package/Package.php index be1b7e36ac0c..2b5d2eb97246 100644 --- a/typo3/sysext/core/Classes/Package/Package.php +++ b/typo3/sysext/core/Classes/Package/Package.php @@ -15,12 +15,11 @@ namespace TYPO3\CMS\Core\Package; -use Composer\InstalledVersions; use Composer\Util\Filesystem; +use TYPO3\CMS\Core\Core\Environment; use TYPO3\CMS\Core\Package\Exception\InvalidPackageKeyException; use TYPO3\CMS\Core\Package\Exception\InvalidPackagePathException; use TYPO3\CMS\Core\Package\MetaData\PackageConstraint; -use TYPO3\CMS\Core\Utility\PathUtility; /** * A Package representing the details of an extension and/or a composer package @@ -235,7 +234,7 @@ class Package implements PackageInterface } $this->isRelativePackagePath = false; - return $this->packagePath = PathUtility::getCanonicalPath(InstalledVersions::getRootPackage()['install_path'] . '/' . $this->packagePath) . '/'; + return $this->packagePath = Environment::getComposerRootPath() . '/' . $this->packagePath; } /** @@ -248,7 +247,7 @@ class Package implements PackageInterface public function makePathRelative(Filesystem $filesystem, string $composerRootPath): void { $this->isRelativePackagePath = true; - $this->packagePath = $filesystem->findShortestPath($composerRootPath, $this->packagePath, true); + $this->packagePath = ($composerRootPath . '/') === $this->packagePath ? '' : $filesystem->findShortestPath($composerRootPath, $this->packagePath, true) . '/'; } /** diff --git a/typo3/sysext/core/composer.json b/typo3/sysext/core/composer.json index a45bc7c679a9..30184367c653 100644 --- a/typo3/sysext/core/composer.json +++ b/typo3/sysext/core/composer.json @@ -26,7 +26,7 @@ "ext-pcre": "*", "ext-session": "*", "ext-xml": "*", - "composer-runtime-api": "^2.0", + "composer-runtime-api": "^2.1", "bacon/bacon-qr-code": "^2.0", "christian-riesen/base32": "^1.6", "cogpowered/finediff": "~0.3.1", -- GitLab