From 0184530368ca95c13c8ee2d6305dbae1f15057ee Mon Sep 17 00:00:00 2001
From: phenaproxima <phenaproxima@205645.no-reply.drupal.org>
Date: Fri, 21 Jan 2022 19:02:49 +0000
Subject: [PATCH] Issue #3259822 by phenaproxima: ComposerUtility should use
 the installed/local repository to get package info

---
 package_manager/src/ComposerUtility.php       | 26 +++++++++-------
 .../vendor/composer/installed.json            | 15 ++++++++++
 .../vendor/composer/installed.json            | 22 ++++++++++++++
 .../fake-site/vendor/composer/installed.json  | 30 +++++++++++++++++++
 .../composer/installed.json}                  | 10 ++++---
 .../composer/installed.json}                  | 10 +++++--
 .../no_core_requirements/composer.lock        |  4 ---
 .../no_core_requirements/vendor/.gitkeep      |  0
 .../vendor/composer/installed.json            |  3 ++
 .../composer/installed.json}                  | 10 +++++--
 .../composer/installed.json}                  | 10 +++++--
 .../composer/installed.json}                  | 10 +++++--
 .../composer/installed.json}                  |  8 +++--
 .../composer/installed.json}                  |  9 ++++--
 .../composer/installed.json}                  |  9 ++++--
 .../StagedDatabaseUpdateValidatorTest.php     |  2 ++
 .../StagedProjectsValidatorTest.php           | 16 ++--------
 17 files changed, 141 insertions(+), 53 deletions(-)
 create mode 100644 package_manager/tests/fixtures/distro_core/vendor/composer/installed.json
 create mode 100644 package_manager/tests/fixtures/distro_core_recommended/vendor/composer/installed.json
 create mode 100644 tests/fixtures/fake-site/vendor/composer/installed.json
 rename tests/fixtures/project_staged_validation/new_project_added/active/{composer.lock => vendor/composer/installed.json} (88%)
 rename tests/fixtures/project_staged_validation/new_project_added/staged/{composer.lock => vendor/composer/installed.json} (87%)
 delete mode 100644 tests/fixtures/project_staged_validation/no_core_requirements/composer.lock
 delete mode 100644 tests/fixtures/project_staged_validation/no_core_requirements/vendor/.gitkeep
 create mode 100644 tests/fixtures/project_staged_validation/no_core_requirements/vendor/composer/installed.json
 rename tests/fixtures/project_staged_validation/no_errors/active/{composer.lock => vendor/composer/installed.json} (90%)
 rename tests/fixtures/project_staged_validation/no_errors/staged/{composer.lock => vendor/composer/installed.json} (90%)
 rename tests/fixtures/project_staged_validation/project_removed/active/{composer.lock => vendor/composer/installed.json} (88%)
 rename tests/fixtures/project_staged_validation/project_removed/staged/{composer.lock => vendor/composer/installed.json} (81%)
 rename tests/fixtures/project_staged_validation/version_changed/active/{composer.lock => vendor/composer/installed.json} (88%)
 rename tests/fixtures/project_staged_validation/version_changed/staged/{composer.lock => vendor/composer/installed.json} (88%)

diff --git a/package_manager/src/ComposerUtility.php b/package_manager/src/ComposerUtility.php
index 4cf3d48ddd..a518bcfee8 100644
--- a/package_manager/src/ComposerUtility.php
+++ b/package_manager/src/ComposerUtility.php
@@ -73,9 +73,14 @@ class ComposerUtility {
     // @see https://getcomposer.org/doc/06-config.md#htaccess-protect
     $htaccess = getenv('COMPOSER_HTACCESS_PROTECT');
 
+    $factory = new Factory();
     putenv("COMPOSER_HOME=$dir");
     putenv("COMPOSER_HTACCESS_PROTECT=false");
-    $composer = Factory::create($io, $configuration);
+    // Initialize the Composer API with plugins disabled and only the root
+    // package loaded (i.e., nothing from the global Composer project will be
+    // considered or loaded). This allows us to inspect the project directory
+    // using Composer's API in a "hands-off" manner.
+    $composer = $factory->createComposer($io, $configuration, TRUE, $dir, FALSE);
     putenv("COMPOSER_HOME=$home");
     putenv("COMPOSER_HTACCESS_PROTECT=$htaccess");
 
@@ -104,7 +109,7 @@ class ComposerUtility {
   }
 
   /**
-   * Returns the names of the core packages in the lock file.
+   * Returns the names of the installed core packages.
    *
    * All packages listed in ../core_packages.json are considered core packages.
    *
@@ -116,7 +121,7 @@ class ComposerUtility {
    */
   public function getCorePackageNames(): array {
     $core_packages = array_intersect(
-      array_keys($this->getLockedPackages()),
+      array_keys($this->getInstalledPackages()),
       static::getCorePackageList()
     );
 
@@ -147,22 +152,23 @@ class ComposerUtility {
       ];
       return in_array($package->getType(), $drupal_package_types, TRUE);
     };
-    return array_filter($this->getLockedPackages(), $filter);
+    return array_filter($this->getInstalledPackages(), $filter);
   }
 
   /**
-   * Returns all packages in the lock file.
+   * Returns information on all installed packages.
    *
    * @return \Composer\Package\PackageInterface[]
-   *   All packages in the lock file, keyed by name.
+   *   All installed packages, keyed by name.
    */
