Repository: humbug/php-scoper (php)

Issue:
Handle the case where Composer's InstalledVersion does not exist
See https://github.com/infection/infection/issues/1770, it may not exist due to a lack of dependencies, not necessarily an outdated Composer version.

Pull request:
fix: Handle the case where the Compoer InstalledVersions.php file is not present
Closes #784

Patch:
diff --git a/Makefile b/Makefile
index d8d214b..5d70669 100644
--- a/Makefile
+++ b/Makefile
@@ -147,7 +147,7 @@ infection: $(COVERAGE_XML) vendor
 include .makefile/e2e.file
 .PHONY: e2e
 e2e: ## Runs end-to-end tests
-e2e: e2e_004 e2e_005 e2e_011 e2e_013 e2e_014 e2e_015 e2e_016 e2e_017 e2e_018 e2e_019 e2e_020 e2e_024 e2e_025 e2e_027 e2e_028 e2e_029 e2e_030 e2e_031 e2e_032 e2e_033 e2e_034 e2e_035
+e2e: e2e_004 e2e_005 e2e_011 e2e_013 e2e_014 e2e_015 e2e_016 e2e_017 e2e_018 e2e_019 e2e_020 e2e_024 e2e_025 e2e_027 e2e_028 e2e_029 e2e_030 e2e_031 e2e_032 e2e_033 e2e_034 e2e_035 e2e_036
 
 .PHONY: blackfire
 blackfire: ## Runs Blackfire profiling
diff --git a/fixtures/set036/bin/greet.php b/fixtures/set036/bin/greet.php
new file mode 100644
index 0000000..ebbe4e6
--- /dev/null
+++ b/fixtures/set036/bin/greet.php
@@ -0,0 +1,13 @@
+<?php
+
+declare(strict_types=1);
+
+if (file_exists(__DIR__.'/../vendor/scoper-autoload.php')) {
+    require_once __DIR__.'/../vendor/scoper-autoload.php';
+} else {
+    require_once __DIR__.'/../vendor/autoload.php';
+}
+
+use Set004\Greeter;
+
+echo (new Greeter())->greet().PHP_EOL;
diff --git a/fixtures/set036/composer.json b/fixtures/set036/composer.json
new file mode 100644
index 0000000..3264b4a
--- /dev/null
+++ b/fixtures/set036/composer.json
@@ -0,0 +1,10 @@
+{
+    "bin": [
+        "bin/greet.php"
+    ],
+    "autoload": {
+        "psr-4": {
+            "Set004\\": "src/"
+        }
+    }
+}
diff --git a/fixtures/set036/expected-output b/fixtures/set036/expected-output
new file mode 100644
index 0000000..cd08755
--- /dev/null
+++ b/fixtures/set036/expected-output
@@ -0,0 +1,1 @@
+Hello world!
diff --git a/fixtures/set036/src/Greeter.php b/fixtures/set036/src/Greeter.php
new file mode 100644
index 0000000..bb11481
--- /dev/null
+++ b/fixtures/set036/src/Greeter.php
@@ -0,0 +1,13 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Set004;
+
+class Greeter
+{
+    public function greet(): string
+    {
+        return 'Hello world!';
+    }
+}
diff --git a/src/Autoload/ScoperAutoloadGenerator.php b/src/Autoload/ScoperAutoloadGenerator.php
index 881131f..e522737 100644
--- a/src/Autoload/ScoperAutoloadGenerator.php
+++ b/src/Autoload/ScoperAutoloadGenerator.php
@@ -94,7 +94,8 @@ final class ScoperAutoloadGenerator
 
                     \$loader = require_once __DIR__.'/autoload.php';
                     // Ensure InstalledVersions is available
