Skip to content

Commit 7c48460

Browse files
feature #713 Use root constraints when they have no intersection with extra.symfony.require (nicolas-grekas)
This PR was merged into the 1.9-dev branch. Discussion ---------- Use root constraints when they have no intersection with extra.symfony.require Fixes #712 Fixes composer/composer#9409 Fixes https://twitter.com/scherzmut/status/1323609763125612546 Commits ------- 1ef0b00 Use root constraints when they have no intersection with extra.symfony.require
2 parents 6483a87 + 1ef0b00 commit 7c48460

File tree

6 files changed

+93
-11
lines changed

6 files changed

+93
-11
lines changed

src/Cache.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Composer\Cache as BaseCache;
1515
use Composer\IO\IOInterface;
16+
use Composer\Package\RootPackageInterface;
1617
use Composer\Semver\Constraint\Constraint;
1718
use Composer\Semver\VersionParser;
1819

@@ -24,17 +25,22 @@ class Cache extends BaseCache
2425
private $versions;
2526
private $versionParser;
2627
private $symfonyRequire;
28+
private $rootConstraints = [];
2729
private $symfonyConstraints;
2830
private $downloader;
2931
private $io;
3032

31-
public function setSymfonyRequire(string $symfonyRequire, Downloader $downloader, IOInterface $io = null)
33+
public function setSymfonyRequire(string $symfonyRequire, RootPackageInterface $rootPackage, Downloader $downloader, IOInterface $io = null)
3234
{
3335
$this->versionParser = new VersionParser();
3436
$this->symfonyRequire = $symfonyRequire;
3537
$this->symfonyConstraints = $this->versionParser->parseConstraints($symfonyRequire);
3638
$this->downloader = $downloader;
3739
$this->io = $io;
40+
41+
foreach ($rootPackage->getRequires() + $rootPackage->getDevRequires() as $name => $link) {
42+
$this->rootConstraints[$name] = $link->getConstraint();
43+
}
3844
}
3945

4046
public function read($file)
@@ -59,14 +65,23 @@ public function removeLegacyTags(array $data): array
5965
continue;
6066
}
6167

68+
$rootConstraint = $this->rootConstraints[$name] ?? null;
69+
$rootVersions = [];
70+
6271
foreach ($versions as $version => $composerJson) {
6372
if (null !== $alias = $composerJson['extra']['branch-alias'][$version] ?? null) {
6473
$normalizedVersion = $this->versionParser->normalize($alias);
6574
} elseif (null === $normalizedVersion = $composerJson['version_normalized'] ?? null) {
6675
continue;
6776
}
6877

69-
if (!$this->symfonyConstraints->matches(new Constraint('==', $normalizedVersion))) {
78+
$constraint = new Constraint('==', $normalizedVersion);
79+
80+
if ($rootConstraint && $rootConstraint->matches($constraint)) {
81+
$rootVersions[$version] = $composerJson;
82+
}
83+
84+
if (!$this->symfonyConstraints->matches($constraint)) {
7085
if (null !== $this->io) {
7186
$this->io->writeError(sprintf('<info>Restricting packages listed in "symfony/symfony" to "%s"</>', $this->symfonyRequire));
7287
$this->io = null;
@@ -75,6 +90,10 @@ public function removeLegacyTags(array $data): array
7590
}
7691
}
7792

93+
if ($rootConstraint && !array_intersect_key($rootVersions, $versions)) {
94+
$versions = $rootVersions;
95+
}
96+
7897
$data['packages'][$name] = $versions;
7998
}
8099

src/Flex.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,16 +140,17 @@ class_exists(__NAMESPACE__.str_replace('/', '\\', substr($file, \strlen(__DIR__)
140140
$this->downloader = $downloader = new Downloader($composer, $io, $this->rfs);
141141
$this->downloader->setFlexId($this->getFlexId());
142142

143+
$rootPackage = $composer->getPackage();
143144
$manager = RepositoryFactory::manager($this->io, $this->config, $composer->getEventDispatcher(), $this->rfs);
144-
$setRepositories = \Closure::bind(function (RepositoryManager $manager) use (&$symfonyRequire, $downloader) {
145+
$setRepositories = \Closure::bind(function (RepositoryManager $manager) use (&$symfonyRequire, $rootPackage, $downloader) {
145146
$manager->repositoryClasses = $this->repositoryClasses;
146147
$manager->setRepositoryClass('composer', TruncatedComposerRepository::class);
147148
$manager->repositories = $this->repositories;
148149
$i = 0;
149150
foreach (RepositoryFactory::defaultRepos(null, $this->config, $manager) as $repo) {
150151
$manager->repositories[$i++] = $repo;
151152
if ($repo instanceof TruncatedComposerRepository && $symfonyRequire) {
152-
$repo->setSymfonyRequire($symfonyRequire, $downloader, $this->io);
153+
$repo->setSymfonyRequire($symfonyRequire, $rootPackage, $downloader, $this->io);
153154
}
154155
}
155156
$manager->setLocalRepository($this->getLocalRepository());
@@ -863,7 +864,11 @@ public function truncatePackages(PrePoolCreateEvent $event)
863864
if (!$this->filter) {
864865
return;
865866
}
866-
$event->setPackages($this->filter->removeLegacyPackages($event->getPackages(), $event->getRequest()->getFixedOrLockedPackages()));
867+
868+
$rootPackage = $this->composer->getPackage();
869+
$lockedPackages = $event->getRequest()->getFixedOrLockedPackages();
870+
871+
$event->setPackages($this->filter->removeLegacyPackages($event->getPackages(), $rootPackage, $lockedPackages));
867872
}
868873

869874
private function initOptions(): Options

src/PackageFilter.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
use Composer\IO\IOInterface;
1515
use Composer\Package\AliasPackage;
1616
use Composer\Package\PackageInterface;
17+
use Composer\Package\RootPackageInterface;
1718
use Composer\Semver\Constraint\Constraint;
19+
use Composer\Semver\Intervals;
1820
use Composer\Semver\VersionParser;
1921

2022
/**
@@ -44,7 +46,7 @@ public function __construct(IOInterface $io, string $symfonyRequire, Downloader
4446
*
4547
* @return PackageInterface[]
4648
*/
47-
public function removeLegacyPackages(array $data, array $lockedPackages): array
49+
public function removeLegacyPackages(array $data, RootPackageInterface $rootPackage, array $lockedPackages): array
4850
{
4951
if (!$this->symfonyConstraints || !$data) {
5052
return $data;
@@ -58,6 +60,11 @@ public function removeLegacyPackages(array $data, array $lockedPackages): array
5860
}
5961
}
6062

63+
$rootConstraints = [];
64+
foreach ($rootPackage->getRequires() + $rootPackage->getDevRequires() as $name => $link) {
65+
$rootConstraints[$name] = $link->getConstraint();
66+
}
67+
6168
$knownVersions = $this->getVersions();
6269
$filteredPackages = [];
6370
$symfonyPackages = [];
@@ -68,7 +75,12 @@ public function removeLegacyPackages(array $data, array $lockedPackages): array
6875
if ($package instanceof AliasPackage) {
6976
$versions[] = $package->getAliasOf()->getVersion();
7077
}
71-
if ('symfony/symfony' !== $name && (!isset($knownVersions['splits'][$name]) || array_intersect($versions, $lockedVersions[$name] ?? []))) {
78+
79+
if ('symfony/symfony' !== $name && (
80+
!isset($knownVersions['splits'][$name])
81+
|| array_intersect($versions, $lockedVersions[$name] ?? [])
82+
|| (isset($rootConstraints[$name]) && !Intervals::haveIntersections($this->symfonyConstraints, $rootConstraints[$name]))
83+
)) {
7284
$filteredPackages[] = $package;
7385
continue;
7486
}

src/TruncatedComposerRepository.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Composer\Config;
1515
use Composer\EventDispatcher\EventDispatcher;
1616
use Composer\IO\IOInterface;
17+
use Composer\Package\RootPackageInterface;
1718
use Composer\Repository\ComposerRepository as BaseComposerRepository;
1819
use Composer\Util\RemoteFilesystem;
1920

@@ -29,9 +30,9 @@ public function __construct(array $repoConfig, IOInterface $io, Config $config,
2930
$this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
3031
}
3132

32-
public function setSymfonyRequire(string $symfonyRequire, Downloader $downloader, IOInterface $io)
33+
public function setSymfonyRequire(string $symfonyRequire, RootPackageInterface $rootPackage, Downloader $downloader, IOInterface $io)
3334
{
34-
$this->cache->setSymfonyRequire($symfonyRequire, $downloader, $io);
35+
$this->cache->setSymfonyRequire($symfonyRequire, $rootPackage, $downloader, $io);
3536
}
3637

3738
protected function fetchFile($filename, $cacheKey = null, $sha256 = null, $storeLastModifiedTime = false)

tests/CacheTest.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
namespace Symfony\Flex\Tests;
1313

14+
use Composer\Package\Link;
15+
use Composer\Package\RootPackage;
16+
use Composer\Semver\Constraint\Constraint;
1417
use PHPUnit\Framework\TestCase;
1518
use Symfony\Flex\Cache;
1619

@@ -25,8 +28,14 @@ public function testRemoveLegacyTags(array $expected, array $packages, string $s
2528
$downloader->expects($this->once())
2629
->method('getVersions')
2730
->willReturn($versions);
31+
32+
$rootPackage = new RootPackage('test/test', '1.0.0.0', '1.0');
33+
$rootPackage->setRequires([
34+
'symfony/bar' => new Link('__root__', 'symfony/bar', new Constraint('>=', '3.0.0.0')),
35+
]);
36+
2837
$cache = (new \ReflectionClass(Cache::class))->newInstanceWithoutConstructor();
29-
$cache->setSymfonyRequire($symfonyRequire, $downloader);
38+
$cache->setSymfonyRequire($symfonyRequire, $rootPackage, $downloader);
3039

3140
$this->assertSame(['packages' => $expected], $cache->removeLegacyTags(['packages' => $packages]));
3241
}
@@ -120,5 +129,18 @@ public function provideRemoveLegacyTags()
120129
'symfony/foo' => ['2.8', '3.0'],
121130
'symfony/new' => ['3.0'],
122131
]]];
132+
133+
$packages = [
134+
'symfony/symfony' => [
135+
'3.0.0' => ['version_normalized' => '3.0.0.0'],
136+
],
137+
'symfony/bar' => [
138+
'3.0.0' => ['version_normalized' => '3.0.0.0'],
139+
],
140+
];
141+
142+
yield 'root-constraints-are-preserved' => [$packages, $packages, '~2.8', ['splits' => [
143+
'symfony/bar' => ['2.8', '3.0'],
144+
]]];
123145
}
124146
}

tests/PackageFilterTest.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,17 @@
1313

1414
use Composer\IO\NullIO;
1515
use Composer\Package\CompletePackage;
16+
use Composer\Package\Link;
1617
use Composer\Package\Loader\ArrayLoader;
1718
use Composer\Package\PackageInterface;
19+
use Composer\Package\RootPackage;
20+
use Composer\Semver\Constraint\Constraint;
1821
use PHPUnit\Framework\TestCase;
1922
use Symfony\Flex\PackageFilter;
2023

24+
/**
25+
* @requires function \Composer\Plugin\PrePoolCreateEvent::__construct
26+
*/
2127
class PackageFilterTest extends TestCase
2228
{
2329
/**
@@ -52,8 +58,12 @@ public function testRemoveLegacyPackages(array $expected, array $packages, strin
5258
$expected = $configToPackage($expected);
5359
$packages = $configToPackage($packages);
5460
$lockedPackages = $configToPackage($lockedPackages);
61+
$rootPackage = new RootPackage('test/test', '1.0.0.0', '1.0');
62+
$rootPackage->setRequires([
63+
'symfony/bar' => new Link('__root__', 'symfony/bar', new Constraint('>=', '3.0.0.0')),
64+
]);
5565

56-
$actual = $filter->removeLegacyPackages($packages, $lockedPackages);
66+
$actual = $filter->removeLegacyPackages($packages, $rootPackage, $lockedPackages);
5767

5868
usort($expected, $sortPackages);
5969
usort($actual, $sortPackages);
@@ -183,5 +193,18 @@ public function provideRemoveLegacyPackages()
183193
yield 'locked-packages-are-preserved' => [$packages, $packages, '~2.8', ['splits' => [
184194
'symfony/foo' => ['2.8', '3.0'],
185195
]], $lockedPackages];
196+
197+
$packages = [
198+
'symfony/symfony' => [
199+
'3.0.0' => ['version_normalized' => '3.0.0.0'],
200+
],
201+
'symfony/bar' => [
202+
'3.0.0' => ['version_normalized' => '3.0.0.0'],
203+
],
204+
];
205+
206+
yield 'root-constraints-are-preserved' => [$packages, $packages, '~2.8', ['splits' => [
207+
'symfony/bar' => ['2.8', '3.0'],
208+
]]];
186209
}
187210
}

0 commit comments

Comments
 (0)