From 917748c9963a75c258973fdfa1005b330f287f9c Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 20 Aug 2022 08:42:20 +0300 Subject: [PATCH] Fix cache invalidation issue when a git tag gets created on an old ref after the cache is populated, fixes #11002 (#11004) --- src/Composer/Downloader/GitDownloader.php | 2 +- src/Composer/Util/Git.php | 25 ++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index 2866ae59d..908cb08e7 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -70,7 +70,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface $this->io->writeError(" - Syncing " . $package->getName() . " (" . $package->getFullPrettyVersion() . ") into cache"); $this->io->writeError(sprintf(' Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG); $ref = $package->getSourceReference(); - if ($this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref) && is_dir($cachePath)) { + if ($this->gitUtil->fetchRefOrSyncMirror($url, $cachePath, $ref, $package->getPrettyVersion()) && is_dir($cachePath)) { $this->cachedPackages[$package->getId()][$ref] = true; } } elseif (null === $gitVersion) { diff --git a/src/Composer/Util/Git.php b/src/Composer/Util/Git.php index 19f411bba..40e646d4f 100644 --- a/src/Composer/Util/Git.php +++ b/src/Composer/Util/Git.php @@ -314,12 +314,35 @@ class Git * @param string $url * @param string $dir * @param string $ref + * @param ?string $prettyVersion * * @return bool */ - public function fetchRefOrSyncMirror($url, $dir, $ref) + public function fetchRefOrSyncMirror($url, $dir, $ref, $prettyVersion = null) { if ($this->checkRefIsInMirror($dir, $ref)) { + if (Preg::isMatch('{^[a-f0-9]{40}$}', $ref) && $prettyVersion !== null) { + $branch = Preg::replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $prettyVersion); + $branches = null; + $tags = null; + if (0 === $this->process->execute('git branch', $output, $dir)) { + $branches = $output; + } + if (0 === $this->process->execute('git tag', $output, $dir)) { + $tags = $output; + } + + // if the pretty version cannot be found as a branch (nor branch with 'v' in front of the branch as it may have been stripped when generating pretty name), + // nor as a tag, then we sync the mirror as otherwise it will likely fail during install. + // this can occur if a git tag gets created *after* the reference is already put into the cache, as the ref check above will then not sync the new tags + // see https://github.com/composer/composer/discussions/11002 + if (null !== $branches && !Preg::isMatch('{^[\s*]*v?'.preg_quote($branch).'$}m', $branches) + && null !== $tags && !Preg::isMatch('{^[\s*]*'.preg_quote($branch).'$}m', $tags) + ) { + $this->syncMirror($url, $dir); + } + } + return true; }