-                    require_once __DIR__.'/composer/InstalledVersions.php';
+                    \$installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
+                    if (file_exists(\$installedVersionsPath)) require_once \$installedVersionsPath;
 
                     // Restore the backup
                     if (isset(\$existingComposerAutoloadFiles)) {
@@ -124,7 +125,8 @@ final class ScoperAutoloadGenerator
 
                 \$loader = require_once __DIR__.'/autoload.php';
                 // Ensure InstalledVersions is available
-                require_once __DIR__.'/composer/InstalledVersions.php';
+                \$installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
+                if (file_exists(\$installedVersionsPath)) require_once \$installedVersionsPath;
 
                 // Restore the backup
                 if (isset(\$existingComposerAutoloadFiles)) {


Test patch:
diff --git a/.github/workflows/e2e-tests.yaml b/.github/workflows/e2e-tests.yaml
index b326d37..1b0ee6e 100644
--- a/.github/workflows/e2e-tests.yaml
+++ b/.github/workflows/e2e-tests.yaml
@@ -83,6 +83,7 @@ jobs:
                     - 'e2e_033'
                     - 'e2e_034'
                     - 'e2e_035'
+                    - 'e2e_036'
                 php:
                     - '8.1'
                     - '8.2'
diff --git a/.makefile/e2e.file b/.makefile/e2e.file
index 2d79ac1..9af9391 100644
--- a/.makefile/e2e.file
+++ b/.makefile/e2e.file
@@ -328,6 +328,29 @@ e2e_035: $(PHP_SCOPER_PHAR_BIN) fixtures/set035-composer-files-autoload/vendor f
 	php build/set035-composer-files-autoload/index.php &> build/set035-composer-files-autoload/output || true
 	php build/set035-composer-files-autoload/test.php
 
+.PHONY: e2e_036
+e2e_036: # Runs end-to-end tests for the fixture set e2e_036 — Minimalistic codebase
+e2e_036: $(PHP_SCOPER_PHAR_BIN)
+	# Identical to set004 but without Box
+	rm fixtures/set036/composer.lock || true
+	rm -rf fixtures/set036/vendor || true
+	rm -rf build/set036 || true
+	mkdir -p build/set036
+
+	composer --working-dir=fixtures/set036 dump-autoload
+
+	$(PHP_SCOPER_PHAR) add-prefix . \
+		--working-dir=fixtures/set036 \
+		--output-dir=../../build/set036 \
+		--force \
+		--no-config \
+		--no-interaction \
+		--stop-on-failure
+	composer --working-dir=build/set036 dump-autoload
+
+	php build/set036/bin/greet.php > build/set036/output
+	diff fixtures/set036/expected-output build/set036/output
+
 
 #
 # Rules from files
diff --git a/tests/Autoload/ScoperAutoloadGeneratorTest.php b/tests/Autoload/ScoperAutoloadGeneratorTest.php
index 16ad0c9..789754e 100644
--- a/tests/Autoload/ScoperAutoloadGeneratorTest.php
+++ b/tests/Autoload/ScoperAutoloadGeneratorTest.php
@@ -51,7 +51,8 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                 $loader = require_once __DIR__.'/autoload.php';
                 // Ensure InstalledVersions is available
-                require_once __DIR__.'/composer/InstalledVersions.php';
+                $installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
+                if (file_exists($installedVersionsPath)) require_once $installedVersionsPath;
 
                 // Restore the backup
                 if (isset($existingComposerAutoloadFiles)) {
@@ -85,7 +86,8 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                 $loader = require_once __DIR__.'/autoload.php';
                 // Ensure InstalledVersions is available
-                require_once __DIR__.'/composer/InstalledVersions.php';
+                $installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
+                if (file_exists($installedVersionsPath)) require_once $installedVersionsPath;
 
                 // Restore the backup
                 if (isset($existingComposerAutoloadFiles)) {
@@ -124,7 +126,8 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                 $loader = require_once __DIR__.'/autoload.php';
                 // Ensure InstalledVersions is available
-                require_once __DIR__.'/composer/InstalledVersions.php';
+                $installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
+                if (file_exists($installedVersionsPath)) require_once $installedVersionsPath;
 
                 // Restore the backup
                 if (isset($existingComposerAutoloadFiles)) {
@@ -165,7 +168,8 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                     $loader = require_once __DIR__.'/autoload.php';
                     // Ensure InstalledVersions is available
-                    require_once __DIR__.'/composer/InstalledVersions.php';
+                    $installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
+                    if (file_exists($installedVersionsPath)) require_once $installedVersionsPath;
 
                     // Restore the backup
                     if (isset($existingComposerAutoloadFiles)) {
@@ -215,7 +219,8 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                     $loader = require_once __DIR__.'/autoload.php';
                     // Ensure InstalledVersions is available
-                    require_once __DIR__.'/composer/InstalledVersions.php';
+                    $installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
+                    if (file_exists($installedVersionsPath)) require_once $installedVersionsPath;
 
                     // Restore the backup
                     if (isset($existingComposerAutoloadFiles)) {
@@ -262,7 +267,8 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                 $loader = require_once __DIR__.'/autoload.php';
                 // Ensure InstalledVersions is available
-                require_once __DIR__.'/composer/InstalledVersions.php';
+                $installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
+                if (file_exists($installedVersionsPath)) require_once $installedVersionsPath;
 
                 // Restore the backup
                 if (isset($existingComposerAutoloadFiles)) {
@@ -305,7 +311,8 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                 $loader = require_once __DIR__.'/autoload.php';
                 // Ensure InstalledVersions is available
-                require_once __DIR__.'/composer/InstalledVersions.php';
+                $installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
+                if (file_exists($installedVersionsPath)) require_once $installedVersionsPath;
 
                 // Restore the backup
                 if (isset($existingComposerAutoloadFiles)) {
@@ -355,7 +362,8 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                     $loader = require_once __DIR__.'/autoload.php';
                     // Ensure InstalledVersions is available
-                    require_once __DIR__.'/composer/InstalledVersions.php';
+                    $installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
+                    if (file_exists($installedVersionsPath)) require_once $installedVersionsPath;
 
                     // Restore the backup
                     if (isset($existingComposerAutoloadFiles)) {
@@ -419,7 +427,8 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                 $loader = require_once __DIR__.'/autoload.php';
                 // Ensure InstalledVersions is available
-                require_once __DIR__.'/composer/InstalledVersions.php';
+                $installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
+                if (file_exists($installedVersionsPath)) require_once $installedVersionsPath;
 
                 // Restore the backup
                 if (isset($existingComposerAutoloadFiles)) {
@@ -459,7 +468,8 @@ class ScoperAutoloadGeneratorTest extends TestCase
 
                     $loader = require_once __DIR__.'/autoload.php';
                     // Ensure InstalledVersions is available
-                    require_once __DIR__.'/composer/InstalledVersions.php';
+                    $installedVersionsPath = __DIR__.'/composer/InstalledVersions.php';
+                    if (file_exists($installedVersionsPath)) require_once $installedVersionsPath;
 
                     // Restore the backup
                     if (isset($existingComposerAutoloadFiles)) {