-  protected function getLockedPackages(): array {
-    $locked_packages = $this->getComposer()->getLocker()
-      ->getLockedRepository(TRUE)
+  protected function getInstalledPackages(): array {
+    $installed_packages = $this->getComposer()
+      ->getRepositoryManager()
+      ->getLocalRepository()
       ->getPackages();
 
     $packages = [];
-    foreach ($locked_packages as $package) {
+    foreach ($installed_packages as $package) {
       $key = $package->getName();
       $packages[$key] = $package;
     }
diff --git a/package_manager/tests/fixtures/distro_core/vendor/composer/installed.json b/package_manager/tests/fixtures/distro_core/vendor/composer/installed.json
new file mode 100644
index 0000000000..33e3282787
--- /dev/null
+++ b/package_manager/tests/fixtures/distro_core/vendor/composer/installed.json
@@ -0,0 +1,15 @@
+{
+    "packages": [
+        {
+            "name": "drupal/test-distribution",
+            "version": "1.0.0",
+            "require": {
+                "drupal/core": "*"
+            }
+        },
+        {
+            "name": "drupal/core",
+            "version": "9.8.0"
+        }
+    ]
+}
diff --git a/package_manager/tests/fixtures/distro_core_recommended/vendor/composer/installed.json b/package_manager/tests/fixtures/distro_core_recommended/vendor/composer/installed.json
new file mode 100644
index 0000000000..f68c6fc621
--- /dev/null
+++ b/package_manager/tests/fixtures/distro_core_recommended/vendor/composer/installed.json
@@ -0,0 +1,22 @@
+{
+    "packages": [
+        {
+            "name": "drupal/test-distribution",
+            "version": "1.0.0",
+            "require": {
+                "drupal/core-recommended": "*"
+            }
+        },
+        {
+            "name": "drupal/core-recommended",
+            "version": "9.8.0",
+            "require": {
+                "drupal/core": "9.8.0"
+            }
+        },
+        {
+            "name": "drupal/core",
+            "version": "9.8.0"
+        }
+    ]
+}
diff --git a/tests/fixtures/fake-site/vendor/composer/installed.json b/tests/fixtures/fake-site/vendor/composer/installed.json
new file mode 100644
index 0000000000..c8ad1ba32e
--- /dev/null
+++ b/tests/fixtures/fake-site/vendor/composer/installed.json
@@ -0,0 +1,30 @@
+{
+    "packages": [
+        {
+            "name": "drupal/test-distribution",
+            "version": "1.0.0",
+            "require": {
+                "drupal/core-recommended": "*"
+            }
+        },
+        {
+            "name": "drupal/core-recommended",
+            "version": "9.8.0",
+            "require": {
+                "drupal/core": "9.8.0"
+            }
+        },
+        {
+            "name": "drupal/core",
+            "version": "9.8.0"
+        },
+        {
+            "name": "drupal/core-dev",
+            "version": "9.8.0"
+        }
+    ],
+    "dev": true,
+    "dev-package-names": [
+        "drupal/core-dev"
+    ]
+}
diff --git a/tests/fixtures/project_staged_validation/new_project_added/active/composer.lock b/tests/fixtures/project_staged_validation/new_project_added/active/vendor/composer/installed.json
similarity index 88%
rename from tests/fixtures/project_staged_validation/new_project_added/active/composer.lock
rename to tests/fixtures/project_staged_validation/new_project_added/active/vendor/composer/installed.json
index 67668976a3..df420decb6 100644
--- a/tests/fixtures/project_staged_validation/new_project_added/active/composer.lock
+++ b/tests/fixtures/project_staged_validation/new_project_added/active/vendor/composer/installed.json
@@ -15,9 +15,7 @@
       "description": "This project is removed but there should be no error because it is not a Drupal project.",
       "version": "1.3.1",
       "type": "library"
-    }
-  ],
-  "packages-dev": [
+    },
     {
       "name": "drupal/dev-test_module",
       "version": "1.3.0",
@@ -29,6 +27,10 @@
       "version": "1.3.1",
       "type": "library"
     }
-
+  ],
+  "dev": true,
+  "dev-package-names": [
+    "drupal/dev-test_module",
+    "other/dev-removed"
   ]
 }
