Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d65dabd

Browse files
committedFeb 19, 2017
Add support of dependencies resolution to solve the conflicts
1 parent 1baac76 commit d65dabd

11 files changed

+303
-3
lines changed
 

‎FxpAssetPlugin.php

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Fxp\Composer\AssetPlugin\Config\Config;
2424
use Fxp\Composer\AssetPlugin\Config\ConfigBuilder;
2525
use Fxp\Composer\AssetPlugin\Repository\AssetRepositoryManager;
26+
use Fxp\Composer\AssetPlugin\Repository\ResolutionManager;
2627
use Fxp\Composer\AssetPlugin\Repository\VcsPackageFilter;
2728
use Fxp\Composer\AssetPlugin\Util\AssetPlugin;
2829

@@ -87,6 +88,7 @@ public function activate(Composer $composer, IOInterface $io)
8788
$this->io = $io;
8889
$this->packageFilter = new VcsPackageFilter($this->config, $composer->getPackage(), $composer->getInstallationManager(), $installedRepository);
8990
$this->assetRepositoryManager = new AssetRepositoryManager($io, $composer->getRepositoryManager(), $this->packageFilter);
91+
$this->assetRepositoryManager->setResolutionManager(new ResolutionManager($this->config->getArray('resolutions')));
9092

9193
AssetPlugin::addRegistryRepositories($this->assetRepositoryManager, $this->packageFilter, $this->config);
9294
AssetPlugin::setVcsTypeRepositories($composer->getRepositoryManager());

‎Package/Loader/LazyAssetPackageLoader.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ protected function preProcess(VcsDriverInterface $driver, array $data, $identifi
264264
$data['source'] = $driver->getSource($identifier);
265265
}
266266

267-
return (array) $data;
267+
return $this->assetRepositoryManager->solveResolutions((array) $data);
268268
}
269269

270270
/**

‎Repository/AbstractAssetVcsRepository.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,9 @@ protected function preProcessAsset(array $data)
237237

238238
// keep the name of the main identifier for all packages
239239
$data['name'] = $this->packageName ?: $data['name'];
240-
$data = $this->assetType->getPackageConverter()->convert($data, $vcsRepos);
240+
$data = (array) $this->assetType->getPackageConverter()->convert($data, $vcsRepos);
241241

242-
return (array) $data;
242+
return $this->assetRepositoryManager->solveResolutions($data);
243243
}
244244

245245
/**

‎Repository/AssetRepositoryManager.php

+29
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ class AssetRepositoryManager
4343
*/
4444
protected $pool;
4545

46+
/**
47+
* @var ResolutionManager
48+
*/
49+
protected $resolutionManager;
50+
4651
/**
4752
* @var RepositoryInterface[]
4853
*/
@@ -86,6 +91,30 @@ public function setPool(Pool $pool)
8691
return $this;
8792
}
8893

94+
/**
95+
* Set the dependency resolution manager.
96+
*
97+
* @param ResolutionManager $resolutionManager The dependency resolution manager
98+
*/
99+
public function setResolutionManager(ResolutionManager $resolutionManager)
100+
{
101+
$this->resolutionManager = $resolutionManager;
102+
}
103+
104+
/**
105+
* Solve the dependency resolutions.
106+
*
107+
* @param array $data
108+
*
109+
* @return array
110+
*/
111+
public function solveResolutions(array $data)
112+
{
113+
return null !== $this->resolutionManager
114+
? $this->resolutionManager->solveResolutions($data)
115+
: $data;
116+
}
117+
89118
/**
90119
* Adds asset vcs repositories.
91120
*

‎Repository/NpmRepository.php

+1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ protected function createArrayRepositoryConfig(array $packageConfigs)
139139
foreach ($packageConfigs as $version => $config) {
140140
$config['version'] = $version;
141141
$config = $this->assetType->getPackageConverter()->convert($config);
142+
$config = $this->assetRepositoryManager->solveResolutions($config);
142143
$packages[] = $loader->load($config);
143144
}
144145

‎Repository/ResolutionManager.php

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Fxp Composer Asset Plugin package.
5+
*
6+
* (c) François Pluchino <francois.pluchino@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Fxp\Composer\AssetPlugin\Repository;
13+
14+
/**
15+
* Solve the conflicts of dependencies by the resolutions.
16+
*
17+
* @author François Pluchino <francois.pluchino@gmail.com>
18+
*/
19+
class ResolutionManager
20+
{
21+
/**
22+
* @var array
23+
*/
24+
protected $resolutions;
25+
26+
/**
27+
* Constructor.
28+
*
29+
* @param array $resolutions The dependency resolutions
30+
*/
31+
public function __construct(array $resolutions = array())
32+
{
33+
$this->resolutions = $resolutions;
34+
}
35+
36+
/**
37+
* Solve the dependency resolutions.
38+
*
39+
* @param array $data The data of asset composer package
40+
*
41+
* @return array
42+
*/
43+
public function solveResolutions(array $data)
44+
{
45+
$data = $this->doSolveResolutions($data, 'require');
46+
$data = $this->doSolveResolutions($data, 'require-dev');
47+
48+
return $data;
49+
}
50+
51+
/**
52+
* Solve the dependency resolutions.
53+
*
54+
* @param array $data The data of asset composer package
55+
* @param string $section The dependency section in package
56+
*
57+
* @return array
58+
*/
59+
protected function doSolveResolutions(array $data, $section)
60+
{
61+
if (array_key_exists($section, $data) && is_array($data[$section])) {
62+
foreach ($data[$section] as $dependency => &$range) {
63+
foreach ($this->resolutions as $resolutionDependency => $resolutionRange) {
64+
if ($dependency === $resolutionDependency) {
65+
$range = $resolutionRange;
66+
}
67+
}
68+
}
69+
}
70+
71+
return $data;
72+
}
73+
}

‎Resources/doc/index.md

+45
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,51 @@ You can further define this option for each package:
511511
With this configuration, all your github packages will use the native Git, except for
512512
the `bower-asset/example-asset1` package.
513513

514+
### Solve the conflicts of asset dependencies
515+
516+
Bower include a [resolution section](https://jaketrent.com/post/bower-resolutions) to
517+
solve the conflicts between 2 same dependencies but with different versions.
518+
519+
As for NPM, it's possible to install several versions of the same dependency by different
520+
dependencies, which is not the case for Bower and Composer. Only the installation of a
521+
single version compatible for all dependencies is possible.
522+
523+
The dependency resolution would force (replace) a version or range version directly in the
524+
root Composer package.
525+
526+
**Example:**
527+
```json
528+
"name": "foo/bar",
529+
"require": {
530+
"bower-asset/jquery": "^2.2.0"
531+
}
532+
```
533+
```json
534+
"name": "bar/baz",
535+
"require": {
536+
"bower-asset/jquery": "2.0.*"
537+
}
538+
```
539+
```json
540+
"name": "root/package",
541+
"require": {
542+
"foo/bar": "^1.0.0",
543+
"bar/baz": "^1.0.0"
544+
}
545+
"config": {
546+
"fxp-asset": {
547+
"resolutions": {
548+
"bower-asset/jquery": "^3.0.0"
549+
}
550+
}
551+
}
552+
```
553+
554+
Result, all asset packages with the `bower-asset/jquery` dependency will use the `^3.0.0` range version.
555+
556+
> **Note:**
557+
> Be careful when replacing the version, and check the compatibility before.
558+
514559
### Define the config for all projects
515560

516561
You can define each option (`config.fxp-asset.*`) in each project in the `composer.json`

‎Tests/Package/Loader/LazyAssetPackageLoaderTest.php

+6
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ protected function setUp()
7474
$this->assetRepositoryManager = $this->getMockBuilder(AssetRepositoryManager::class)
7575
->disableOriginalConstructor()->getMock();
7676

77+
$this->assetRepositoryManager->expects($this->any())
78+
->method('solveResolutions')
79+
->willReturnCallback(function ($value) {
80+
return $value;
81+
});
82+
7783
$this->lazyPackage
7884
->expects($this->any())
7985
->method('getName')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Fxp Composer Asset Plugin package.
5+
*
6+
* (c) François Pluchino <francois.pluchino@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Fxp\Composer\AssetPlugin\Tests\Repository;
13+
14+
use Composer\IO\IOInterface;
15+
use Composer\Repository\RepositoryManager;
16+
use Fxp\Composer\AssetPlugin\Repository\AssetRepositoryManager;
17+
use Fxp\Composer\AssetPlugin\Repository\ResolutionManager;
18+
use Fxp\Composer\AssetPlugin\Repository\VcsPackageFilter;
19+
20+
/**
21+
* Tests of Asset Repository Manager.
22+
*
23+
* @author François Pluchino <francois.pluchino@gmail.com>
24+
*/
25+
class AssetRepositoryManagerTest extends \PHPUnit_Framework_TestCase
26+
{
27+
/**
28+
* @var ResolutionManager|\PHPUnit_Framework_MockObject_MockObject
29+
*/
30+
protected $resolutionManager;
31+
32+
/**
33+
* @var AssetRepositoryManager
34+
*/
35+
protected $assertRepositoryManager;
36+
37+
protected function setUp()
38+
{
39+
/* @var IOInterface|\PHPUnit_Framework_MockObject_MockObject $io */
40+
$io = $this->getMockBuilder(IOInterface::class)->getMock();
41+
/* @var RepositoryManager|\PHPUnit_Framework_MockObject_MockObject $rm */
42+
$rm = $this->getMockBuilder(RepositoryManager::class)->disableOriginalConstructor()->getMock();
43+
/* @var VcsPackageFilter|\PHPUnit_Framework_MockObject_MockObject $filter */
44+
$filter = $this->getMockBuilder(VcsPackageFilter::class)->disableOriginalConstructor()->getMock();
45+
46+
$this->resolutionManager = $this->getMockBuilder(ResolutionManager::class)->getMock();
47+
$this->assertRepositoryManager = new AssetRepositoryManager($io, $rm, $filter);
48+
}
49+
50+
public function getDataForSolveResolutions()
51+
{
52+
return array(
53+
array(true),
54+
array(false),
55+
);
56+
}
57+
58+
/**
59+
* @dataProvider getDataForSolveResolutions
60+
*
61+
* @param bool $withResolutionManager
62+
*/
63+
public function testSolveResolutions($withResolutionManager)
64+
{
65+
$expected = array(
66+
'name' => 'foo/bar',
67+
);
68+
69+
if ($withResolutionManager) {
70+
$this->assertRepositoryManager->setResolutionManager($this->resolutionManager);
71+
$this->resolutionManager->expects($this->once())
72+
->method('solveResolutions')
73+
->with($expected)
74+
->willReturn($expected);
75+
} else {
76+
$this->resolutionManager->expects($this->never())
77+
->method('solveResolutions');
78+
}
79+
80+
$data = $this->assertRepositoryManager->solveResolutions($expected);
81+
82+
$this->assertSame($expected, $data);
83+
}
84+
}

‎Tests/Repository/AssetVcsRepositoryTest.php

+6
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ protected function setUp()
6666
$this->assetRepositoryManager = $this->getMockBuilder(AssetRepositoryManager::class)
6767
->disableOriginalConstructor()
6868
->getMock();
69+
70+
$this->assetRepositoryManager->expects($this->any())
71+
->method('solveResolutions')
72+
->willReturnCallback(function ($value) {
73+
return $value;
74+
});
6975
}
7076

