1
0
Fork 0

Clean up lock update code to remove redundancy and avoid errors (#12149)

pull/12152/head
Jordi Boggiano 2024-10-04 11:47:01 +02:00 committed by GitHub
parent 4cb5479211
commit b840a06207
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 66 additions and 35 deletions

View File

@ -217,14 +217,7 @@ EOT
} }
if (!$dryRun && $composer->getLocker()->isLocked() && $changeCount > 0) { if (!$dryRun && $composer->getLocker()->isLocked() && $changeCount > 0) {
$contents = file_get_contents($composerJson->getPath()); $composer->getLocker()->updateHash($composerJson);
if (false === $contents) {
throw new \RuntimeException('Unable to read '.$composerJson->getPath().' contents to update the lock file hash.');
}
$lock = new JsonFile(Factory::getLockFile($composerJsonPath));
$lockData = $lock->read();
$lockData['content-hash'] = Locker::getContentHash($contents);
$lock->write($lockData);
} }
if ($dryRun && $changeCount > 0) { if ($dryRun && $changeCount > 0) {

View File

@ -555,27 +555,14 @@ EOT
if (!$dryRun) { if (!$dryRun) {
$this->updateFile($this->json, $requirements, $requireKey, $removeKey, $sortPackages); $this->updateFile($this->json, $requirements, $requireKey, $removeKey, $sortPackages);
if ($locker->isLocked()) { if ($locker->isLocked()) {
$contents = file_get_contents($this->json->getPath()); $stabilityFlags = RootPackageLoader::extractStabilityFlags($requirements, $composer->getPackage()->getMinimumStability(), []);
if (false === $contents) { $locker->updateHash($this->json, function (array $lockData) use ($stabilityFlags) {
throw new \RuntimeException('Unable to read '.$this->json->getPath().' contents to update the lock file hash.');
}
$lockFile = Factory::getLockFile($this->json->getPath());
if (file_exists($lockFile)) {
$stabilityFlags = RootPackageLoader::extractStabilityFlags($requirements, $composer->getPackage()->getMinimumStability(), []);
$lockMtime = filemtime($lockFile);
$lock = new JsonFile($lockFile);
$lockData = $lock->read();
$lockData['content-hash'] = Locker::getContentHash($contents);
foreach ($stabilityFlags as $packageName => $flag) { foreach ($stabilityFlags as $packageName => $flag) {
$lockData['stability-flags'][$packageName] = $flag; $lockData['stability-flags'][$packageName] = $flag;
} }
ksort($lockData['stability-flags']);
$lock->write($lockData); return $lockData;
if (is_int($lockMtime)) { });
@touch($lockFile, $lockMtime);
}
}
} }
} }

View File

@ -372,31 +372,28 @@ class Locker
'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies', 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies',
'This file is @gener'.'ated automatically', ], 'This file is @gener'.'ated automatically', ],
'content-hash' => $this->contentHash, 'content-hash' => $this->contentHash,
'packages' => null, 'packages' => $this->lockPackages($packages),
'packages-dev' => null, 'packages-dev' => null,
'aliases' => $aliases, 'aliases' => $aliases,
'minimum-stability' => $minimumStability, 'minimum-stability' => $minimumStability,
'stability-flags' => \count($stabilityFlags) > 0 ? $stabilityFlags : new \stdClass, 'stability-flags' => $stabilityFlags,
'prefer-stable' => $preferStable, 'prefer-stable' => $preferStable,
'prefer-lowest' => $preferLowest, 'prefer-lowest' => $preferLowest,
]; ];
if (is_array($lock['stability-flags'])) {
ksort($lock['stability-flags']);
}
$lock['packages'] = $this->lockPackages($packages);
if (null !== $devPackages) { if (null !== $devPackages) {
$lock['packages-dev'] = $this->lockPackages($devPackages); $lock['packages-dev'] = $this->lockPackages($devPackages);
} }
$lock['platform'] = \count($platformReqs) > 0 ? $platformReqs : new \stdClass; $lock['platform'] = $platformReqs;
$lock['platform-dev'] = \count($platformDevReqs) > 0 ? $platformDevReqs : new \stdClass; $lock['platform-dev'] = $platformDevReqs;
if (\count($platformOverrides) > 0) { if (\count($platformOverrides) > 0) {
$lock['platform-overrides'] = $platformOverrides; $lock['platform-overrides'] = $platformOverrides;
} }
$lock['plugin-api-version'] = PluginInterface::PLUGIN_API_VERSION; $lock['plugin-api-version'] = PluginInterface::PLUGIN_API_VERSION;
$lock = $this->fixupJsonDataType($lock);
try { try {
$isLocked = $this->isLocked(); $isLocked = $this->isLocked();
} catch (ParsingException $e) { } catch (ParsingException $e) {
@ -418,6 +415,60 @@ class Locker
return false; return false;
} }
/**
* Updates the lock file's hash in-place from a given composer.json's JsonFile
*
* This does not reload or require any packages, and retains the filemtime of the lock file.
*
* Use this only to update the lock file hash after updating a composer.json in ways that are guaranteed NOT to impact the dependency resolution.
*
* This is a risky method, use carefully.
*
* @param (callable(array<mixed>): array<mixed>)|null $dataProcessor Receives the lock data and can process it before it gets written to disk
*/
public function updateHash(JsonFile $composerJson, ?callable $dataProcessor = null): void
{
$contents = file_get_contents($composerJson->getPath());
if (false === $contents) {
throw new \RuntimeException('Unable to read '.$composerJson->getPath().' contents to update the lock file hash.');
}
$lockMtime = filemtime($this->lockFile->getPath());
$lockData = $this->lockFile->read();
$lockData['content-hash'] = Locker::getContentHash($contents);
if ($dataProcessor !== null) {
$lockData = $dataProcessor($lockData);
}
$this->lockFile->write($this->fixupJsonDataType($lockData));
$this->lockDataCache = null;
$this->virtualFileWritten = false;
if (is_int($lockMtime)) {
@touch($this->lockFile->getPath(), $lockMtime);
}
}
/**
* Ensures correct data types and ordering for the JSON lock format
*
* @param array<mixed> $lockData
* @return array<mixed>
*/
private function fixupJsonDataType(array $lockData): array
{
foreach (['stability-flags', 'platform', 'platform-dev'] as $key) {
if (isset($lockData[$key]) && is_array($lockData[$key]) && \count($lockData[$key]) === 0) {
$lockData[$key] = new \stdClass();
}
}
if (is_array($lockData['stability-flags'])) {
ksort($lockData['stability-flags']);
}
return $lockData;
}
/** /**
* @param PackageInterface[] $packages * @param PackageInterface[] $packages
* *