diff --git a/tests/fixtures/project_staged_validation/new_project_added/staged/composer.lock b/tests/fixtures/project_staged_validation/new_project_added/staged/vendor/composer/installed.json
similarity index 87%
rename from tests/fixtures/project_staged_validation/new_project_added/staged/composer.lock
rename to tests/fixtures/project_staged_validation/new_project_added/staged/vendor/composer/installed.json
index ba77632196..db60c8425c 100644
--- a/tests/fixtures/project_staged_validation/new_project_added/staged/composer.lock
+++ b/tests/fixtures/project_staged_validation/new_project_added/staged/vendor/composer/installed.json
@@ -20,9 +20,7 @@
       "description": "This is newly added project but there should be no error because it is not a drupal project",
       "version": "1.3.1",
       "type": "library"
-    }
-  ],
-  "packages-dev": [
+    },
     {
       "name": "drupal/dev-test_module",
       "version": "1.3.0",
@@ -39,5 +37,11 @@
       "version": "1.3.1",
       "type": "library"
     }
+  ],
+  "dev": true,
+  "dev-package-names": [
+    "drupal/dev-test_module",
+    "drupal/dev-test_module2",
+    "other/dev-new_project"
   ]
 }
diff --git a/tests/fixtures/project_staged_validation/no_core_requirements/composer.lock b/tests/fixtures/project_staged_validation/no_core_requirements/composer.lock
deleted file mode 100644
index b44dcb4aea..0000000000
--- a/tests/fixtures/project_staged_validation/no_core_requirements/composer.lock
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-    "packages": [],
-    "packages-dev": []
-}
diff --git a/tests/fixtures/project_staged_validation/no_core_requirements/vendor/.gitkeep b/tests/fixtures/project_staged_validation/no_core_requirements/vendor/.gitkeep
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/tests/fixtures/project_staged_validation/no_core_requirements/vendor/composer/installed.json b/tests/fixtures/project_staged_validation/no_core_requirements/vendor/composer/installed.json
new file mode 100644
index 0000000000..aee57674ec
--- /dev/null
+++ b/tests/fixtures/project_staged_validation/no_core_requirements/vendor/composer/installed.json
@@ -0,0 +1,3 @@
+{
+    "packages": []
+}
diff --git a/tests/fixtures/project_staged_validation/no_errors/active/composer.lock b/tests/fixtures/project_staged_validation/no_errors/active/vendor/composer/installed.json
similarity index 90%
rename from tests/fixtures/project_staged_validation/no_errors/active/composer.lock
rename to tests/fixtures/project_staged_validation/no_errors/active/vendor/composer/installed.json
index 24e46dc84c..cc5be9cb71 100644
--- a/tests/fixtures/project_staged_validation/no_errors/active/composer.lock
+++ b/tests/fixtures/project_staged_validation/no_errors/active/vendor/composer/installed.json
@@ -21,9 +21,7 @@
       "description": "This project version is changed but there should be no error because it is not a Drupal project.",
       "version": "1.3.1",
       "type": "library"
-    }
-  ],
-  "packages-dev": [
+    },
     {
       "name": "drupal/dev-test_module",
       "version": "1.3.0",
@@ -41,5 +39,11 @@
       "version": "1.3.1",
       "type": "library"
     }
+  ],
+  "dev": true,
+  "dev-package-names": [
+    "drupal/dev-test_module",
+    "other/dev-removed",
+    "other/dev-changed"
   ]
 }
