22
22
use Composer \Package \Package ;
23
23
use Composer \Package \RootPackageInterface ;
24
24
use Composer \Plugin \PluginInterface ;
25
+ use Composer \Repository \RepositoryInterface ;
25
26
use Composer \Repository \RepositoryManager ;
26
27
use Composer \Repository \WritableRepositoryInterface ;
27
28
use Composer \Script \Event ;
@@ -213,6 +214,96 @@ public function testFetchRecipesOrder()
213
214
], array_keys ($ recipes ));
214
215
}
215
216
217
+ public function testFetchRecipesWithConflicts ()
218
+ {
219
+ $ originalRecipes = [
220
+ 'locks ' => [
221
+ 'doctrine/annotations ' => [
222
+ 'version ' => '1.13 ' ,
223
+ 'recipe ' => [
224
+ 'version ' => '1.0 ' ,
225
+ ],
226
+ ],
227
+ 'doctrine/doctrine-bundle ' => [
228
+ 'version ' => '2.5 ' ,
229
+ 'recipe ' => [
230
+ 'version ' => '2.4 ' ,
231
+ ],
232
+ ],
233
+ ],
234
+ 'manifests ' => [
235
+ 'doctrine/annotations ' => [
236
+ 'version ' => '1.0 ' ,
237
+ 'manifest ' => [],
238
+ ],
239
+ 'doctrine/doctrine-bundle ' => [
240
+ 'version ' => '2.4 ' ,
241
+ 'manifest ' => [
242
+ 'conflict ' => [
243
+ 'symfony/framework-bundle ' => '<5.3 ' ,
244
+ ],
245
+ ],
246
+ ],
247
+ ],
248
+ ];
249
+ $ oldRecipes = [
250
+ 'locks ' => [
251
+ 'doctrine/doctrine-bundle ' => [
252
+ // 2.5 is still being installed, but 2.3 recipe used
253
+ 'version ' => '2.5 ' ,
254
+ 'recipe ' => [
255
+ 'version ' => '2.3 ' ,
256
+ ],
257
+ ],
258
+ ],
259
+ 'manifests ' => [
260
+ 'doctrine/doctrine-bundle ' => [
261
+ 'version ' => '2.3 ' ,
262
+ 'manifest ' => [],
263
+ ],
264
+ ],
265
+ ];
266
+
267
+ $ io = new BufferIO ('' , OutputInterface::VERBOSITY_VERBOSE );
268
+ $ rootPackage = $ this ->mockRootPackage (['symfony ' => ['allow-contrib ' => true ]]);
269
+
270
+ $ downloader = $ this ->getMockBuilder (Downloader::class)->disableOriginalConstructor ()->getMock ();
271
+ $ downloader ->expects ($ this ->exactly (2 ))
272
+ ->method ('getRecipes ' )
273
+ ->willReturnOnConsecutiveCalls ($ originalRecipes , $ oldRecipes );
274
+ $ downloader ->expects ($ this ->any ())->method ('isEnabled ' )->willReturn (true );
275
+ $ downloader ->expects ($ this ->once ())->method ('removeRecipeFromIndex ' )->with ('doctrine/doctrine-bundle ' , '2.4 ' );
276
+
277
+ $ locker = $ this ->getMockBuilder (Locker::class)->disableOriginalConstructor ()->getMock ();
278
+ $ lockedRepository = $ this ->getMockBuilder (RepositoryInterface::class)->disableOriginalConstructor ()->getMock ();
279
+ // make the conflicted package show up
280
+ $ locker ->expects ($ this ->any ())
281
+ ->method ('getLockedRepository ' )
282
+ ->willReturn ($ lockedRepository );
283
+ $ lockedRepository ->expects ($ this ->once ())
284
+ ->method ('findPackage ' )
285
+ ->with ('symfony/framework-bundle ' , '<5.3 ' )
286
+ ->willReturn (new Package ('symfony/framework-bundle ' , '5.2.0 ' , '5.2.0 ' ));
287
+ $ composer = $ this ->mockComposer ($ locker , $ rootPackage );
288
+ $ configurator = $ this ->mockConfigurator ();
289
+ $ lock = $ this ->mockLock ();
290
+ $ flex = $ this ->mockFlexCustom ($ io , $ composer , $ configurator , $ downloader , $ lock );
291
+
292
+ $ operations = [];
293
+ foreach ($ originalRecipes ['manifests ' ] as $ name => $ recipeData ) {
294
+ $ package = new Package ($ name , $ recipeData ['version ' ], $ recipeData ['version ' ]);
295
+
296
+ $ operations [] = new InstallOperation ($ package );
297
+ }
298
+ $ recipes = $ flex ->fetchRecipes ($ operations , true );
299
+
300
+ $ this ->assertSame ([
301
+ 'doctrine/annotations ' ,
302
+ 'doctrine/doctrine-bundle ' ,
303
+ ], array_keys ($ recipes ));
304
+ $ this ->assertSame ('2.3 ' , $ recipes ['doctrine/doctrine-bundle ' ]->getVersion ());
305
+ }
306
+
216
307
public static function getTestPackages (): array
217
308
{
218
309
return [
@@ -358,14 +449,8 @@ private function mockManager(): RepositoryManager
358
449
return $ manager ;
359
450
}
360
451
361
- private function mockFlex (BufferIO $ io , RootPackageInterface $ package , Recipe $ recipe = null , array $ recipes = [], array $ lockerData = [] ): Flex
452
+ private function mockFlexCustom (BufferIO $ io , Composer $ composer , Configurator $ configurator , Downloader $ downloader , Lock $ lock ): Flex
362
453
{
363
- $ composer = $ this ->mockComposer ($ this ->mockLocker ($ lockerData ), $ package );
364
-
365
- $ configurator = $ this ->mockConfigurator ($ recipe );
366
- $ downloader = $ this ->mockDownloader ($ recipes );
367
- $ lock = $ this ->mockLock ();
368
-
369
454
return \Closure::bind (function () use ($ composer , $ io , $ configurator , $ downloader , $ lock ) {
370
455
$ flex = new Flex ();
371
456
$ flex ->composer = $ composer ;
@@ -381,4 +466,15 @@ private function mockFlex(BufferIO $io, RootPackageInterface $package, Recipe $r
381
466
return $ flex ;
382
467
}, null , Flex::class)->__invoke ();
383
468
}
469
+
470
+ private function mockFlex (BufferIO $ io , RootPackageInterface $ package , Recipe $ recipe = null , array $ recipes = [], array $ lockerData = []): Flex
471
+ {
472
+ $ composer = $ this ->mockComposer ($ this ->mockLocker ($ lockerData ), $ package );
473
+
474
+ $ configurator = $ this ->mockConfigurator ($ recipe );
475
+ $ downloader = $ this ->mockDownloader ($ recipes );
476
+ $ lock = $ this ->mockLock ();
477
+
478
+ return $ this ->mockFlexCustom ($ io , $ composer , $ configurator , $ downloader , $ lock );
479
+ }
384
480
}
0 commit comments