7177
protected function tearDown()
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Fxp Composer Asset Plugin package.
5+
*
6+
* (c) François Pluchino <francois.pluchino@gmail.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Fxp\Composer\AssetPlugin\Tests\Repository;
13+
14+
use Fxp\Composer\AssetPlugin\Repository\ResolutionManager;
15+
16+
/**
17+
* Tests of Resolution Manager.
18+
*
19+
* @author François Pluchino <francois.pluchino@gmail.com>
20+
*/
21+
class ResolutionManagerTest extends \PHPUnit_Framework_TestCase
22+
{
23+
public function testSolveResolutions()
24+
{
25+
$rm = new ResolutionManager(array(
26+
'foo/bar' => '^2.2.0',
27+
'bar/foo' => '^0.2.0',
28+
));
29+
30+
$data = $rm->solveResolutions(array(
31+
'require' => array(
32+
'foo/bar' => '2.0.*',
33+
'foo/baz' => '~1.0',
34+
),
35+
'require-dev' => array(
36+
'bar/foo' => '^0.1.0',
37+
'test/dev' => '~1.0@dev',
38+
),
39+
));
40+
41+
$expected = array(
42+
'require' => array(
43+
'foo/bar' => '^2.2.0',
44+
'foo/baz' => '~1.0',
45+
),
46+
'require-dev' => array(
47+
'bar/foo' => '^0.2.0',
48+
'test/dev' => '~1.0@dev',
49+
),
50+
);
51+
52+
$this->assertSame($expected, $data);
53+
}
54+
}

0 commit comments

Comments
 (0)