Skip to content

Commit

Permalink
[BUGFIX] Generate correct asset symlinks on Windows
Browse files Browse the repository at this point in the history
This patch fixes two issues when generating symlinks to the public
extension resources (Public/Resources) into the _assets folder during
Composer installation.

First, directory symlinks can't be created the same way on Windows as
on Unix platforms. The creation requires elevated rights, and the
required command is named differently as well. Junctions should be used
on Windows instead, because they do not need elevated privileges to be
created.

When installing a TYPO3 extension via Composer, its Resources/Public
folder is getting symlinked to the publicly accessible _assets folder.
Until now, this process only used the Unix specific functions provided
by Composer. It did not create any symlinks on Windows based
installations, without generating any error message.

This patch adds the same checks and platform-specific functions used by
Composer when symlinking packages from a local path repository.

The second issue that has been addressed is the naming of the symlinks
themselves. When a Resources/Public directory is symlinked into the
_assets folder, the symlink will be named using an md5 hash based on
parts of the extension's installation path on the filesystem. During
Composer installation, this relative path is derived from the
absolute path provided by Composer. As Windows uses a different default
path separator (backslash) compared to Unix (forward slash), the
relative path will be different between both platforms, resulting in a
different md5 hash being generated.

Absolute path on Unix:
/path/to/typo3/vendor/mycompany/myext

Absolute path on Windows:
C:\path\to\typo3\vendor/mycompany/myext

Relative path to be used for the hash on Unix:
/vendor/mycompany/myext

Relative path to be used for the hash on Windows:
\vendor/mycompany/myext

If an uri into the _assets folder is to be generated in either frontend
or backend, the md5 hash will be always be generated by using forward
slashes, resulting in incorrect links on Windows installations.

This difference has been solved by replacing all backslashes in the
absolute extension installation path into forward slashes on Windows
installations, so the symlink will be named correctly from the
beginning.

Resolves: #98434
Resolves: #98447
Releases: main, 12.4, 11.5
Change-Id: I221eb538312302a7af4f7c3010c9982922f1c6ce
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/80688
Tested-by: Stefan B�rk <stefan@buerk.tech>
Tested-by: core-ci <typo3@b13.com>
Reviewed-by: Stefan B�rk <stefan@buerk.tech>
  • Loading branch information
Physikbuddha authored and sbuerk committed Aug 30, 2023
1 parent 1d84179 commit f10914e
Showing 1 changed file with 6 additions and 1 deletion.
Expand Up @@ -21,6 +21,7 @@
use Composer\Repository\PlatformRepository;
use Composer\Script\Event;
use Composer\Util\Filesystem;
use Composer\Util\Platform;
use TYPO3\CMS\Composer\Plugin\Config;
use TYPO3\CMS\Composer\Plugin\Core\InstallerScript;
use TYPO3\CMS\Composer\Plugin\Util\ExtensionKeyResolver;
Expand All @@ -32,6 +33,7 @@
use TYPO3\CMS\Core\Package\Package;
use TYPO3\CMS\Core\Package\PackageManager;
use TYPO3\CMS\Core\Service\DependencyOrderingService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility;

/**
Expand Down Expand Up @@ -160,6 +162,7 @@ private function extractPackageMapFromComposer(): array
function (array $packageAndPath) use ($rootPackage, &$usedExtensionKeys) {
[$composerPackage, $packagePath] = $packageAndPath;
$packageName = $composerPackage->getName();
$packagePath = GeneralUtility::fixWindowsFilePath($packagePath);
try {
$extensionKey = ExtensionKeyResolver::resolve($composerPackage);
} catch (\Throwable $e) {
Expand Down Expand Up @@ -268,7 +271,9 @@ private function publishResources(array $installedTypo3Packages): void
[$relativePrefix] = explode('Resources/Public', $relativePath);
$publicResourcesPath = $fileSystem->normalizePath($this->config->get('web-dir') . '/_assets/' . md5($relativePrefix));
$fileSystem->ensureDirectoryExists(dirname($publicResourcesPath));
if (!$fileSystem->isSymlinkedDirectory($publicResourcesPath)) {
if (Platform::isWindows() && !$fileSystem->isJunction($publicResourcesPath)) {
$fileSystem->junction($fileSystemResourcesPath, $publicResourcesPath);
} elseif (!$fileSystem->isSymlinkedDirectory($publicResourcesPath)) {
$fileSystem->relativeSymlink($fileSystemResourcesPath, $publicResourcesPath);
}
}
Expand Down

0 comments on commit f10914e

Please sign in to comment.