Skip to content

Commit f2d8d11

Browse files
committed
add suggested fix from copilot
1 parent 28d4f2e commit f2d8d11

File tree

1 file changed

+31
-2
lines changed

1 file changed

+31
-2
lines changed

system/Autoloader/Autoloader.php

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ class Autoloader
9393
*/
9494
protected $helpers = ['url'];
9595

96+
/**
97+
* Track whether Composer namespaces have been loaded to prevent
98+
* re-loading in parallel test execution contexts.
99+
*/
100+
private bool $composerNamespacesLoaded = false;
101+
96102
public function __construct(private readonly string $composerPath = COMPOSER_PATH)
97103
{
98104
}
@@ -109,6 +115,8 @@ public function initialize(Autoload $config, Modules $modules)
109115
$this->classmap = [];
110116
$this->files = [];
111117

118+
$this->composerNamespacesLoaded = false;
119+
112120
// We have to have one or the other, though we don't enforce the need
113121
// to have both present in order to work.
114122
if ($config->psr4 === [] && $config->classmap === []) {
@@ -150,9 +158,11 @@ private function loadComposerAutoloader(Modules $modules): void
150158
$composer = include $this->composerPath;
151159

152160
// Should we load through Composer's namespaces, also?
153-
if ($modules->discoverInComposer) {
161+
// Guard against repeated loading in parallel execution environments
162+
if ($modules->discoverInComposer && ! $this->composerNamespacesLoaded) {
154163
$composerPackages = $modules->composerPackages;
155164
$this->loadComposerNamespaces($composer, $composerPackages ?? []);
165+
$this->composerNamespacesLoaded = true;
156166
}
157167

158168
unset($composer);
@@ -371,6 +381,24 @@ public function sanitizeFilename(string $filename): string
371381
return $cleanFilename;
372382
}
373383

384+
/**
385+
* Convert a path to absolute path if it isn't already.
386+
* Prevents issues with relative paths in parallel execution.
387+
*/
388+
private function makePathAbsolute(string $path): string
389+
{
390+
if (str_starts_with($path, '/') || (strlen($path) > 1 && $path[1] === ':')) {
391+
return $path; // Already absolute
392+
}
393+
394+
// Make relative to vendor directory
395+
if (defined('VENDORPATH')) {
396+
return VENDORPATH . ltrim($path, '/\\');
397+
}
398+
399+
return $path;
400+
}
401+
374402
/**
375403
* @param array{only?: list<string>, exclude?: list<string>} $composerPackages
376404
*/
@@ -441,7 +469,8 @@ private function loadComposerNamespaces(ClassLoader $composer, array $composerPa
441469

442470
if ($add) {
443471
// Composer stores namespaces with trailing slash. We don't.
444-
$newPaths[rtrim($namespace, '\\ ')] = $srcPaths;
472+
// Ensure all paths are absolute to prevent issues in parallel execution
473+
$newPaths[rtrim($namespace, '\\ ')] = array_map($this->makePathAbsolute(...), $srcPaths);
445474
}
446475
}
447476

0 commit comments

Comments
 (0)