[BUGFIX] Improve package name resolving#704
Merged
sbuerk merged 3 commits intoJul 23, 2026
Merged
Conversation
Contributor
|
I propose this goes to: |
oliverklee
reviewed
Feb 23, 2026
ComposerPackageManager::removePrefixPaths() strips a list of known path prefixes from a value before that value is looked up as a composer package name or as an extension key. The list contained the plain base name of the project root folder, for example `typo3` for a project checked out into a folder named `typo3`. That entry is a relative single segment prefix, so it also matches the vendor segment of a composer package name. With a project root folder named `typo3` the lookup value `typo3/testing-framework` is reduced to `testing-framework` and `typo3/sysext/core` is reduced to `sysext/core`. Both lookups fail, and functional tests abort with a method call on null, for example in Testbase::linkFrameworkExtensionsToInstance(). The entry had been added together with the relative path handling in getPackageFromPathFallback(), which resolves `../<root>/...` values by prefixing the project root real path and canonicalizing the result. The base name entry is not needed for that, so remove it. Resolves: TYPO3#665 Releases: main, 9, 8
ComposerPackageManager::getPackageInfo() passed every handed over value through resolvePackageName(), which removes known path prefixes and classic mode notation prefixes before the lookup is done. A value that already is a known composer package name does not need that normalization at all, and the normalization can turn it into an unknown value when the vendor segment of the package name matches one of the removed prefixes. Look up the handed over value first and only fall back to the resolved name if it is not a known composer package. Resolves: TYPO3#665 Releases: main, 9, 8
Testbase::linkTestExtensionsToInstance() resolves a configured test extension path with getPackageInfoWithFallback() and symlinks the extension into the test instance using the resolved extension key. Testbase::setUpPackageStates() resolves the very same value with getPackageInfo() instead, which only handles composer package names and extension keys. For a local extension that is not required by the root composer.json that lookup fails, and the code falls back to the directory basename. If the directory name differs from the extension key, the symlink and the PackageStates.php entry end up with different names, and instantiating the package fails with an InvalidPackagePathException. Use getPackageInfoWithFallback() in setUpPackageStates(), so both call sites derive the extension key the same way. Resolves: TYPO3#683 Releases: main, 9, 8
sbuerk
force-pushed
the
bugfix/improve-package-name-resolving
branch
from
July 23, 2026 09:37
e580518 to
c223b05
Compare
sbuerk
approved these changes
Jul 23, 2026
Collaborator
|
Agreed, the footers are Branch |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolving a value to a composer package went through
ComposerPackageManager::resolvePackageName(), which strips a list of knownpath prefixes before the lookup is done. One of those prefixes was the plain
base name of the project root folder.
That entry is a relative single segment prefix, so it also matches the vendor
segment of a composer package name. For a project checked out into a folder
named
typo3, the valuetypo3/testing-frameworkwas reduced totesting-frameworkandtypo3/sysext/coretosysext/core. Both lookups thenfail, and functional tests abort with a method call on null:
This is reproducible with the TYPO3 core itself:
git clone https://github.com/typo3/typo3 cd typo3 Build/Scripts/runTests.sh -s composerInstall Build/Scripts/runTests.sh -s functional typo3/sysext/core/Tests/Functional/Authentication/AbstractUserAuthenticationTest.phpThe same mechanism hits any project whose root folder is named like one of its
composer vendors.
A second, independent defect surfaced while verifying this:
Testbase::linkTestExtensionsToInstance()determines the name of a testextension with
getPackageInfoWithFallback()and symlinks it into the testinstance under the resolved extension key, while
Testbase::setUpPackageStates()determines it withgetPackageInfo(), whichonly handles composer package names and extension keys. For a local extension
that is not required by the root
composer.jsonthat lookup fails and the codefalls back to the directory base name. If the directory name differs from the
extension key,
PackageStates.phppoints to a path that was never created:Changes
The three commits are kept separate and are bisectable:
base name from the prefix list in
removePrefixPaths(). The entry had beenadded together with the relative path handling in
getPackageFromPathFallback(), which resolves../<root>/…values byprefixing the project root real path and canonicalizing the result; the base
name entry is not needed for that. Resolves core functional tests does not work if checkout directory is called 'typo3' #665.
getPackageInfo()now looks upthe handed over value first and only falls back to the resolved name if it is
not a known composer package. A value that already is a known package name
does not need normalization at all. Resolves core functional tests does not work if checkout directory is called 'typo3' #665.
setUpPackageStates()usesgetPackageInfoWithFallback(), the same waylinkTestExtensionsToInstance()already does, so both call sites derive the extension key identically.
Resolves Streamline
ComposerPackageManager->getPackageInfo()usage to support extensions with none matching folder name #683.Tests
Each commit carries its own regression test:
ComposerPackageManagerTest::prepareResolvePackageNameKeepsProjectRootFolderNamePrefix()asserts that
<project-root-folder-name>/some-packageis not rewritten.ComposerPackageManagerTest::knownPackageNameIsNotModifiedBeforeLookup()registers a fixture extension and looks it up by its composer package name.
TestbaseTest::setUpPackageStatesUsesExtensionKeyOfTestExtensionAndNotItsFolderName()builds a minimal test instance, symlinks a fixture extension whose folder name
differs from its extension key, and asserts the written
PackageStates.phpentry. Without commit 3 this test fails with the
InvalidPackagePathExceptionquoted above.All three tests fail against
mainand pass with the respective commit applied.Verification
Run locally on PHP 8.2 (podman):
Additionally verified against a TYPO3 project checkout placed in a folder named
typo3(issue #665) and against a project with a local, non-required extensionpackage whose folder name differs from its extension key (issue #683).
Resolves: #665
Resolves: #683
Releases: main, 9, 8