diff --git a/tests/fixtures/project_staged_validation/no_errors/staged/composer.lock b/tests/fixtures/project_staged_validation/no_errors/staged/vendor/composer/installed.json
similarity index 90%
rename from tests/fixtures/project_staged_validation/no_errors/staged/composer.lock
rename to tests/fixtures/project_staged_validation/no_errors/staged/vendor/composer/installed.json
index 5b77d4cbbd..e7061278bd 100644
--- a/tests/fixtures/project_staged_validation/no_errors/staged/composer.lock
+++ b/tests/fixtures/project_staged_validation/no_errors/staged/vendor/composer/installed.json
@@ -21,9 +21,7 @@
       "description": "This project version is changed but there should be no error because it is not a Drupal project.",
       "version": "1.3.2",
       "type": "library"
-    }
-  ],
-  "packages-dev": [
+    },
     {
       "name": "drupal/dev-test_module",
       "version": "1.3.0",
@@ -41,5 +39,11 @@
       "version": "1.3.2",
       "type": "library"
     }
+  ],
+  "dev": true,
+  "dev-package-names": [
+    "drupal/dev-test_module",
+    "other/dev-new_project",
+    "other/dev-changed"
   ]
 }
diff --git a/tests/fixtures/project_staged_validation/project_removed/active/composer.lock b/tests/fixtures/project_staged_validation/project_removed/active/vendor/composer/installed.json
similarity index 88%
rename from tests/fixtures/project_staged_validation/project_removed/active/composer.lock
rename to tests/fixtures/project_staged_validation/project_removed/active/vendor/composer/installed.json
index ef86aa78d8..ecede582df 100644
--- a/tests/fixtures/project_staged_validation/project_removed/active/composer.lock
+++ b/tests/fixtures/project_staged_validation/project_removed/active/vendor/composer/installed.json
@@ -20,9 +20,7 @@
       "description": "This project is removed but there should be no error because it is not a Drupal project.",
       "version": "1.3.1",
       "type": "library"
-    }
-  ],
-  "packages-dev": [
+    },
     {
       "name": "drupal/dev-test_theme",
       "version": "1.3.0",
@@ -39,5 +37,11 @@
       "version": "1.3.1",
       "type": "library"
     }
+  ],
+  "dev": true,
+  "dev-package-names": [
+    "drupal/dev-test_theme",
+    "drupal/dev-test_module2",
+    "other/dev-removed"
   ]
 }
diff --git a/tests/fixtures/project_staged_validation/project_removed/staged/composer.lock b/tests/fixtures/project_staged_validation/project_removed/staged/vendor/composer/installed.json
similarity index 81%
rename from tests/fixtures/project_staged_validation/project_removed/staged/composer.lock
rename to tests/fixtures/project_staged_validation/project_removed/staged/vendor/composer/installed.json
index 07773fab4c..d9247b6a62 100644
--- a/tests/fixtures/project_staged_validation/project_removed/staged/composer.lock
+++ b/tests/fixtures/project_staged_validation/project_removed/staged/vendor/composer/installed.json
@@ -9,13 +9,15 @@
       "name": "drupal/test_module2",
       "version": "1.3.1",
       "type": "drupal-module"
-    }
-  ],
-  "packages-dev": [
+    },
     {
       "name": "drupal/dev-test_module2",
       "version": "1.3.1",
       "type": "drupal-module"
     }
+  ],
+  "dev": true,
+  "dev-package-names": [
+    "drupal/dev-test_module2"
   ]
 }
diff --git a/tests/fixtures/project_staged_validation/version_changed/active/composer.lock b/tests/fixtures/project_staged_validation/version_changed/active/vendor/composer/installed.json
similarity index 88%
rename from tests/fixtures/project_staged_validation/version_changed/active/composer.lock
rename to tests/fixtures/project_staged_validation/version_changed/active/vendor/composer/installed.json
index 36980fee6f..da5feae3bc 100644
--- a/tests/fixtures/project_staged_validation/version_changed/active/composer.lock
+++ b/tests/fixtures/project_staged_validation/version_changed/active/vendor/composer/installed.json
@@ -15,9 +15,7 @@
       "description": "This project version is changed but there should be no error because it is not a Drupal project.",
       "version": "1.3.1",
       "type": "library"
