Commit a034c620 authored by Helmut Hummel's avatar Helmut Hummel Committed by Andreas Fernandez
Browse files

[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's avatarcore-ci <typo3@b13.com>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
parent d013c730
......@@ -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",
......
......@@ -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": {
......
......@@ -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.');
}
......
......@@ -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.
......
......@@ -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) . '/';
}
/**
......
......@@ -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",
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment