Skip to content

Commit 843bb7c

Browse files
committedApr 7, 2021
Refactor the code that matches loaded package data to the ones installed to fix incompat between composer 1/2.
Make it much more sane and cleaner at the same time.
1 parent 4d98a97 commit 843bb7c

7 files changed

+136
-48
lines changed
 

‎docs/testing.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,12 @@ _String that will be appended to every invocation of composer command._
4444
> **Warning!** Arguments passed through env vars must must be space-delimited
4545
> and each argument cannot contain space characters even if they are escaped.
4646
47-
4847
#### `COMPOSER_SANDBOX_TEST_DEBUG` - Enable extra debugging features
4948

5049
If enabled sandbox directories of failed tests are preserved and composer
5150
command output is flushed for every test.
52-
51+
52+
#### `COMPOSER_SANDBOX_DISABLE_CLEANUP` - Preserve sandbox temp dirs
53+
54+
Do not remove the directory after running a test.
55+

‎src/PackageApplicationRepository.php

+118-33
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
use Composer\Package\AliasPackage;
77
use Composer\Package\PackageInterface;
88
use Composer\Repository\RepositoryInterface;
9+
use Composer\Package\Dumper\ArrayDumper;
10+
use Composer\Package\Loader\ArrayLoader;
11+
use Composer\Json\JsonFile;
12+
use Composer\Semver\Semver;
913
use Psr\Log\LoggerInterface;
1014

1115
class PackageApplicationRepository
@@ -30,6 +34,16 @@ class PackageApplicationRepository
3034
*/
3135
private $logger;
3236

37+
/**
38+
* @var ArrayDumper
39+
*/
40+
private $packageDumper;
41+
42+
/**
43+
* @var ArrayLoader
44+
*/
45+
private $packageLoader;
46+
3347
/**
3448
* @param RepositoryInterface $installedRepository
3549
* @param InstallationManager $installationManager
@@ -46,6 +60,9 @@ public function __construct(
4660
$this->installationManager = $installationManager;
4761
$this->pathResolver = $pathResolver;
4862
$this->logger = $logger;
63+
64+
$this->packageDumper = new ArrayDumper();
65+
$this->packageLoader = new ArrayLoader();
4966
}
5067

5168
/**
@@ -81,7 +98,7 @@ public function getPackageApplication(PackageInterface $targetPackage)
8198
}
8299

83100
if (!is_readable($dataFile)) {
84-
throw new \RuntimeException('Cannot read applied patches data file "%s"', $dataFile);
101+
throw new \RuntimeException('Cannot Loaded applied patches data file "%s"', $dataFile);
85102
}
86103

87104
$data = json_decode(file_get_contents($dataFile), true);
@@ -126,46 +143,104 @@ private function encodeData(array $data)
126143
* @param array $data
127144
* @return PackagePatchApplication
128145
*/
129-
private function createPackagePatchApplication(PackageInterface $targetPackage, array $data)
146+
private function createPackagePatchApplication($targetPackage, array $data)
130147
{
131-
return new PackagePatchApplication($targetPackage,
132-
array_map([$this, 'createPatchApplication'], $data['patches'])
133-
);
148+
return new PackagePatchApplication($targetPackage, array_map(
149+
function($patchData) use ($targetPackage) {
150+
return $this->createPatchApplication($targetPackage, $patchData);
151+
},
152+
$data['patches']
153+
));
154+
}
155+
156+
/**
157+
* @param PackageInterface|null $loadedPackage
158+
* @param string $versionConstraint
159+
* @return PackageInterface|null
160+
*/
161+
private function matchLoadedPackageToInstalled($loadedPackage, $versionConstraint = null)
162+
{
163+
if ($package = $this->installedRepository->findPackage($loadedPackage->getName(), $loadedPackage->getVersion())) {
164+
return $package;
165+
}
166+
167+
if ($loadedPackage->getPrettyVersion()
168+
&& $package = $this->installedRepository->findPackage($loadedPackage->getName(), $loadedPackage->getPrettyVersion())) {
169+
return $package;
170+
}
171+
172+
if ($loadedPackage->getFullPrettyVersion()
173+
&& $package = $this->installedRepository->findPackage($loadedPackage->getName(), $loadedPackage->getFullPrettyVersion())) {
174+
return $package;
175+
}
176+
177+
if ($versionConstraint && $package = $this->installedRepository->findPackage($loadedPackage->getName(), $versionConstraint)) {
178+
return $package;
179+
}
180+
181+
return null;
182+
}
183+
184+
/**
185+
* @param PackageInterface $targetPackageInstalled
186+
* @param PackageInterface $targetPackageLoaded
187+
* @param Patch $patchLoaded
188+
* @return PackageInterface|null
189+
*/
190+
private function matchTargetLoadedPackageToInstalled($targetPackageInstalled, $targetPackageLoaded, $patchLoaded)
191+
{
192+
if ($targetPackageInstalled->getName() === $targetPackageLoaded->getName()) {
193+
if ($targetPackageInstalled->getVersion() === $targetPackageLoaded->getVersion()) {
194+
return $targetPackageInstalled;
195+
}
196+
197+
if ($targetPackageInstalled->getPrettyVersion() === $targetPackageLoaded->getPrettyVersion()) {
198+
return $targetPackageInstalled;
199+
}
200+
201+
if ($patchLoaded->getVersionConstraint() && Semver::satisfies($targetPackageInstalled->getVersion(), $patchLoaded->getVersionConstraint())) {
202+
return $targetPackageInstalled;
203+
}
204+
205+
$this->logger->warning(sprintf(
206+
'Could not find find installed package (%s) matching version (%s) loaded loaded from applied patch.' .
207+
'Name and location checks out, but it might indicate a potential problem. Continuing...',
208+
$targetPackageInstalled->getPrettyName(),
209+
$targetPackageLoaded->getPrettyName()
210+
));
211+
}
212+
213+
return $this->matchLoadedPackageToInstalled($targetPackageLoaded, $patchLoaded->getVersionConstraint());
134214
}
135215