-    }
-  ],
-  "packages-dev": [
+    },
     {
       "name": "drupal/dev-test_module",
       "version": "1.3.0",
@@ -29,5 +27,10 @@
       "version": "1.3.1",
       "type": "library"
     }
+  ],
+  "dev": true,
+  "dev-package-names": [
+    "drupal/dev-test_module",
+    "other/dev-changed"
   ]
 }
diff --git a/tests/fixtures/project_staged_validation/version_changed/staged/composer.lock b/tests/fixtures/project_staged_validation/version_changed/staged/vendor/composer/installed.json
similarity index 88%
rename from tests/fixtures/project_staged_validation/version_changed/staged/composer.lock
rename to tests/fixtures/project_staged_validation/version_changed/staged/vendor/composer/installed.json
index c16841c9dd..d35464c3cd 100644
--- a/tests/fixtures/project_staged_validation/version_changed/staged/composer.lock
+++ b/tests/fixtures/project_staged_validation/version_changed/staged/vendor/composer/installed.json
@@ -15,9 +15,7 @@
       "description": "This project version is changed but there should be no error because it is not a Drupal project.",
       "version": "1.3.2",
       "type": "library"
-    }
-  ],
-  "packages-dev": [
+    },
     {
       "name": "drupal/dev-test_module",
       "version": "1.3.1",
@@ -29,5 +27,10 @@
       "version": "1.3.2",
       "type": "library"
     }
+  ],
+  "dev": true,
+  "dev-package-names": [
+    "drupal/dev-test_module",
+    "other/dev-changed"
   ]
 }
diff --git a/tests/src/Kernel/ReadinessValidation/StagedDatabaseUpdateValidatorTest.php b/tests/src/Kernel/ReadinessValidation/StagedDatabaseUpdateValidatorTest.php
index bf1469e4a8..212f3df1f8 100644
--- a/tests/src/Kernel/ReadinessValidation/StagedDatabaseUpdateValidatorTest.php
+++ b/tests/src/Kernel/ReadinessValidation/StagedDatabaseUpdateValidatorTest.php
@@ -52,6 +52,8 @@ class StagedDatabaseUpdateValidatorTest extends AutomaticUpdatesKernelTestBase {
     $active_dir = $this->getDrupalRoot();
     @copy("$active_dir/composer.json", "$stage_dir/composer.json");
     @copy("$active_dir/composer.lock", "$stage_dir/composer.lock");
+    mkdir("$stage_dir/vendor/composer", 0777, TRUE);
+    @copy("$active_dir/vendor/composer/installed.json", "$stage_dir/vendor/composer/installed.json");
 
     // Copy the .install and .post_update.php files from every installed module
     // into the staging directory.
diff --git a/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php b/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php
index 2ed0e70035..13db2035d0 100644
--- a/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php
+++ b/tests/src/Kernel/ReadinessValidation/StagedProjectsValidatorTest.php
@@ -114,7 +114,8 @@ class StagedProjectsValidatorTest extends AutomaticUpdatesKernelTestBase {
     // Composer data.
     $fixture = __DIR__ . '/../../../fixtures/fake-site';
     copy("$fixture/composer.json", 'public://composer.json');
-    copy("$fixture/composer.lock", 'public://composer.lock');
+    mkdir('public://vendor/composer', 0777, TRUE);
+    copy("$fixture/vendor/composer/installed.json", 'public://vendor/composer/installed.json');
 
     $event_dispatcher = $this->container->get('event_dispatcher');
     // Disable the disk space validator, since it doesn't work with vfsStream,
@@ -216,19 +217,6 @@ class StagedProjectsValidatorTest extends AutomaticUpdatesKernelTestBase {
     $this->assertEmpty($results);
   }
 
-  /**
-   * Tests validation when a composer.lock file is not found.
-   */
-  public function testNoLockFile(): void {
-    $fixtures_dir = realpath(__DIR__ . '/../../../fixtures/project_staged_validation/no_errors');
-
-    $results = $this->validate("$fixtures_dir/active", $fixtures_dir);
-    $this->assertCount(1, $results);
-    $result = array_pop($results);
-    $this->assertSame("No lockfile found. Unable to read locked packages", (string) $result->getMessages()[0]);
-    $this->assertSame('', (string) $result->getSummary());
-  }
-
 }
 
 /**
-- 
GitLab