diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index c32abc4..4ffd0ac 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -19,7 +19,11 @@ jobs:
- '7.3'
- '7.4'
- '8.0'
+ - '8.1'
include:
+ - php-versions: '7.0'
+ composer-flags: '--prefer-lowest'
+ operating-system: ubuntu-latest
- php-versions: '5.3'
composer-flags: '--prefer-lowest'
operating-system: ubuntu-latest
@@ -50,15 +54,14 @@ jobs:
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
- name: Run mutation tests
- if: ${{ matrix.php-versions == 7.4 && matrix.operating-system == 'ubuntu-latest' }}
+ if: ${{ matrix.php-versions == 8.0 && matrix.operating-system == 'ubuntu-latest' }}
env:
STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }}
run: |
composer req infection/infection
vendor/bin/infection --ignore-msi-with-no-mutations --min-covered-msi=100 --min-msi=100 -s -j4
- name: Run phpstan
- if: ${{ matrix.php-versions >= 7.1 && matrix.php-versions < 8.0 }}
+ if: ${{ matrix.php-versions == 8.0 && matrix.operating-system == 'ubuntu-latest' }}
run: |
composer req phpstan/phpstan
- vendor/bin/phpstan analyse src -l 6
-
+ vendor/bin/phpstan
diff --git a/README.md b/README.md
index abd6bab..f512408 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,10 @@
# Composer Diff Plugin
+[](https://packagist.org/packages/ion-bazan/composer-diff)
+[](https://packagist.org/packages/ion-bazan/composer-diff)
+[](https://packagist.org/packages/ion-bazan/composer-diff)
[](https://packagist.org/packages/ion-bazan/composer-diff)
[](https://github.com/IonBazan/composer-diff/actions)
-[](https://packagist.org/packages/ion-bazan/composer-diff)
[](https://codecov.io/gh/IonBazan/composer-diff)
[](https://dashboard.stryker-mutator.io/reports/github.com/IonBazan/composer-diff/master)
[](https://packagist.org/packages/ion-bazan/composer-diff)
diff --git a/composer.json b/composer.json
index 4aa3ddc..3947560 100644
--- a/composer.json
+++ b/composer.json
@@ -37,7 +37,7 @@
"platform-check": false
},
"extra": {
- "class": "IonBazan\\ComposerDiff\\Plugin"
+ "class": "IonBazan\\ComposerDiff\\Composer\\Plugin"
},
"autoload": {
"psr-4": {
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 0000000..99b1de4
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,6 @@
+parameters:
+ level: 6
+ paths:
+ - src
+ checkGenericClassInNonGenericObjectType: true
+ checkMissingIterableValueType: true
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 1f10f73..a245aa7 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -16,6 +16,7 @@
>
+
diff --git a/src/Command/DiffCommand.php b/src/Command/DiffCommand.php
index 4b92702..238a77b 100644
--- a/src/Command/DiffCommand.php
+++ b/src/Command/DiffCommand.php
@@ -3,8 +3,8 @@
namespace IonBazan\ComposerDiff\Command;
use Composer\Command\BaseCommand;
-use Composer\DependencyResolver\Operation\OperationInterface;
-use Composer\DependencyResolver\Operation\UpdateOperation;
+use IonBazan\ComposerDiff\Diff\DiffEntries;
+use IonBazan\ComposerDiff\Diff\DiffEntry;
use IonBazan\ComposerDiff\Formatter\Formatter;
use IonBazan\ComposerDiff\Formatter\JsonFormatter;
use IonBazan\ComposerDiff\Formatter\MarkdownListFormatter;
@@ -133,8 +133,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
$formatter = $this->getFormatter($input, $output);
- $prodOperations = array();
- $devOperations = array();
+ $prodOperations = new DiffEntries(array());
+ $devOperations = new DiffEntries(array());
if (!$input->getOption('no-prod')) {
$prodOperations = $this->packageDiff->getPackageDiff($base, $target, false, $withPlatform);
@@ -150,27 +150,24 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
/**
- * @param OperationInterface[] $prodOperations
- * @param OperationInterface[] $devOperations
- *
* @return int Exit code
*/
- private function getExitCode(array $prodOperations, array $devOperations)
+ private function getExitCode(DiffEntries $prodEntries, DiffEntries $devEntries)
{
$exitCode = 0;
- if (!empty($prodOperations)) {
+ if (count($prodEntries)) {
$exitCode = self::CHANGES_PROD;
- if ($this->hasDowngrades($prodOperations)) {
+ if ($this->hasDowngrades($prodEntries)) {
$exitCode |= self::DOWNGRADES_PROD;
}
}
- if (!empty($devOperations)) {
+ if (count($devEntries)) {
$exitCode |= self::CHANGES_DEV;
- if ($this->hasDowngrades($devOperations)) {
+ if ($this->hasDowngrades($devEntries)) {
$exitCode |= self::DOWNGRADES_DEV;
}
}
@@ -179,17 +176,18 @@ private function getExitCode(array $prodOperations, array $devOperations)
}
/**
- * @param OperationInterface[] $operations
- *
* @return bool
*/
- private function hasDowngrades(array $operations)
+ private function hasDowngrades(DiffEntries $entries)
{
- $downgrades = array_filter($operations, function (OperationInterface $operation) {
- return $operation instanceof UpdateOperation && !PackageDiff::isUpgrade($operation);
- });
+ /** @var DiffEntry $entry */
+ foreach ($entries as $entry) {
+ if ($entry->isDowngrade()) {
+ return true;
+ }
+ }
- return !empty($downgrades);
+ return false;
}
/**
diff --git a/src/Plugin.php b/src/Composer/Plugin.php
similarity index 95%
rename from src/Plugin.php
rename to src/Composer/Plugin.php
index 841ea6a..0d816fc 100644
--- a/src/Plugin.php
+++ b/src/Composer/Plugin.php
@@ -1,6 +1,6 @@
+ */
+class DiffEntries implements IteratorAggregate, Countable
+{
+ /** @var DiffEntry[] */
+ private $entries;
+
+ /**
+ * @param DiffEntry[] $entries
+ */
+ public function __construct(array $entries)
+ {
+ $this->entries = $entries;
+ }
+
+ /**
+ * @return ArrayIterator
+ */
+ public function getIterator()
+ {
+ return new ArrayIterator($this->entries);
+ }
+
+ public function count()
+ {
+ return \count($this->entries);
+ }
+}
diff --git a/src/Diff/DiffEntry.php b/src/Diff/DiffEntry.php
new file mode 100644
index 0000000..7349f11
--- /dev/null
+++ b/src/Diff/DiffEntry.php
@@ -0,0 +1,111 @@
+operation = $operation;
+ $this->type = $this->determineType();
+ }
+
+ /**
+ * @return OperationInterface
+ */
+ public function getOperation()
+ {
+ return $this->operation;
+ }
+
+ /**
+ * @return string
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isInstall()
+ {
+ return self::TYPE_INSTALL === $this->type;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isUpgrade()
+ {
+ return self::TYPE_UPGRADE === $this->type;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isDowngrade()
+ {
+ return self::TYPE_DOWNGRADE === $this->type;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isRemove()
+ {
+ return self::TYPE_REMOVE === $this->type;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isChange()
+ {
+ return self::TYPE_CHANGE === $this->type;
+ }
+
+ /**
+ * @return string
+ */
+ private function determineType()
+ {
+ if ($this->operation instanceof InstallOperation) {
+ return self::TYPE_INSTALL;
+ }
+
+ if ($this->operation instanceof UninstallOperation) {
+ return self::TYPE_REMOVE;
+ }
+
+ if ($this->operation instanceof UpdateOperation) {
+ $upgrade = VersionComparator::isUpgrade($this->operation);
+
+ if (null === $upgrade) {
+ return self::TYPE_CHANGE;
+ }
+
+ return $upgrade ? self::TYPE_UPGRADE : self::TYPE_DOWNGRADE;
+ }
+
+ return self::TYPE_CHANGE;
+ }
+}
diff --git a/src/Diff/VersionComparator.php b/src/Diff/VersionComparator.php
new file mode 100644
index 0000000..6df684f
--- /dev/null
+++ b/src/Diff/VersionComparator.php
@@ -0,0 +1,39 @@
+normalize($operation->getInitialPackage()->getVersion());
+ $normalizedTo = $versionParser->normalize($operation->getTargetPackage()->getVersion());
+ } catch (UnexpectedValueException $e) {
+ return null; // Consider as change if versions are not parseable
+ }
+
+ /* @infection-ignore-all False-positive, handled by build matrix with Composer 1 installed */
+ if (
+ '9999999-dev' === $normalizedFrom
+ || '9999999-dev' === $normalizedTo // BC for Composer 1.x
+ || 0 === strpos($normalizedFrom, 'dev-')
+ || 0 === strpos($normalizedTo, 'dev-')
+ ) {
+ return null;
+ }
+
+ $sorted = Semver::sort(array($normalizedTo, $normalizedFrom));
+
+ return $sorted[0] === $normalizedFrom;
+ }
+}
diff --git a/src/Formatter/AbstractFormatter.php b/src/Formatter/AbstractFormatter.php
index 71c8de5..b8c177b 100644
--- a/src/Formatter/AbstractFormatter.php
+++ b/src/Formatter/AbstractFormatter.php
@@ -3,10 +3,10 @@
namespace IonBazan\ComposerDiff\Formatter;
use Composer\DependencyResolver\Operation\InstallOperation;
-use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\Package\PackageInterface;
+use IonBazan\ComposerDiff\Diff\DiffEntry;
use IonBazan\ComposerDiff\Url\GeneratorContainer;
use Symfony\Component\Console\Output\OutputInterface;
@@ -31,8 +31,10 @@ public function __construct(OutputInterface $output, GeneratorContainer $generat
/**
* @return string|null
*/
- public function getUrl(OperationInterface $operation)
+ public function getUrl(DiffEntry $entry)
{
+ $operation = $entry->getOperation();
+
if ($operation instanceof UpdateOperation) {
return $this->getCompareUrl($operation->getInitialPackage(), $operation->getTargetPackage());
}
diff --git a/src/Formatter/Formatter.php b/src/Formatter/Formatter.php
index 246b43c..c743dde 100644
--- a/src/Formatter/Formatter.php
+++ b/src/Formatter/Formatter.php
@@ -2,30 +2,28 @@
namespace IonBazan\ComposerDiff\Formatter;
-use Composer\DependencyResolver\Operation\OperationInterface;
+use IonBazan\ComposerDiff\Diff\DiffEntries;
+use IonBazan\ComposerDiff\Diff\DiffEntry;
interface Formatter
{
/**
- * @param OperationInterface[] $prodOperations
- * @param OperationInterface[] $devOperations
- * @param bool $withUrls
+ * @param bool $withUrls
*
* @return void
*/
- public function render(array $prodOperations, array $devOperations, $withUrls);
+ public function render(DiffEntries $prodEntries, DiffEntries $devEntries, $withUrls);
/**
- * @param OperationInterface[] $operations
- * @param string $title
- * @param bool $withUrls
+ * @param string $title
+ * @param bool $withUrls
*
* @return void
*/
- public function renderSingle(array $operations, $title, $withUrls);
+ public function renderSingle(DiffEntries $entries, $title, $withUrls);
/**
* @return string|null
*/
- public function getUrl(OperationInterface $operation);
+ public function getUrl(DiffEntry $entry);
}
diff --git a/src/Formatter/JsonFormatter.php b/src/Formatter/JsonFormatter.php
index d6638a9..6697d01 100644
--- a/src/Formatter/JsonFormatter.php
+++ b/src/Formatter/JsonFormatter.php
@@ -3,30 +3,30 @@
namespace IonBazan\ComposerDiff\Formatter;
use Composer\DependencyResolver\Operation\InstallOperation;
-use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
-use IonBazan\ComposerDiff\PackageDiff;
+use IonBazan\ComposerDiff\Diff\DiffEntries;
+use IonBazan\ComposerDiff\Diff\DiffEntry;
class JsonFormatter extends AbstractFormatter
{
/**
* {@inheritdoc}
*/
- public function render(array $prodOperations, array $devOperations, $withUrls)
+ public function render(DiffEntries $prodEntries, DiffEntries $devEntries, $withUrls)
{
$this->format(array(
- 'packages' => $this->transformOperations($prodOperations, $withUrls),
- 'packages-dev' => $this->transformOperations($devOperations, $withUrls),
+ 'packages' => $this->transformEntries($prodEntries, $withUrls),
+ 'packages-dev' => $this->transformEntries($devEntries, $withUrls),
));
}
/**
* {@inheritdoc}
*/
- public function renderSingle(array $operations, $title, $withUrls)
+ public function renderSingle(DiffEntries $entries, $title, $withUrls)
{
- $this->format($this->transformOperations($operations, $withUrls));
+ $this->format($this->transformEntries($entries, $withUrls));
}
/**
@@ -40,20 +40,19 @@ private function format(array $data)
}
/**
- * @param OperationInterface[] $operations
- * @param bool $withUrls
+ * @param bool $withUrls
*
* @return array>
*/
- private function transformOperations(array $operations, $withUrls)
+ private function transformEntries(DiffEntries $entries, $withUrls)
{
$rows = array();
- foreach ($operations as $operation) {
- $row = $this->transformOperation($operation);
+ foreach ($entries as $entry) {
+ $row = $this->transformEntry($entry);
if ($withUrls) {
- $row['compare'] = $this->getUrl($operation);
+ $row['compare'] = $this->getUrl($entry);
}
$rows[$row['name']] = $row;
@@ -65,12 +64,14 @@ private function transformOperations(array $operations, $withUrls)
/**
* @return array
*/
- private function transformOperation(OperationInterface $operation)
+ private function transformEntry(DiffEntry $entry)
{
+ $operation = $entry->getOperation();
+
if ($operation instanceof InstallOperation) {
return array(
'name' => $operation->getPackage()->getName(),
- 'operation' => 'install',
+ 'operation' => $entry->getType(),
'version_base' => null,
'version_target' => $operation->getPackage()->getFullPrettyVersion(),
);
@@ -79,7 +80,7 @@ private function transformOperation(OperationInterface $operation)
if ($operation instanceof UpdateOperation) {
return array(
'name' => $operation->getInitialPackage()->getName(),
- 'operation' => PackageDiff::isUpgrade($operation) ? 'upgrade' : 'downgrade',
+ 'operation' => $entry->getType(),
'version_base' => $operation->getInitialPackage()->getFullPrettyVersion(),
'version_target' => $operation->getTargetPackage()->getFullPrettyVersion(),
);
@@ -88,7 +89,7 @@ private function transformOperation(OperationInterface $operation)
if ($operation instanceof UninstallOperation) {
return array(
'name' => $operation->getPackage()->getName(),
- 'operation' => 'remove',
+ 'operation' => $entry->getType(),
'version_base' => $operation->getPackage()->getFullPrettyVersion(),
'version_target' => null,
);
diff --git a/src/Formatter/MarkdownListFormatter.php b/src/Formatter/MarkdownListFormatter.php
index e95e9a5..9c4f7f3 100644
--- a/src/Formatter/MarkdownListFormatter.php
+++ b/src/Formatter/MarkdownListFormatter.php
@@ -3,28 +3,28 @@
namespace IonBazan\ComposerDiff\Formatter;
use Composer\DependencyResolver\Operation\InstallOperation;
-use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
-use IonBazan\ComposerDiff\PackageDiff;
+use IonBazan\ComposerDiff\Diff\DiffEntries;
+use IonBazan\ComposerDiff\Diff\DiffEntry;
class MarkdownListFormatter extends MarkdownFormatter
{
/**
* {@inheritdoc}
*/
- public function render(array $prodOperations, array $devOperations, $withUrls)
+ public function render(DiffEntries $prodEntries, DiffEntries $devEntries, $withUrls)
{
- $this->renderSingle($prodOperations, 'Prod Packages', $withUrls);
- $this->renderSingle($devOperations, 'Dev Packages', $withUrls);
+ $this->renderSingle($prodEntries, 'Prod Packages', $withUrls);
+ $this->renderSingle($devEntries, 'Dev Packages', $withUrls);
}
/**
* {@inheritdoc}
*/
- public function renderSingle(array $operations, $title, $withUrls)
+ public function renderSingle(DiffEntries $entries, $title, $withUrls)
{
- if (!\count($operations)) {
+ if (!\count($entries)) {
return;
}
@@ -32,8 +32,8 @@ public function renderSingle(array $operations, $title, $withUrls)
$this->output->writeln(str_repeat('=', strlen($title)));
$this->output->writeln('');
- foreach ($operations as $operation) {
- $this->output->writeln($this->getRow($operation, $withUrls));
+ foreach ($entries as $entry) {
+ $this->output->writeln($this->getRow($entry, $withUrls));
}
$this->output->writeln('');
@@ -44,10 +44,11 @@ public function renderSingle(array $operations, $title, $withUrls)
*
* @return string
*/
- private function getRow(OperationInterface $operation, $withUrls)
+ private function getRow(DiffEntry $entry, $withUrls)
{
- $url = $withUrls ? $this->formatUrl($this->getUrl($operation), 'Compare') : null;
+ $url = $withUrls ? $this->formatUrl($this->getUrl($entry), 'Compare') : null;
$url = (null !== $url) ? ' '.$url : '';
+ $operation = $entry->getOperation();
if ($operation instanceof InstallOperation) {
return sprintf(
@@ -59,11 +60,9 @@ private function getRow(OperationInterface $operation, $withUrls)
}
if ($operation instanceof UpdateOperation) {
- $isUpgrade = PackageDiff::isUpgrade($operation);
-
return sprintf(
' - %s %s> (%s> => %s>)%s',
- $isUpgrade ? 'Upgrade' : 'Downgrade',
+ ucfirst($entry->getType()),
$operation->getInitialPackage()->getName(),
$operation->getInitialPackage()->getFullPrettyVersion(),
$operation->getTargetPackage()->getFullPrettyVersion(),
diff --git a/src/Formatter/MarkdownTableFormatter.php b/src/Formatter/MarkdownTableFormatter.php
index 761f689..d0a02bb 100644
--- a/src/Formatter/MarkdownTableFormatter.php
+++ b/src/Formatter/MarkdownTableFormatter.php
@@ -3,39 +3,39 @@
namespace IonBazan\ComposerDiff\Formatter;
use Composer\DependencyResolver\Operation\InstallOperation;
-use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
+use IonBazan\ComposerDiff\Diff\DiffEntries;
+use IonBazan\ComposerDiff\Diff\DiffEntry;
use IonBazan\ComposerDiff\Formatter\Helper\Table;
-use IonBazan\ComposerDiff\PackageDiff;
class MarkdownTableFormatter extends MarkdownFormatter
{
/**
* {@inheritdoc}
*/
- public function render(array $prodOperations, array $devOperations, $withUrls)
+ public function render(DiffEntries $prodEntries, DiffEntries $devEntries, $withUrls)
{
- $this->renderSingle($prodOperations, 'Prod Packages', $withUrls);
- $this->renderSingle($devOperations, 'Dev Packages', $withUrls);
+ $this->renderSingle($prodEntries, 'Prod Packages', $withUrls);
+ $this->renderSingle($devEntries, 'Dev Packages', $withUrls);
}
/**
* {@inheritdoc}
*/
- public function renderSingle(array $operations, $title, $withUrls)
+ public function renderSingle(DiffEntries $entries, $title, $withUrls)
{
- if (!\count($operations)) {
+ if (!\count($entries)) {
return;
}
$rows = array();
- foreach ($operations as $operation) {
- $row = $this->getTableRow($operation);
+ foreach ($entries as $entry) {
+ $row = $this->getTableRow($entry);
if ($withUrls) {
- $row[] = $this->formatUrl($this->getUrl($operation), 'Compare');
+ $row[] = $this->formatUrl($this->getUrl($entry), 'Compare');
}
$rows[] = $row;
@@ -55,8 +55,9 @@ public function renderSingle(array $operations, $title, $withUrls)
/**
* @return string[]
*/
- private function getTableRow(OperationInterface $operation)
+ private function getTableRow(DiffEntry $entry)
{
+ $operation = $entry->getOperation();
if ($operation instanceof InstallOperation) {
return array(
$operation->getPackage()->getName(),
@@ -69,7 +70,7 @@ private function getTableRow(OperationInterface $operation)
if ($operation instanceof UpdateOperation) {
return array(
$operation->getInitialPackage()->getName(),
- PackageDiff::isUpgrade($operation) ? 'Upgraded>' : 'Downgraded>',
+ $entry->isChange() ? 'Changed>' : ($entry->isUpgrade() ? 'Upgraded>' : 'Downgraded>'),
$operation->getInitialPackage()->getFullPrettyVersion(),
$operation->getTargetPackage()->getFullPrettyVersion(),
);
diff --git a/src/PackageDiff.php b/src/PackageDiff.php
index 8b76abb..c94c035 100644
--- a/src/PackageDiff.php
+++ b/src/PackageDiff.php
@@ -9,9 +9,8 @@
use Composer\Package\CompletePackage;
use Composer\Package\Loader\ArrayLoader;
use Composer\Repository\ArrayRepository;
-use Composer\Semver\Semver;
-use Composer\Semver\VersionParser;
-use UnexpectedValueException;
+use IonBazan\ComposerDiff\Diff\DiffEntries;
+use IonBazan\ComposerDiff\Diff\DiffEntry;
class PackageDiff
{
@@ -23,7 +22,7 @@ class PackageDiff
* @param bool $dev
* @param bool $withPlatform
*
- * @return OperationInterface[]
+ * @return DiffEntries
*/
public function getPackageDiff($from, $to, $dev, $withPlatform)
{
@@ -50,24 +49,9 @@ public function getPackageDiff($from, $to, $dev, $withPlatform)
}
}
- return $operations;
- }
-
- /**
- * @return bool
- */
- public static function isUpgrade(UpdateOperation $operation)
- {
- $versionParser = new VersionParser();
- try {
- $normalizedFrom = $versionParser->normalize($operation->getInitialPackage()->getVersion());
- $normalizedTo = $versionParser->normalize($operation->getTargetPackage()->getVersion());
- } catch (UnexpectedValueException $e) {
- return true; // Consider as upgrade if versions are not parsable
- }
- $sorted = Semver::sort(array($normalizedTo, $normalizedFrom));
-
- return $sorted[0] === $normalizedFrom;
+ return new DiffEntries(array_map(function (OperationInterface $operation) {
+ return new DiffEntry($operation);
+ }, $operations));
}
/**
diff --git a/tests/Command/DiffCommandTest.php b/tests/Command/DiffCommandTest.php
index acf24b4..7d8c742 100644
--- a/tests/Command/DiffCommandTest.php
+++ b/tests/Command/DiffCommandTest.php
@@ -24,7 +24,7 @@ public function testItGeneratesReportInGivenFormat($expectedOutput, array $optio
$diff->expects($this->once())
->method('getPackageDiff')
->with($this->isType('string'), $this->isType('string'), false, false)
- ->willReturn(array(
+ ->willReturn($this->getEntries(array(
new InstallOperation($this->getPackageWithSource('a/package-1', '1.0.0', 'github.com')),
new UpdateOperation($this->getPackageWithSource('a/package-2', '1.0.0', 'github.com'), $this->getPackageWithSource('a/package-2', '1.2.0', 'github.com')),
new UninstallOperation($this->getPackageWithSource('a/package-3', '0.1.1', 'github.com')),
@@ -32,7 +32,7 @@ public function testItGeneratesReportInGivenFormat($expectedOutput, array $optio
new UninstallOperation($this->getPackageWithSource('a/package-5', '0.1.1', 'gitlab2.org')),
new UninstallOperation($this->getPackageWithSource('a/package-6', '0.1.1', 'gitlab3.org')),
new UpdateOperation($this->getPackageWithSource('a/package-7', '1.2.0', 'github.com'), $this->getPackageWithSource('a/package-7', '1.0.0', 'github.com')),
- ))
+ )))
;
$result = $tester->execute($options);
$this->assertSame(0, $result);
@@ -53,7 +53,7 @@ public function testStrictMode($exitCode, array $prodOperations, array $devOpera
$diff->expects($this->exactly(2))
->method('getPackageDiff')
->with($this->isType('string'), $this->isType('string'), $this->isType('boolean'), false)
- ->willReturnOnConsecutiveCalls($prodOperations, $devOperations)
+ ->willReturnOnConsecutiveCalls($this->getEntries($prodOperations), $this->getEntries($devOperations))
;
$this->assertSame($exitCode, $tester->execute(array('--strict' => null)));
}
diff --git a/tests/PluginTest.php b/tests/Composer/PluginTest.php
similarity index 81%
rename from tests/PluginTest.php
rename to tests/Composer/PluginTest.php
index 4e49f7f..9afb35f 100644
--- a/tests/PluginTest.php
+++ b/tests/Composer/PluginTest.php
@@ -1,8 +1,9 @@
assertSame($expectedType, $entry->getType());
+ $this->assertTrue($entry->{'is'.ucfirst($expectedType)}());
+ }
+
+ public function operationTypeProvider()
+ {
+ return array(
+ 'Install operation' => array(
+ 'install',
+ new InstallOperation($this->getPackage('a/package-1', '1.0.0')),
+ ),
+ 'Remove operation' => array(
+ 'remove',
+ new UninstallOperation($this->getPackage('a/package-1', '1.0.0')),
+ ),
+ 'Upgrade operation' => array(
+ 'upgrade',
+ new UpdateOperation($this->getPackage('a/package-1', '1.0.0'), $this->getPackage('a/package-1', '2.0.0')),
+ ),
+ 'Downgrade operation' => array(
+ 'downgrade',
+ new UpdateOperation($this->getPackage('a/package-1', '2.0.0'), $this->getPackage('a/package-1', '1.0.0')),
+ ),
+ 'Change operation (base branch)' => array(
+ 'change',
+ new UpdateOperation($this->getPackage('a/package-1', 'dev-master', 'dev-master 1234567'), $this->getPackage('a/package-1', '1.0.0')),
+ ),
+ 'Change operation (target branch)' => array(
+ 'change',
+ new UpdateOperation($this->getPackage('a/package-1', '1.0.0'), $this->getPackage('a/package-1', 'dev-master', 'dev-master 1234567')),
+ ),
+ 'Change operation (both branch)' => array(
+ 'change',
+ new UpdateOperation($this->getPackage('a/package-1', 'dev-master', 'dev-master 7654321'), $this->getPackage('a/package-1', 'dev-master', 'dev-master 1234567')),
+ ),
+ 'Change operation (both custom branch)' => array(
+ 'change',
+ new UpdateOperation($this->getPackage('a/package-1', 'dev-develop', 'dev-develop 7654321'), $this->getPackage('a/package-1', 'dev-develop', 'dev-develop 1234567')),
+ ),
+ 'Change operation (target branch and base custom branch)' => array(
+ 'change',
+ new UpdateOperation($this->getPackage('a/package-1', 'dev-develop', 'dev-develop 7654321'), $this->getPackage('a/package-1', 'dev-master', 'dev-master 1234567')),
+ ),
+ 'Change operation (base branch and target custom branch)' => array(
+ 'change',
+ new UpdateOperation($this->getPackage('a/package-1', 'dev-master', 'dev-master 7654321'), $this->getPackage('a/package-1', 'dev-develop', 'dev-develop 1234567')),
+ ),
+ 'Change operation (target custom branch)' => array(
+ 'change',
+ new UpdateOperation($this->getPackage('a/package-1', '1.0.0'), $this->getPackage('a/package-1', 'dev-develop', 'dev-develop 1234567')),
+ ),
+ 'Change operation (base custom branch)' => array(
+ 'change',
+ new UpdateOperation($this->getPackage('a/package-1', 'dev-develop', 'dev-develop 7654321'), $this->getPackage('a/package-1', '1.0.0')),
+ ),
+ 'Change operation (BC with Composer 1 master as base)' => array(
+ 'change',
+ new UpdateOperation($this->getPackage('a/package-1', 'master', 'master 7654321'), $this->getPackage('a/package-1', '1.0.0')),
+ ),
+ 'Change operation (BC with Composer 1 master as target)' => array(
+ 'change',
+ new UpdateOperation($this->getPackage('a/package-1', '1.0.0'), $this->getPackage('a/package-1', 'master', 'master 1234567')),
+ ),
+ );
+ }
+}
diff --git a/tests/Formatter/FormatterTest.php b/tests/Formatter/FormatterTest.php
index 17504e8..d939c0c 100644
--- a/tests/Formatter/FormatterTest.php
+++ b/tests/Formatter/FormatterTest.php
@@ -6,6 +6,8 @@
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\Package\PackageInterface;
+use IonBazan\ComposerDiff\Diff\DiffEntries;
+use IonBazan\ComposerDiff\Diff\DiffEntry;
use IonBazan\ComposerDiff\Formatter\Formatter;
use IonBazan\ComposerDiff\Tests\TestCase;
use IonBazan\ComposerDiff\Url\GeneratorContainer;
@@ -19,7 +21,7 @@ public function testItNoopsWhenListIsEmpty()
{
$output = new StreamOutput(fopen('php://memory', 'wb', false));
$formatter = $this->getFormatter($output, $this->getGenerators());
- $formatter->render(array(), array(), true);
+ $formatter->render(new DiffEntries(array()), new DiffEntries(array()), true);
$this->assertSame(static::getEmptyOutput(), $this->getDisplay($output));
}
@@ -28,7 +30,7 @@ public function testGetUrlReturnsNullForInvalidOperation()
$output = $this->getMockBuilder('Symfony\Component\Console\Output\OutputInterface')->getMock();
$operation = $this->getMockBuilder('Composer\DependencyResolver\Operation\OperationInterface')->getMock();
$formatter = $this->getFormatter($output, $this->getGenerators());
- $this->assertNull($formatter->getUrl($operation));
+ $this->assertNull($formatter->getUrl(new DiffEntry($operation)));
}
/**
@@ -54,7 +56,7 @@ public function testItRendersTheListOfOperations($withUrls)
new UninstallOperation($this->getPackage('a/package-4', '0.1.1')),
new UninstallOperation($this->getPackage('a/no-link-2', '0.1.1')),
);
- $formatter->render($prodPackages, $devPackages, $withUrls);
+ $formatter->render($this->getEntries($prodPackages), $this->getEntries($devPackages), $withUrls);
$this->assertSame($this->getSampleOutput($withUrls), $this->getDisplay($output));
}
@@ -62,9 +64,9 @@ public function testItFailsWithInvalidOperation()
{
$output = $this->getMockBuilder('Symfony\Component\Console\Output\OutputInterface')->getMock();
$this->setExpectedException('InvalidArgumentException', 'Invalid operation');
- $this->getFormatter($output, $this->getGenerators())->render(array(
+ $this->getFormatter($output, $this->getGenerators())->render($this->getEntries(array(
$this->getMockBuilder('Composer\DependencyResolver\Operation\OperationInterface')->getMock(),
- ), array(), false);
+ )), $this->getEntries(array()), false);
}
/**
diff --git a/tests/Formatter/JsonFormatterTest.php b/tests/Formatter/JsonFormatterTest.php
index ee92d96..d5df1be 100644
--- a/tests/Formatter/JsonFormatterTest.php
+++ b/tests/Formatter/JsonFormatterTest.php
@@ -26,7 +26,7 @@ public function testRenderSingle()
);
$output = new StreamOutput(fopen('php://memory', 'wb', false));
$formatter = $this->getFormatter($output, $this->getGenerators());
- $formatter->renderSingle($sampleData, 'test', true);
+ $formatter->renderSingle($this->getEntries($sampleData), 'test', true);
$this->assertSame(self::formatOutput(array(
'a/package-1' => array(
@@ -66,7 +66,7 @@ public function testRenderSingle()
),
'a/package-5' => array(
'name' => 'a/package-5',
- 'operation' => 'downgrade',
+ 'operation' => 'change',
'version_base' => 'dev-master 1234567',
'version_target' => '1.1.1',
'compare' => 'https://example.com/c/dev-master..1.1.1',
@@ -123,7 +123,7 @@ protected function getSampleOutput($withUrls)
),
'php' => array(
'name' => 'php',
- 'operation' => 'upgrade',
+ 'operation' => 'change',
'version_base' => '>=7.4.6',
'version_target' => '^8.0',
'compare' => null,
@@ -132,7 +132,7 @@ protected function getSampleOutput($withUrls)
'packages-dev' => array(
'a/package-5' => array(
'name' => 'a/package-5',
- 'operation' => 'downgrade',
+ 'operation' => 'change',
'version_base' => 'dev-master 1234567',
'version_target' => '1.1.1',
'compare' => 'https://example.com/c/dev-master..1.1.1',
@@ -189,7 +189,7 @@ protected function getSampleOutput($withUrls)
),
'php' => array(
'name' => 'php',
- 'operation' => 'upgrade',
+ 'operation' => 'change',
'version_base' => '>=7.4.6',
'version_target' => '^8.0',
),
@@ -197,7 +197,7 @@ protected function getSampleOutput($withUrls)
'packages-dev' => array(
'a/package-5' => array(
'name' => 'a/package-5',
- 'operation' => 'downgrade',
+ 'operation' => 'change',
'version_base' => 'dev-master 1234567',
'version_target' => '1.1.1',
),
diff --git a/tests/Formatter/MarkdownListFormatterTest.php b/tests/Formatter/MarkdownListFormatterTest.php
index bfcf9a1..7f97ac8 100644
--- a/tests/Formatter/MarkdownListFormatterTest.php
+++ b/tests/Formatter/MarkdownListFormatterTest.php
@@ -20,12 +20,12 @@ protected function getSampleOutput($withUrls)
- Upgrade a/package-2 (1.0.0 => 1.2.0) [Compare](https://example.com/c/1.0.0..1.2.0)
- Downgrade a/package-3 (2.0.0 => 1.1.1) [Compare](https://example.com/c/2.0.0..1.1.1)
- Downgrade a/no-link-2 (2.0.0 => 1.1.1)
- - Upgrade php (>=7.4.6 => ^8.0)
+ - Change php (>=7.4.6 => ^8.0)
Dev Packages
============
- - Downgrade a/package-5 (dev-master 1234567 => 1.1.1) [Compare](https://example.com/c/dev-master..1.1.1)
+ - Change a/package-5 (dev-master 1234567 => 1.1.1) [Compare](https://example.com/c/dev-master..1.1.1)
- Uninstall a/package-4 (0.1.1) [Compare](https://example.com/r/0.1.1)
- Uninstall a/no-link-2 (0.1.1)
@@ -42,12 +42,12 @@ protected function getSampleOutput($withUrls)
- Upgrade a/package-2 (1.0.0 => 1.2.0)
- Downgrade a/package-3 (2.0.0 => 1.1.1)
- Downgrade a/no-link-2 (2.0.0 => 1.1.1)
- - Upgrade php (>=7.4.6 => ^8.0)
+ - Change php (>=7.4.6 => ^8.0)
Dev Packages
============
- - Downgrade a/package-5 (dev-master 1234567 => 1.1.1)
+ - Change a/package-5 (dev-master 1234567 => 1.1.1)
- Uninstall a/package-4 (0.1.1)
- Uninstall a/no-link-2 (0.1.1)
diff --git a/tests/Formatter/MarkdownTableFormatterTest.php b/tests/Formatter/MarkdownTableFormatterTest.php
index edb118b..1d1ba76 100644
--- a/tests/Formatter/MarkdownTableFormatterTest.php
+++ b/tests/Formatter/MarkdownTableFormatterTest.php
@@ -19,13 +19,13 @@ protected function getSampleOutput($withUrls)
| a/package-2 | Upgraded | 1.0.0 | 1.2.0 | [Compare](https://example.com/c/1.0.0..1.2.0) |
| a/package-3 | Downgraded | 2.0.0 | 1.1.1 | [Compare](https://example.com/c/2.0.0..1.1.1) |
| a/no-link-2 | Downgraded | 2.0.0 | 1.1.1 | |
-| php | Upgraded | >=7.4.6 | ^8.0 | |
+| php | Changed | >=7.4.6 | ^8.0 | |
-| Dev Packages | Operation | Base | Target | Link |
-|--------------|------------|--------------------|--------|----------------------------------------------------|
-| a/package-5 | Downgraded | dev-master 1234567 | 1.1.1 | [Compare](https://example.com/c/dev-master..1.1.1) |
-| a/package-4 | Removed | 0.1.1 | - | [Compare](https://example.com/r/0.1.1) |
-| a/no-link-2 | Removed | 0.1.1 | - | |
+| Dev Packages | Operation | Base | Target | Link |
+|--------------|-----------|--------------------|--------|----------------------------------------------------|
+| a/package-5 | Changed | dev-master 1234567 | 1.1.1 | [Compare](https://example.com/c/dev-master..1.1.1) |
+| a/package-4 | Removed | 0.1.1 | - | [Compare](https://example.com/r/0.1.1) |
+| a/no-link-2 | Removed | 0.1.1 | - | |
OUTPUT;
@@ -39,13 +39,13 @@ protected function getSampleOutput($withUrls)
| a/package-2 | Upgraded | 1.0.0 | 1.2.0 |
| a/package-3 | Downgraded | 2.0.0 | 1.1.1 |
| a/no-link-2 | Downgraded | 2.0.0 | 1.1.1 |
-| php | Upgraded | >=7.4.6 | ^8.0 |
+| php | Changed | >=7.4.6 | ^8.0 |
-| Dev Packages | Operation | Base | Target |
-|--------------|------------|--------------------|--------|
-| a/package-5 | Downgraded | dev-master 1234567 | 1.1.1 |
-| a/package-4 | Removed | 0.1.1 | - |
-| a/no-link-2 | Removed | 0.1.1 | - |
+| Dev Packages | Operation | Base | Target |
+|--------------|-----------|--------------------|--------|
+| a/package-5 | Changed | dev-master 1234567 | 1.1.1 |
+| a/package-4 | Removed | 0.1.1 | - |
+| a/no-link-2 | Removed | 0.1.1 | - |
OUTPUT;
diff --git a/tests/Integration/DiffCommandTest.php b/tests/Integration/DiffCommandTest.php
index e06fcf6..6ca8953 100644
--- a/tests/Integration/DiffCommandTest.php
+++ b/tests/Integration/DiffCommandTest.php
@@ -2,9 +2,14 @@
namespace IonBazan\ComposerDiff\Tests\Integration;
+use Composer\Composer;
+use Composer\Console\Application;
+use Composer\IO\IOInterface;
+use Composer\IO\NullIO;
use IonBazan\ComposerDiff\Command\DiffCommand;
use IonBazan\ComposerDiff\PackageDiff;
use IonBazan\ComposerDiff\Tests\TestCase;
+use Symfony\Component\Console\Tester\ApplicationTester;
use Symfony\Component\Console\Tester\CommandTester;
class DiffCommandTest extends TestCase
@@ -22,6 +27,29 @@ public function testCommand($expectedOutput, array $input)
$this->assertSame($expectedOutput, $tester->getDisplay());
}
+ /**
+ * @param string $expectedOutput
+ *
+ * @dataProvider commandArgumentsDataProvider
+ */
+ public function testComposerApplication($expectedOutput, array $input)
+ {
+ if (version_compare('2.0', Composer::VERSION, '>=')) {
+ $this->markTestSkipped('This test works properly only on Composer 2');
+ }
+
+ array_unshift($input, 'diff');
+ $app = new ComposerApplication();
+ $app->setIO(new NullIO());
+ $app->setAutoExit(false);
+ $composer = $app->getComposer();
+ $composer->getPluginManager()->registerPackage($composer->getPackage(), true);
+ $tester = new ApplicationTester($app);
+ $result = $tester->run($input);
+ $this->assertSame(0, $result);
+ $this->assertSame($expectedOutput, $tester->getDisplay());
+ }
+
public function commandArgumentsDataProvider()
{
return array(
@@ -194,3 +222,11 @@ public function commandArgumentsDataProvider()
);
}
}
+
+class ComposerApplication extends Application
+{
+ public function setIO(IOInterface $io)
+ {
+ $this->io = $io;
+ }
+}
diff --git a/tests/PackageDiffTest.php b/tests/PackageDiffTest.php
index babdfae..10ba6db 100644
--- a/tests/PackageDiffTest.php
+++ b/tests/PackageDiffTest.php
@@ -3,9 +3,9 @@
namespace IonBazan\ComposerDiff\Tests;
use Composer\DependencyResolver\Operation\InstallOperation;
-use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
+use IonBazan\ComposerDiff\Diff\DiffEntry;
use IonBazan\ComposerDiff\PackageDiff;
class PackageDiffTest extends TestCase
@@ -27,7 +27,7 @@ public function testBasicUsage(array $expected, $dev, $withPlatform)
$withPlatform
);
- $this->assertSame($expected, array_map(array($this, 'operationToString'), $operations));
+ $this->assertSame($expected, array_map(array($this, 'entryToString'), $operations->getIterator()->getArrayCopy()));
}
public function testSameBaseAndTarget()
@@ -56,7 +56,7 @@ public function testGitUsage(array $expected, $dev, $withPlatform)
$this->prepareGit();
$operations = $diff->getPackageDiff('HEAD', '', $dev, $withPlatform);
- $this->assertSame($expected, array_map(array($this, 'operationToString'), $operations));
+ $this->assertSame($expected, array_map(array($this, 'entryToString'), $operations->getIterator()->getArrayCopy()));
}
public function testInvalidGitRef()
@@ -135,8 +135,10 @@ private function prepareGit()
file_put_contents($gitDir.'/composer.lock', file_get_contents(__DIR__.'/fixtures/target/composer.lock'));
}
- private function operationToString(OperationInterface $operation)
+ private function entryToString(DiffEntry $entry)
{
+ $operation = $entry->getOperation();
+
if ($operation instanceof InstallOperation) {
return sprintf('install %s %s', $operation->getPackage()->getName(), $operation->getPackage()->getPrettyVersion());
}
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 792d4c9..e5f4bb1 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -2,7 +2,10 @@
namespace IonBazan\ComposerDiff\Tests;
+use Composer\DependencyResolver\Operation\OperationInterface;
use Composer\Package\PackageInterface;
+use IonBazan\ComposerDiff\Diff\DiffEntries;
+use IonBazan\ComposerDiff\Diff\DiffEntry;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase as BaseTestCase;
@@ -58,4 +61,16 @@ protected function getPackageWithSource($name, $version, $sourceUrl, $sourceRefe
return $package;
}
+
+ /**
+ * @param OperationInterface[] $operations
+ *
+ * @return DiffEntries
+ */
+ protected function getEntries(array $operations)
+ {
+ return new DiffEntries(array_map(function (OperationInterface $operation) {
+ return new DiffEntry($operation);
+ }, $operations));
+ }
}