136216
/**
217+
* @param PackageInterface $targetPackage
137218
* @param array $data
138219
* @return PatchApplication
139220
*/
140-
private function createPatchApplication(array $data)
221+
private function createPatchApplication($targetPackage, array $data)
141222
{
142223
$patch = Patch::createFromArray($data['patch']);
143224

144-
$sourcePackage = $this->installedRepository->findPackage(
145-
$data['source_package']['name'],
146-
$data['source_package']['version']
147-
);
225+
$sourcePackageLoaded = $this->loadPackageFromArray($data['source_package']);
226+
$targetPackageLoaded = $this->loadPackageFromArray($data['target_package']);
148227

149-
if (!$sourcePackage) {
150-
$this->logger->debug(sprintf('Could not find source package %s (%s) for installed patch, it was removed probably',
151-
$data['source_package']['name'],
152-
$data['source_package']['version']
228+
if (!$sourcePackageInstalled = $this->matchLoadedPackageToInstalled($sourcePackageLoaded)) {
229+
$this->logger->debug(sprintf(
230+
'Could not find source package %s for installed patch, it was removed probably',
231+
$sourcePackageLoaded->getPrettyName()
153232
));
154233
}
155234

156-
$targetPackage = $this->installedRepository->findPackage(
157-
$data['target_package']['name'],
158-
$data['target_package']['version']
159-
);
160235

161-
if (!$targetPackage) {
162-
throw new \RuntimeException(sprintf('Could not find target package %s (%s) for installed patch',
163-
$data['target_package']['name'],
164-
$data['target_package']['version']
236+
if (!$targetPackageInstalled = $this->matchTargetLoadedPackageToInstalled($targetPackage, $targetPackageLoaded, $patch)) {
237+
throw new \LogicException(sprintf(
238+
'Could not find target package %s for installed patch. This should not happen.',
239+
$targetPackageLoaded->getPrettyName()
165240
));
166241
}
167242

168-
return new PatchApplication($patch, $sourcePackage, $targetPackage, $data['hash']);
243+
return new PatchApplication($patch, $sourcePackageInstalled, $targetPackageInstalled, $data['hash']);
169244
}
170245

171246
/**
@@ -183,6 +258,24 @@ public function transformPackagePatchApplicationToArray(PackagePatchApplication
183258
];
184259
}
185260

261+
/**
262+
* @param PackageInterface $package
263+
* @return array
264+
*/
265+
public function dumpPackageToArray($package)
266+
{
267+
return $this->packageDumper->dump($package);
268+
}
269+
270+
/**
271+
* @param array $packageData
272+
* @return PackageInterface
273+
*/
274+
public function loadPackageFromArray($packageData)
275+
{
276+
return $this->packageLoader->load($packageData);
277+
}
278+
186279
/**
187280
* @param PatchApplication $application
188281
* @return array
@@ -191,16 +284,8 @@ public function transformPatchApplicationToArray(PatchApplication $application)
191284
{
192285
return [
193286
'hash' => $application->getHash(),
194-
'target_package' => [
195-
'name' => $application->getTargetPackage()->getName(),
196-
'version' => $application->getTargetPackage()->getVersion(),
197-
'ref' => $application->getTargetPackage()->getSourceReference(),
198-
],
199-
'source_package' => [
200-
'name' => $application->getSourcePackage()->getName(),
201-
'version' => $application->getSourcePackage()->getVersion(),
202-
'ref' => $application->getSourcePackage()->getSourceReference(),
203-
],
287+
'target_package' => $this->dumpPackageToArray($application->getTargetPackage()),
288+
'source_package' => $this->dumpPackageToArray($application->getSourcePackage()),
204289
'patch' => $application->getPatch()->toArray()
205290
];
206291
}

‎src/PathResolver.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
class PathResolver
1010
{
11-
const PATCH_APPLICATION_DATA_FILENAME = 'composer.patches_applied.json';
11+
const PATCH_APPLICATION_DATA_FILENAME = 'patches-applied.json';
12+
const PATCH_APPLICATION_DATA_LEGACY_FILENAME = 'composer.patches_applied.json';
1213

1314
/**
1415
* @var InstallationManager
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "test/package-a",
33
"type": "library",
4-
"version": "dev-master",
4+
"version": "1.0.0-dev",
55
"require": {}
66
}

‎tests/sandbox/ComposerProjectSandbox.php

-2
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,6 @@ private function writeComposerJson()
145145

146146
$config = array_merge($config, $this->config);
147147

148-
var_dump(($this->config));
149-
150148
file_put_contents($this->getConfigPath(), json_encode($config, JSON_PRETTY_PRINT + JSON_UNESCAPED_SLASHES + JSON_UNESCAPED_UNICODE));
151149
}
152150

‎tests/sandbox/ComposerSandbox.php

+9-5
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,10 @@ public function __construct(
237237
$this->phpBinary = $phpBinary;
238238
}
239239

240+
if (getenv('COMPOSER_SANDBOX_DISABLE_CLEANUP')) {
241+
$this->disableCleanup();
242+
}
243+
240244
if (null === $selfPackageDir) {
241245
$selfPackageDir = static::getRootProjectDir();
242246
}
@@ -270,11 +274,6 @@ public function __construct(
270274
*/
271275
public function disableCleanup()
272276
{
273-
$this->io->write(sprintf(
274-
" ---> Cleanup is disabled, keeping output buffer and root dir: <info>%s</info>",
275-
$this->rootDir
276-
));
277-
278277
$this->cleanupDisabled = true;
279278
}
280279

@@ -561,6 +560,11 @@ public function cleanupProjects()
561560
public function cleanup()
562561
{
563562
if ($this->cleanupDisabled) {
563+
$this->io->write(sprintf(
564+
" ---> Ignoring cleanup - keeping output buffer and root dir: <info>%s</info>",
565+
$this->rootDir
566+
));
567+
564568
return;
565569
}
566570

‎tests/sandbox/ComposerSandboxTestCase.php

+1-4
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,10 @@ protected function createComposerSandbox()
7676
ComposerSandbox::enableDebugOutput();
7777
}
7878

79-
$sb = new ComposerSandbox(
79+
return new ComposerSandbox(
8080
$this->getComposerSandboxFixturesDir(),
8181
$this->getComposerSandboxIdentifier()
8282
);
83-
$sb->disableCleanup();
84-
85-
return $sb;
8683
}
8784

8885
/**

0 commit comments

Comments
 (0)
Please sign in to comment.