diff --git a/docs/class_descriptions.md b/docs/class_descriptions.md index 1dd0aff..b177973 100644 --- a/docs/class_descriptions.md +++ b/docs/class_descriptions.md @@ -150,13 +150,17 @@ This is accomplished by comparing `composer.json` fields between the original Ma - **`findResolution()`** - For an individual field value, compare the original Magento value to the target Magento value, and if a delta is found, check if the user's installation has a customized value for the field. If the user has changed the value, resolve the conflict according to the CLI command options: use the user's custom value, override with the target Magento value, or interactively ask the user which of the two values should be used - **`resolveLinkSection()`** - - For a given `composer.json` section that consists of links to package versions/constraints (such as the `require` and `conflict` sections), call `findResolution()` for each package constraint found in either the original Magento root or the target Magento root + - For a given `composer.json` section that consists of links to package versions/constraints (such as the `require` and `conflict` sections), call `findLinkResolution()` for each package constraint found in either the original Magento root or the target Magento root - **`resolveArraySection()`** - For a given `composer.json` section that consists of data that is not package links (such as the `"autoload"` or `"extra"` sections), call `resolveNestedArray()` and accept the new values if changes were made - **`resolveNestedArray()`** - Recursively processes changes to a `composer.json` value that could be a nested array, calling `findResolution()` for each "leaf" value found in either the original Magento root or the target Magento root - - **`linksToMap()`** - - Helper function to convert a set of package links to an associative array for use by `resolveLinkSection()` + - **`findLinkResolution()`** + - Helper function to call `findResolution()` for a particular package for use by `resolveLinkSection()` + - **`getLinkOrderOverride()`** + - Determine the order to use for a link section when the user's order disagrees with the target Magento section order + - **`buildLinkOrderComparator()`** + - Construct the comparator function to use for sorting a set of links according to `getLinkOverride()` results followed by the order in the target Magento version followed by the order of custom values in the user's installation #### [**MagentoRootUpdater**](../src/Magento/ComposerRootUpdatePlugin/Updater/MagentoRootUpdater.php) diff --git a/src/Magento/ComposerRootUpdatePlugin/Updater/DeltaResolver.php b/src/Magento/ComposerRootUpdatePlugin/Updater/DeltaResolver.php index 8fcd429..922e550 100644 --- a/src/Magento/ComposerRootUpdatePlugin/Updater/DeltaResolver.php +++ b/src/Magento/ComposerRootUpdatePlugin/Updater/DeltaResolver.php @@ -89,21 +89,41 @@ public function resolveRootDeltas() $target = $this->targetMageRootPackage; $user = $this->userRootPackage; - $this->resolveLinkSection('require', $original->getRequires(), $target->getRequires(), $user->getRequires()); + $this->resolveLinkSection( + 'require', + $original->getRequires(), + $target->getRequires(), + $user->getRequires(), + true + ); $this->resolveLinkSection( 'require-dev', $original->getDevRequires(), $target->getDevRequires(), - $user->getDevRequires() + $user->getDevRequires(), + true ); $this->resolveLinkSection( 'conflict', $original->getConflicts(), $target->getConflicts(), - $user->getConflicts() + $user->getConflicts(), + false + ); + $this->resolveLinkSection( + 'provide', + $original->getProvides(), + $target->getProvides(), + $user->getProvides(), + false + ); + $this->resolveLinkSection( + 'replace', + $original->getReplaces(), + $target->getReplaces(), + $user->getReplaces(), + false ); - $this->resolveLinkSection('provide', $original->getProvides(), $target->getProvides(), $user->getProvides()); - $this->resolveLinkSection('replace', $original->getReplaces(), $target->getReplaces(), $user->getReplaces()); $this->resolveArraySection('autoload', $original->getAutoload(), $target->getAutoload(), $user->getAutoload()); $this->resolveArraySection( @@ -215,53 +235,26 @@ public function findResolution( * @param Link[] $originalMageLinks * @param Link[] $targetMageLinks * @param Link[] $userLinks + * @param bool $verifyOrder * @return array */ - public function resolveLinkSection($section, $originalMageLinks, $targetMageLinks, $userLinks) + public function resolveLinkSection($section, $originalMageLinks, $targetMageLinks, $userLinks, $verifyOrder) { - /** @var Link[] $originalLinkMap */ - $originalLinkMap = static::linksToMap($originalMageLinks); - - /** @var Link[] $targetLinkMap */ - $targetLinkMap = static::linksToMap($targetMageLinks); - - /** @var Link[] $userLinkMap */ - $userLinkMap = static::linksToMap($userLinks); - $adds = []; $removes = []; $changes = []; - $magePackages = array_unique(array_merge(array_keys($originalLinkMap), array_keys($targetLinkMap))); + $magePackages = array_unique(array_merge(array_keys($originalMageLinks), array_keys($targetMageLinks))); foreach ($magePackages as $pkg) { if ($section === 'require' && PackageUtils::getMagentoProductEdition($pkg)) { continue; } - $field = "$section:$pkg"; - $originalConstraint = key_exists($pkg, $originalLinkMap) ? $originalLinkMap[$pkg]->getConstraint() : null; - $originalMageVal = ($originalConstraint === null) ? null : $originalConstraint->__toString(); - $prettyOriginalMageVal = ($originalConstraint === null) ? null : $originalConstraint->getPrettyString(); - $targetConstraint = key_exists($pkg, $targetLinkMap) ? $targetLinkMap[$pkg]->getConstraint() : null; - $targetMageVal = ($targetConstraint === null) ? null : $targetConstraint->__toString(); - $prettyTargetMageVal = ($targetConstraint === null) ? null : $targetConstraint->getPrettyString(); - $userConstraint = key_exists($pkg, $userLinkMap) ? $userLinkMap[$pkg]->getConstraint() : null; - $userVal = ($userConstraint === null) ? null : $userConstraint->__toString(); - $prettyUserVal = ($userConstraint === null) ? null : $userConstraint->getPrettyString(); - - $action = $this->findResolution( - $field, - $originalMageVal, - $targetMageVal, - $userVal, - $prettyOriginalMageVal, - $prettyTargetMageVal, - $prettyUserVal - ); + $action = $this->findLinkResolution($section, $pkg, $originalMageLinks, $targetMageLinks, $userLinks); if ($action == static::ADD_VAL) { - $adds[$pkg] = $targetLinkMap[$pkg]; + $adds[$pkg] = $targetMageLinks[$pkg]; } elseif ($action == static::REMOVE_VAL) { $removes[] = $pkg; } elseif ($action == static::CHANGE_VAL) { - $changes[$pkg] = $targetLinkMap[$pkg]; + $changes[$pkg] = $targetMageLinks[$pkg]; } } @@ -287,11 +280,26 @@ public function resolveLinkSection($section, $originalMageLinks, $targetMageLink $this->console->labeledVerbose("Updating $section constraints: " . implode(', ', $prettyChanges)); } + $enforcedOrder = []; + if ($verifyOrder) { + $enforcedOrder = $this->getLinkOrderOverride( + $section, + array_keys($originalMageLinks), + array_keys($targetMageLinks), + array_keys($userLinks) + ); + if ($enforcedOrder !== []) { + $changed = true; + $prettyOrder = " [\n " . implode(",\n ", $enforcedOrder) . "\n ]"; + $this->console->labeledVerbose("Updating $section order:\n$prettyOrder"); + } + } + if ($changed) { $replacements = array_values($adds); /** @var Link $userLink */ - foreach ($userLinkMap as $pkg => $userLink) { + foreach ($userLinks as $pkg => $userLink) { if (in_array($pkg, $removes)) { continue; } elseif (key_exists($pkg, $changes)) { @@ -301,6 +309,12 @@ public function resolveLinkSection($section, $originalMageLinks, $targetMageLink } } + usort($replacements, $this->buildLinkOrderComparator( + $enforcedOrder, + array_keys($targetMageLinks), + array_keys($userLinks) + )); + $newJson = []; /** @var Link $link */ foreach ($replacements as $link) { @@ -349,37 +363,15 @@ public function resolveNestedArray($field, $originalMageVal, $targetMageVal, $us $result = $userVal === null ? [] : $userVal; if (is_array($originalMageVal) && is_array($targetMageVal) && is_array($userVal)) { - $originalMageAssociativePart = []; - $originalMageFlatPart = []; - foreach ($originalMageVal as $key => $value) { - if (is_string($key)) { - $originalMageAssociativePart[$key] = $value; - } else { - $originalMageFlatPart[] = $value; - } - } + $originalMageAssociativePart = array_filter($originalMageVal, 'is_string', ARRAY_FILTER_USE_KEY); + $originalMageFlatPart = array_filter($originalMageVal, 'is_int', ARRAY_FILTER_USE_KEY); - $targetMageAssociativePart = []; - $targetMageFlatPart = []; - foreach ($targetMageVal as $key => $value) { - if (is_string($key)) { - $targetMageAssociativePart[$key] = $value; - } else { - $targetMageFlatPart[] = $value; - } - } + $targetMageAssociativePart = array_filter($targetMageVal, 'is_string', ARRAY_FILTER_USE_KEY); + $targetMageFlatPart = array_filter($targetMageVal, 'is_int', ARRAY_FILTER_USE_KEY); - $userAssociativePart = []; - $userFlatPart = []; - foreach ($userVal as $key => $value) { - if (is_string($key)) { - $userAssociativePart[$key] = $value; - } else { - $userFlatPart[] = $value; - } - } + $userAssociativePart = array_filter($userVal, 'is_string', ARRAY_FILTER_USE_KEY); - $associativeResult = array_filter($result, 'is_string', ARRAY_FILTER_USE_KEY); + $associativeResult = $userAssociativePart; $mageKeys = array_unique( array_merge(array_keys($originalMageAssociativePart), array_keys($targetMageAssociativePart)) ); @@ -417,7 +409,7 @@ public function resolveNestedArray($field, $originalMageVal, $targetMageVal, $us } } - $flatResult = array_filter($result, 'is_int', ARRAY_FILTER_USE_KEY); + $flatResult = array_filter($userVal, 'is_int', ARRAY_FILTER_USE_KEY); $flatAdds = array_diff(array_diff($targetMageFlatPart, $originalMageFlatPart), $flatResult); if ($flatAdds !== []) { $valChanged = true; @@ -456,17 +448,132 @@ public function resolveNestedArray($field, $originalMageVal, $targetMageVal, $us } /** - * Helper function to convert a set of links to an associative array with target package names as keys + * Helper function to find the resolution action for a package constraint in the Link sections * - * @param Link[] $links - * @return array + * @param string $section + * @param string $pkg + * @param Link[] $originalLinkMap + * @param Link[] $targetLinkMap + * @param Link[] $userLinkMap + * @return string|null ADD_VAL|REMOVE_VAL|CHANGE_VAL to adjust the link constraint, null for no change */ - protected function linksToMap($links) + protected function findLinkResolution($section, $pkg, $originalLinkMap, $targetLinkMap, $userLinkMap) { - $targets = array_map(function ($link) { - /** @var Link $link */ - return $link->getTarget(); - }, $links); - return array_combine($targets, $links); + $field = "$section:$pkg"; + $originalConstraint = key_exists($pkg, $originalLinkMap) ? $originalLinkMap[$pkg]->getConstraint() : null; + $originalMageVal = ($originalConstraint === null) ? null : $originalConstraint->__toString(); + $prettyOriginalMageVal = ($originalConstraint === null) ? null : $originalConstraint->getPrettyString(); + $targetConstraint = key_exists($pkg, $targetLinkMap) ? $targetLinkMap[$pkg]->getConstraint() : null; + $targetMageVal = ($targetConstraint === null) ? null : $targetConstraint->__toString(); + $prettyTargetMageVal = ($targetConstraint === null) ? null : $targetConstraint->getPrettyString(); + $userConstraint = key_exists($pkg, $userLinkMap) ? $userLinkMap[$pkg]->getConstraint() : null; + $userVal = ($userConstraint === null) ? null : $userConstraint->__toString(); + $prettyUserVal = ($userConstraint === null) ? null : $userConstraint->getPrettyString(); + + return $this->findResolution( + $field, + $originalMageVal, + $targetMageVal, + $userVal, + $prettyOriginalMageVal, + $prettyTargetMageVal, + $prettyUserVal + ); + } + + /** + * Get the order to use for a link section if local and target versions disagree + * + * @param string $section + * @param string[] $originalMageOrder + * @param string[] $targetMageOrder + * @param string[] $userOrder + * @return string[] + */ + protected function getLinkOrderOverride($section, $originalMageOrder, $targetMageOrder, $userOrder) + { + $overrideOrder = []; + + $conflictTargetOrder = array_values(array_intersect($targetMageOrder, $userOrder)); + $conflictUserOrder = array_values(array_intersect($userOrder, $targetMageOrder)); + + // Check if the user's link order does not match the target section for links that appear in both + if ($conflictTargetOrder != $conflictUserOrder) { + $conflictOriginalOrder = array_values(array_intersect($originalMageOrder, $targetMageOrder)); + + // Check if the user's order is different than the target order because the order has changed between + // the original and target Magento versions + if ($conflictOriginalOrder !== $conflictUserOrder) { + $targetLabel = $this->retriever->getTargetLabel(); + $userOrderDesc = " [\n " . implode(",\n ", $conflictUserOrder) . "\n ]"; + $targetOrderDesc = " [\n " . implode(",\n ", $conflictTargetOrder) . "\n ]"; + $conflictDesc = "$targetLabel is trying to change the existing order of the $section section.\n" . + "Local order:\n$userOrderDesc\n$targetLabel order:\n$targetOrderDesc"; + $shouldOverride = $this->overrideUserValues; + if ($this->overrideUserValues) { + $this->console->log($conflictDesc); + $this->console->log( + 'Overriding local order due to --' . MageRootRequireCommand::OVERRIDE_OPT . '.' + ); + } else { + $shouldOverride = $this->console->ask( + "$conflictDesc\nWould you like to override the local order?" + ); + } + + if (!$shouldOverride) { + $this->console->comment("$conflictDesc but it will not be changed. Re-run using " . + '--' . MageRootRequireCommand::OVERRIDE_OPT . ' or ' . + '--' . MageRootRequireCommand::INTERACTIVE_OPT . ' to override with the Magento order.'); + $overrideOrder = $conflictUserOrder; + } else { + $overrideOrder = $conflictTargetOrder; + } + } else { + $overrideOrder = $conflictTargetOrder; + } + } + + return $overrideOrder; + } + + /** + * Construct a comparison function to use in sorting an array of links by prioritized order lists + * + * @param string[] $overrideOrder + * @param string[] $targetMageOrder + * @param string[] $userOrder + * @return \Closure + */ + protected function buildLinkOrderComparator($overrideOrder, $targetMageOrder, $userOrder) + { + $prioritizedOrderings = [$overrideOrder, $targetMageOrder, $userOrder]; + + return function ($link1, $link2) use ($prioritizedOrderings) { + /** + * @var Link $link1 + * @var Link $link2 + */ + $package1 = $link1->getTarget(); + $package2 = $link2->getTarget(); + + // Check each ordering array to see if it contains both links and if so use their positions to sort + // If the ordering array does not contain both links, try the next one + foreach ($prioritizedOrderings as $sortOrder) { + $index1 = array_search($package1, $sortOrder); + $index2 = array_search($package2, $sortOrder); + if ($index1 !== false && $index2 !== false) { + if ($index1 == $index2) { + return 0; + } else { + return $index1 < $index2 ? -1 : 1; + } + } + } + + // None of the ordering arrays contain both elements, so their relative positions in the sorted array + // do not matter + return 0; + }; } } diff --git a/tests/Unit/Magento/ComposerRootUpdatePlugin/UpdatePluginTestCase.php b/tests/Unit/Magento/ComposerRootUpdatePlugin/UpdatePluginTestCase.php index 11847af..247cdc1 100644 --- a/tests/Unit/Magento/ComposerRootUpdatePlugin/UpdatePluginTestCase.php +++ b/tests/Unit/Magento/ComposerRootUpdatePlugin/UpdatePluginTestCase.php @@ -26,7 +26,8 @@ public static function createLinks($count, $target = 'package/name') { $links = []; for ($i = 1; $i <= $count; $i++) { - $links[] = new Link('root/pkg', "$target$i", new Constraint('==', "$i.0.0"), null, "$i.0.0"); + $name = "$target$i"; + $links[$name] = new Link('root/pkg', $name, new Constraint('==', "$i.0.0"), null, "$i.0.0"); } return $links; } @@ -41,12 +42,13 @@ public static function createLinks($count, $target = 'package/name') public static function changeLink($links, $index) { $result = $links; - $changeLink = $links[$index]; + /** @var Link $changeLink */ + $changeLink = array_values($links)[$index]; $version = explode(' ', $changeLink->getConstraint()->getPrettyString())[1]; $versionParts = array_map('intval', explode('.', $version)); $versionParts[1] = $versionParts[1] + 1; $version = implode('.', $versionParts); - $result[$index] = new Link( + $result[$changeLink->getTarget()] = new Link( $changeLink->getSource(), $changeLink->getTarget(), new Constraint('==', $version), @@ -66,58 +68,30 @@ public static function changeLink($links, $index) public static function assertLinksEqual($expected, $jsonChanges) { static::assertEquals(count($expected), count($jsonChanges)); - while (count($expected) > 0) { - $expectedLink = array_shift($expected); - $expectedTarget = $expectedLink->getTarget(); - $expectedConstraint = $expectedLink->getConstraint()->getPrettyString(); - $found = null; - foreach ($jsonChanges as $target => $constraint) { - if ($target === $expectedTarget && - $constraint === $expectedConstraint) { - $found = $target; - break; - } - } - static::assertNotEmpty($found, "Could not find a link matching $expectedLink"); - unset($jsonChanges[$found]); + $remainingJson = $jsonChanges; + foreach ($expected as $expectedTarget => $expectedLink) { + $expectedTarget = strtolower($expectedTarget); + static::assertArrayHasKey($expectedTarget, $remainingJson); + static::assertEquals($expectedLink->getConstraint()->getPrettyString(), $remainingJson[$expectedTarget]); + unset($remainingJson[$expectedTarget]); } } /** - * Assert that two arrays of links are not equal without checking order - * + * Assert that the links in the $jsonChanges are ordered as expected + * @param Link[] $expected - * @param Link[] $actual + * @param array $jsonChanges * @return void */ - public static function assertLinksNotEqual($expected, $actual) + public static function assertLinksOrdered($expected, $jsonChanges) { - if (count($expected) !== count($actual)) { - static::assertNotEquals(count($expected), count($actual)); - return; - } - - while (count($expected) > 0) { - $expectedLink = array_shift($expected); - $expectedSource = $expectedLink->getSource(); - $expectedTarget = $expectedLink->getTarget(); - $expectedConstraint = $expectedLink->getConstraint()->getPrettyString(); - $found = -1; - foreach ($actual as $key => $actualLink) { - if ($actualLink->getSource() === $expectedSource && - $actualLink->getTarget() === $expectedTarget && - $actualLink->getConstraint()->getPrettyString() === $expectedConstraint) { - $found = $key; - break; - } - } - if ($found === -1) { - static::assertEquals(-1, $found); - return; - } - unset($actual[$found]); - } - static::fail('Expected Link sets to not be equal'); + $expectedOrder = array_map(function ($link) { + /** @var Link $link */ + return $link->getTarget(); + }, array_values($expected)); + $actualOrder = array_keys($jsonChanges); + static::assertEquals($expectedOrder, $actualOrder); } /** diff --git a/tests/Unit/Magento/ComposerRootUpdatePlugin/Updater/DeltaResolverTest.php b/tests/Unit/Magento/ComposerRootUpdatePlugin/Updater/DeltaResolverTest.php index f1d64ac..2868e85 100644 --- a/tests/Unit/Magento/ComposerRootUpdatePlugin/Updater/DeltaResolverTest.php +++ b/tests/Unit/Magento/ComposerRootUpdatePlugin/Updater/DeltaResolverTest.php @@ -324,7 +324,8 @@ public function testResolveLinksAddLink() 'require', $originalMageLinks, $targetMageLinks, - $userLinks + $userLinks, + false ); $this->assertLinksEqual($expected, $result['require']); @@ -343,7 +344,8 @@ public function testResolveLinksRemoveLink() 'require', $originalMageLinks, $targetMageLinks, - $userLinks + $userLinks, + false ); $this->assertLinksEqual($expected, $result['require']); @@ -362,12 +364,99 @@ public function testResolveLinksChangeLink() 'require', $originalMageLinks, $targetMageLinks, - $userLinks + $userLinks, + false ); $this->assertLinksEqual($expected, $result['require']); } + public function testResolveLinksUpdateOrder() + { + $orderedLinks = $this->createLinks(4, 'target/link'); + $reorderedLinks = array_reverse($orderedLinks); + $targetMageLinks = array_merge($this->createLinks(1), $orderedLinks); + $originalMageLinks = array_merge($this->createLinks(2), $reorderedLinks); + + $resolver = new DeltaResolver($this->console, true, $this->retriever); + $result = $resolver->resolveLinkSection( + 'require', + $originalMageLinks, + $targetMageLinks, + $originalMageLinks, + true + ); + + $this->assertLinksEqual($targetMageLinks, $result['require']); + $this->assertLinksOrdered($targetMageLinks, $result['require']); + } + + public function testResolveLinksAddLinkWithOrder() + { + $targetMageLinks = array_merge($this->createLinks(3), $this->createLinks(4, 'target/link')); + $originalMageLinks = array_merge($this->createLinks(2), $this->createLinks(4, 'target/link')); + + $resolver = new DeltaResolver($this->console, true, $this->retriever); + $result = $resolver->resolveLinkSection( + 'require', + $originalMageLinks, + $targetMageLinks, + $originalMageLinks, + true + ); + + $this->assertLinksEqual($targetMageLinks, $result['require']); + $this->assertLinksOrdered($targetMageLinks, $result['require']); + } + + public function testResolveLinksOrderOverride() + { + $orderedLinks = $this->createLinks(4, 'target/link'); + $reorderedLinks = array_reverse($orderedLinks); + $originalMageLinks = $this->createLinks(2); + $targetMageLinks = array_merge($originalMageLinks, $orderedLinks); + $userLinks = array_merge($originalMageLinks, $reorderedLinks); + + $this->io->expects($this->at(1))->method('writeError') + ->with($this->stringContains('overriding local order')); + + $resolver = new DeltaResolver($this->console, true, $this->retriever); + $result = $resolver->resolveLinkSection( + 'require', + $originalMageLinks, + $targetMageLinks, + $userLinks, + true + ); + + $this->assertLinksEqual($targetMageLinks, $result['require']); + $this->assertLinksOrdered($targetMageLinks, $result['require']); + } + + public function testResolveLinksOrderNoOverride() + { + $orderedLinks = $this->createLinks(4, 'target/link'); + $reorderedLinks = array_reverse($orderedLinks); + $originalMageLinks = $this->createLinks(2); + $targetMageLinks = array_merge($originalMageLinks, $orderedLinks); + $userLinks = array_merge($originalMageLinks, $reorderedLinks); + + $this->io->expects($this->at(0))->method('writeError') + ->with($this->stringContains('will not be changed')); + + $resolver = new DeltaResolver($this->console, false, $this->retriever); + $result = $resolver->resolveLinkSection( + 'require', + $originalMageLinks, + $targetMageLinks, + $userLinks, + true + ); + + $this->assertLinksEqual($userLinks, $result['require']); + $this->assertLinksOrdered($userLinks, $result['require']); + } + public function setUp() { $this->io = $this->getMockForAbstractClass(IOInterface::class); diff --git a/tests/Unit/Magento/ComposerRootUpdatePlugin/Updater/MagentoRootUpdaterTest.php b/tests/Unit/Magento/ComposerRootUpdatePlugin/Updater/MagentoRootUpdaterTest.php index 23f46b6..2120739 100644 --- a/tests/Unit/Magento/ComposerRootUpdatePlugin/Updater/MagentoRootUpdaterTest.php +++ b/tests/Unit/Magento/ComposerRootUpdatePlugin/Updater/MagentoRootUpdaterTest.php @@ -79,7 +79,9 @@ public function testMagentoUpdateSetsFieldsNoOverride() $result = $updater->getJsonChanges(); $this->assertLinksEqual($this->expectedNoOverride->getRequires(), $result['require']); + $this->assertLinksOrdered($this->expectedNoOverride->getRequires(), $result['require']); $this->assertLinksEqual($this->expectedNoOverride->getDevRequires(), $result['require-dev']); + $this->assertLinksOrdered($this->expectedNoOverride->getDevRequires(), $result['require-dev']); $this->assertEquals($this->expectedNoOverride->getAutoload(), $result['autoload']); $this->assertEquals($this->expectedNoOverride->getDevAutoload(), $result['autoload-dev']); $this->assertLinksEqual($this->expectedNoOverride->getConflicts(), $result['conflict']); @@ -96,7 +98,9 @@ public function testMagentoUpdateSetsFieldsWithOverride() $result = $updater->getJsonChanges(); $this->assertLinksEqual($this->expectedWithOverride->getRequires(), $result['require']); + $this->assertLinksOrdered($this->expectedWithOverride->getRequires(), $result['require']); $this->assertLinksEqual($this->expectedWithOverride->getDevRequires(), $result['require-dev']); + $this->assertLinksOrdered($this->expectedWithOverride->getDevRequires(), $result['require-dev']); $this->assertEquals($this->expectedWithOverride->getAutoload(), $result['autoload']); $this->assertEquals($this->expectedWithOverride->getDevAutoload(), $result['autoload-dev']); $this->assertLinksEqual($this->expectedWithOverride->getConflicts(), $result['conflict']); @@ -113,9 +117,22 @@ public function setUp() */ $baseRoot = new RootPackage('magento/project-community-edition', '1.0.0.0', '1.0.0'); $baseRoot->setRequires([ - new Link('root/pkg', 'magento/product-community-edition', new Constraint('==', '1.0.0'), null, '1.0.0'), - new Link('root/pkg', PluginDefinition::PACKAGE_NAME, new Constraint('==', '1.0.0.0')), - new Link('root/pkg', 'vendor/package1', new Constraint('==', '1.0.0'), null, '1.0.0') + 'magento/product-community-edition' => new Link( + 'root/pkg', 'magento/product-community-edition', + new Constraint('==', '1.0.0'), null, '1.0.0' + ), + PluginDefinition::PACKAGE_NAME => new Link( + 'root/pkg', + PluginDefinition::PACKAGE_NAME, + new Constraint('==', '1.0.0.0') + ), + 'vendor/package1' => new Link( + 'root/pkg', + 'vendor/package1', + new Constraint('==', '1.0.0'), + null, + '1.0.0' + ) ]); $baseRoot->setDevRequires($this->createLinks(2, 'vendor/dev-package')); $baseRoot->setAutoload(['psr-4' => ['Magento\\' => 'src/Magento/']]); @@ -128,11 +145,26 @@ public function setUp() $targetRoot = new RootPackage('magento/project-community-edition', '2.0.0.0', '2.0.0'); $targetRoot->setRequires([ - new Link('root/pkg', 'magento/product-community-edition', new Constraint('==', '2.0.0'), null, '2.0.0'), - new Link('root/pkg', PluginDefinition::PACKAGE_NAME, new Constraint('==', '1.0.0.0')), - new Link('root/pkg', 'vendor/package1', new Constraint('==', '2.0.0'), null, '2.0.0') + 'magento/product-community-edition' => new Link( + 'root/pkg', + 'magento/product-community-edition', + new Constraint('==', '2.0.0'), + null, + '2.0.0' + ), + PluginDefinition::PACKAGE_NAME => new Link( + 'root/pkg', + PluginDefinition::PACKAGE_NAME, + new Constraint('==', '1.0.0.0') + ), + 'vendor/package1' => new Link( + 'root/pkg', + 'vendor/package1', + new Constraint('==', '2.0.0'), + null, '2.0.0' + ) ]); - $targetRoot->setDevRequires($this->createLinks(1, 'vendor/dev-package')); + $targetRoot->setDevRequires(array_merge($this->createLinks(1, 'vendor/dev-package-new'), $this->createLinks(2, 'vendor/dev-package'))); $targetRoot->setAutoload(['psr-4' => [ 'Magento\\' => 'src/Magento/', 'Zend\\Mvc\\Controller\\'=> 'setup/src/Zend/Mvc/Controller/' @@ -146,9 +178,24 @@ public function setUp() $installRoot = new RootPackage('magento/project-community-edition', '1.0.0.0', '1.0.0'); $installRoot->setRequires([ - new Link('root/pkg', 'magento/product-community-edition', new Constraint('==', '2.0.0'), null, '2.0.0'), - new Link('root/pkg', PluginDefinition::PACKAGE_NAME, new Constraint('==', '1.0.0.0')), - new Link('root/pkg', 'vendor/package1', new Constraint('==', '1.0.0'), null, '1.0.0') + 'magento/product-community-edition' => new Link( + 'root/pkg', + 'magento/product-community-edition', + new Constraint('==', '2.0.0'), + null, + '2.0.0' + ), + PluginDefinition::PACKAGE_NAME => new Link( + 'root/pkg', + PluginDefinition::PACKAGE_NAME, + new Constraint('==', '1.0.0.0') + ), + 'vendor/package1' => new Link( + 'root/pkg', + 'vendor/package1', + new Constraint('==', '1.0.0'), + null, '1.0.0' + ) ]); $installRoot->setDevRequires($baseRoot->getDevRequires()); $installRoot->setAutoload(array_merge($baseRoot->getAutoload(), ['files' => 'app/etc/Register.php'])); @@ -179,8 +226,10 @@ public function setUp() 'Magento\\Sniffs\\' => 'dev/tests/framework/Magento/Sniffs/', 'Magento\\Tools\\' => 'dev/tools/Magento/Tools2/' ]]); + /** @var Link $newConflict */ + $newConflict = array_values($targetRoot->getConflicts())[2]; $expectedNoOverride->setConflicts( - array_merge($this->installRoot->getConflicts(), [$targetRoot->getConflicts()[2]]) + array_merge($this->installRoot->getConflicts(), [$newConflict->getTarget() => $newConflict]) ); $noOverrideExtra = $targetRoot->getExtra(); $noOverrideExtra['extra-key1'] = $this->installRoot->getExtra()['extra-key1'];