Skip to content

Commit bfed1f8

Browse files
committed
Merge pull request wikimedia#93 from bd808/feature/require
Add support for required files
2 parents 7eca510 + f408180 commit bfed1f8

File tree

9 files changed

+148
-10
lines changed

9 files changed

+148
-10
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ Usage
4343
"composer.local.json",
4444
"extensions/*/composer.json"
4545
],
46+
"require": [
47+
"submodule/composer.json"
48+
],
4649
"recurse": true,
4750
"replace": false,
4851
"merge-dev": true,
@@ -87,6 +90,11 @@ in the top-level composer.json file:
8790
(optional, see [merge-extra](#merge-extra) below)
8891

8992

93+
### require
94+
95+
The `require` setting is identical to `[include](#include)` except when
96+
a pattern fails to match at least one file then it will cause an error.
97+
9098
### recurse
9199

92100
By default the merge plugin is recursive; if an included file has

src/Merge/ExtraPackage.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,17 @@ public function getIncludes()
8383
$this->json['extra']['merge-plugin']['include'] : array();
8484
}
8585

86+
/**
87+
* Get list of additional packages to require if precessing recursively.
88+
*
89+
* @return array
90+
*/
91+
public function getRequires()
92+
{
93+
return isset($this->json['extra']['merge-plugin']['require']) ?
94+
$this->json['extra']['merge-plugin']['require'] : array();
95+
}
96+
8697
/**
8798
* Read the contents of a composer.json style file into an array.
8899
*

src/Merge/MissingFileException.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
/**
3+
* This file is part of the Composer Merge plugin.
4+
*
5+
* Copyright (C) 2015 Bryan Davis, Wikimedia Foundation, and contributors
6+
*
7+
* This software may be modified and distributed under the terms of the MIT
8+
* license. See the LICENSE file for details.
9+
*/
10+
11+
namespace Wikimedia\Composer\Merge;
12+
13+
/**
14+
* @author Bryan Davis <bd808@bd808.com>
15+
*/
16+
class MissingFileException extends \RuntimeException
17+
{
18+
}

src/Merge/PluginState.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ class PluginState
2929
*/
3030
protected $includes = array();
3131

32+
/**
33+
* @var array $requires
34+
*/
35+
protected $requires = array();
36+
3237
/**
3338
* @var array $duplicateLinks
3439
*/
@@ -106,6 +111,7 @@ public function loadSettings()
106111
$config = array_merge(
107112
array(
108113
'include' => array(),
114+
'require' => array(),
109115
'recurse' => true,
110116
'replace' => false,
111117
'merge-dev' => true,
@@ -116,6 +122,8 @@ public function loadSettings()
116122

117123
$this->includes = (is_array($config['include'])) ?
118124
$config['include'] : array($config['include']);
125+
$this->requires = (is_array($config['require'])) ?
126+
$config['require'] : array($config['require']);
119127
$this->recurse = (bool)$config['recurse'];
120128
$this->replace = (bool)$config['replace'];
121129
$this->mergeDev = (bool)$config['merge-dev'];
@@ -132,6 +140,16 @@ public function getIncludes()
132140
return $this->includes;
133141
}
134142

143+
/**
144+
* Get list of filenames and/or glob patterns to require
145+
*
146+
* @return array
147+
*/
148+
public function getRequires()
149+
{
150+
return $this->requires;
151+
}
152+
135153
/**
136154
* Set the first install flag
137155
*

src/MergePlugin.php

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
namespace Wikimedia\Composer;
1212

1313
use Wikimedia\Composer\Merge\ExtraPackage;
14+
use Wikimedia\Composer\Merge\MissingFileException;
1415
use Wikimedia\Composer\Merge\PluginState;
1516

1617
use Composer\Composer;
@@ -144,7 +145,8 @@ public function onInstallUpdateOrDump(Event $event)
144145
{
145146
$this->state->loadSettings();
146147
$this->state->setDevMode($event->isDevMode());
147-
$this->mergeIncludes($this->state->getIncludes());
148+
$this->mergeFiles($this->state->getIncludes(), false);
149+
$this->mergeFiles($this->state->getRequires(), true);
148150

149151
if ($event->getName() === ScriptEvents::PRE_AUTOLOAD_DUMP) {
150152
$this->state->setDumpAutoloader(true);
@@ -159,16 +161,29 @@ public function onInstallUpdateOrDump(Event $event)
159161
* Find configuration files matching the configured glob patterns and
160162
* merge their contents with the master package.
161163
*
162-
* @param array $includes List of files/glob patterns
164+
* @param array $patterns List of files/glob patterns
165+
* @param bool $required Are the patterns required to match files?
166+
* @throws MissingFileException when required and a pattern returns no
167+
* results
163168
*/
164-
protected function mergeIncludes(array $includes)
169+
protected function mergeFiles(array $patterns, $required = false)
165170
{
166171
$root = $this->composer->getPackage();
167-
foreach (array_reduce(
168-
array_map('glob', $includes),
169-
'array_merge',
170-
array()
171-
) as $path) {
172+
173+
$files = array_map(
174+
function ($files, $pattern) use ($required) {
175+
if ($required && !$files) {
176+
throw new MissingFileException(
177+
"merge-plugin: No files matched required '{$pattern}'"
178+
);
179+
}
180+
return $files;
181+
},
182+
array_map('glob', $patterns),
183+
$patterns
184+
);
185+
186+
foreach (array_reduce($files, 'array_merge', array()) as $path) {
172187
$this->mergeFile($root, $path);
173188
}
174189
}
@@ -193,7 +208,8 @@ protected function mergeFile(RootPackageInterface $root, $path)
193208
$package->mergeInto($root, $this->state);
194209

195210
if ($this->state->recurseIncludes()) {
196-
$this->mergeIncludes($package->getIncludes());
211+
$this->mergeFiles($package->getIncludes(), false);
212+
$this->mergeFiles($package->getRequires(), true);
197213
}
198214
}
199215

tests/phpunit/MergePluginTest.php

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,6 @@ function ($args) use ($that) {
188188
}
189189

190190

191-
192191
/**
193192
* Given a root package with no requires
194193
* and a composer.local.json with one require, which includes a composer.local.2.json
@@ -225,6 +224,7 @@ function ($args) use (&$packages) {
225224
$this->assertEquals(0, count($extraInstalls));
226225
}
227226

227+
228228
/**
229229
* Given a root package with no requires that disables recursion
230230
* and a composer.local.json with one require, which includes a composer.local.2.json
@@ -261,6 +261,7 @@ function ($args) use (&$packages) {
261261
$this->assertEquals(0, count($extraInstalls));
262262
}
263263

264+
264265
/**
265266
* Given a root package with requires
266267
* and a composer.local.json with requires
@@ -311,6 +312,7 @@ function ($args) use ($that) {
311312
$this->assertEquals('foo', $extraInstalls[1][0]);
312313
}
313314

315+
314316
/**
315317
* Given a root package
316318
* and a composer.local.json with a repository
@@ -391,6 +393,7 @@ function ($args) use ($that) {
391393
$this->assertEquals(0, count($extraInstalls));
392394
}
393395

396+
394397
/**
395398
* Given a root package
396399
* and a composer.local.json with required packages
@@ -449,6 +452,7 @@ function ($args) use ($that, &$expects) {
449452
$this->assertEquals(0, count($extraInstalls));
450453
}
451454

455+
452456
public function testMergedAutoload()
453457
{
454458
$that = $this;
@@ -528,6 +532,7 @@ function ($args) use ($that) {
528532
);
529533
}
530534

535+
531536
/**
532537
* Given a root package with an extra section
533538
* and a composer.local.json with an extra section with no conflicting keys
@@ -564,6 +569,7 @@ function ($args) use ($that) {
564569
$this->assertEquals(0, count($extraInstalls));
565570
}
566571

572+
567573
/**
568574
* Given a root package with an extra section
569575
* and a composer.local.json with an extra section with a conflicting key
@@ -600,6 +606,7 @@ function ($args) use ($that) {
600606
$this->assertEquals(0, count($extraInstalls));
601607
}
602608

609+
603610
/**
604611
* Given a root package with an extra section
605612
* and replace mode is active
@@ -637,6 +644,7 @@ function ($args) use ($that) {
637644
$this->assertEquals(0, count($extraInstalls));
638645
}
639646

647+
640648
/**
641649
* @dataProvider provideOnPostPackageInstall
642650
* @param string $package Package installed
@@ -665,6 +673,7 @@ public function testOnPostPackageInstall($package, $first, $locked)
665673
$this->assertEquals($locked, $this->getState()->isLocked());
666674
}
667675

676+
668677
public function provideOnPostPackageInstall()
669678
{
670679
return array(
@@ -674,6 +683,7 @@ public function provideOnPostPackageInstall()
674683
);
675684
}
676685

686+
677687
/**
678688
* Given a root package with a branch alias
679689
* When the plugin is run
@@ -768,6 +778,7 @@ function ($args) use ($that, &$expects) {
768778
$extraInstalls = $this->triggerPlugin($root->reveal(), $dir);
769779
}
770780

781+
771782
/**
772783
* Test replace link with self.version as version constraint.
773784
*/
@@ -856,6 +867,7 @@ function ($args) use ($that, &$expects) {
856867
$extraInstalls = $this->triggerPlugin($root->reveal(), $dir);
857868
}
858869

870+
859871
/**
860872
* Given a root package with merge-dev=false
861873
* and an include with require-dev and autoload-dev sections
@@ -884,6 +896,39 @@ function ($args) use ($that) {
884896
}
885897

886898

899+
/**
900+
* @expectedException \Wikimedia\Composer\Merge\MissingFileException
901+
*/
902+
public function testMissingRequireThrowsException()
903+
{
904+
$dir = $this->fixtureDir(__FUNCTION__);
905+
$root = $this->rootFromJson("{$dir}/composer.json");
906+
$root->getRequires()->shouldNotBeCalled();
907+
$this->triggerPlugin($root->reveal(), $dir);
908+
}
909+
910+
911+
public function testRequire()
912+
{
913+
$that = $this;
914+
$dir = $this->fixtureDir(__FUNCTION__);
915+
916+
$root = $this->rootFromJson("{$dir}/composer.json");
917+
918+
$root->setRequires(Argument::type('array'))->will(
919+
function ($args) use ($that) {
920+
$requires = $args[0];
921+
$that->assertEquals(1, count($requires));
922+
$that->assertArrayHasKey('monolog/monolog', $requires);
923+
}
924+
);
925+
926+
$extraInstalls = $this->triggerPlugin($root->reveal(), $dir);
927+
928+
$this->assertEquals(0, count($extraInstalls));
929+
}
930+
931+
887932
/**
888933
* @param RootPackage $package
889934
* @param string $directory Working directory for composer run
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"require": {
3+
"wikimedia/composer-merge-plugin": "dev-master"
4+
},
5+
"extra": {
6+
"merge-plugin": {
7+
"require": "glob/*.json"
8+
}
9+
}
10+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"extra": {
3+
"merge-plugin": {
4+
"require": "composer.local.json"
5+
}
6+
}
7+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"require": {
3+
"monolog/monolog": "^1.0"
4+
}
5+
}

0 commit comments

Comments
 (0)