Skip to content

Commit

Permalink
Sort packages linter
Browse files Browse the repository at this point in the history
  • Loading branch information
soullivaneuh committed May 29, 2016
1 parent 975f5b0 commit 24980dc
Show file tree
Hide file tree
Showing 10 changed files with 302 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ root = true
end_of_line = lf
insert_final_newline = true

[composer.json]
[{composer.json,tests/fixtures/*.json}]
indent_style = space
indent_size = 4

Expand Down
20 changes: 17 additions & 3 deletions src/LintPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Plugin\PluginInterface;
Expand All @@ -24,13 +25,19 @@ final class LintPlugin implements PluginInterface, EventSubscriberInterface
*/
private $io;

/**
* @var Linter
*/
private $linter;

/**
* {@inheritdoc}
*/
public function activate(Composer $composer, IOInterface $io)
{
$this->composer = $composer;
$this->io = $io;
$this->linter = new Linter();
}

/**
Expand All @@ -48,16 +55,23 @@ public static function getSubscribedEvents()
/**
* @param CommandEvent $event
*
* @return int The command plugin execution value
* @return bool true if no violation, false otherwise.
*/
public function command(CommandEvent $event)
{
if ('validate' !== $event->getCommandName()) {
return true;
}

$this->io->writeError('This plugin is over development. Please do not use it for the moment.');
$json = new JsonFile($event->getInput()->getArgument('file'));
$manifest = $json->read();

$errors = $this->linter->validate($manifest);

foreach ($errors as $error) {
$this->io->writeError(sprintf('<error>%s</error>', $error));
}

return false;
return empty($errors);
}
}
52 changes: 52 additions & 0 deletions src/Linter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace SLLH\ComposerLint;

/**
* @author Sullivan Senechal <soullivaneuh@gmail.com>
*/
final class Linter
{
/**
* @param array $manifest composer.json file manifest
*
* @return string[]
*/
public function validate($manifest)
{
$errors = array();

if (isset($manifest['config']['sort-packages']) && $manifest['config']['sort-packages']) {
foreach (array('require', 'require-dev', 'conflict', 'replace', 'provide', 'suggest') as $linksSection) {
if (array_key_exists($linksSection, $manifest) && !$this->packagesAreSorted($manifest[$linksSection])) {
array_push($errors, 'Links under '.$linksSection.' section are not sorted.');
}
}
}

return $errors;
}

private function packagesAreSorted(array $packages)
{
$names = array_keys($packages);

$hasPHP = in_array('php', $names);
$extNames = array_filter($names, function ($name) {
return 'ext-' === substr($name, 0, 4) && !strstr($name, '/');
});
sort($extNames);
$vendorName = array_filter($names, function ($name) {
return 'ext-' !== substr($name, 0, 4) && 'php' !== $name;
});
sort($vendorName);

$sortedNames = array_merge(
$hasPHP ? array('php') : array(),
$extNames,
$vendorName
);

return $sortedNames === $names;
}
}
32 changes: 27 additions & 5 deletions tests/LintPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
use Composer\Plugin\PluginInterface;
use Composer\Plugin\PluginManager;
use SLLH\ComposerLint\LintPlugin;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;

/**
Expand Down Expand Up @@ -48,12 +47,35 @@ public function testValidateCommand()
{
$this->addComposerPlugin(new LintPlugin());

$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', new ArrayInput(array()), new NullOutput());
$ret = $this->composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
$input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
$input->expects($this->once())->method('getArgument')->with('file')
->willReturn(__DIR__.'/fixtures/composer.json');

$this->assertSame(1, $ret);
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, new NullOutput());

$this->assertSame(1, $this->composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent));
$this->assertSame(<<<'EOF'
Links under require section are not sorted.
Links under require-dev section are not sorted.

EOF
, $this->io->getOutput());
}

/**
* The plugin should not be executed at all.
*/
public function testDummyCommand()
{
$this->addComposerPlugin(new LintPlugin());

$input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
$input->expects($this->never())->method('getArgument')->with('file');

$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dummy', $input, new NullOutput());

$this->assertSame(0, $this->composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent));
$this->assertSame(<<<'EOF'
This plugin is over development. Please do not use it for the moment.

EOF
, $this->io->getOutput());
Expand Down
53 changes: 53 additions & 0 deletions tests/LinterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace SLLH\ComposerLint\Tests;

use Composer\Json\JsonFile;
use SLLH\ComposerLint\Linter;

/**
* @author Sullivan Senechal <soullivaneuh@gmail.com>
*/
final class LinterTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Linter
*/
private $linter;

/**
* {@inheritdoc}
*/
protected function setUp()
{
$this->linter = new Linter();
}

/**
* @dataProvider getLintData
*
* @param string $file
* @param int $expectedErrorsCount
*/
public function testLint($file, $expectedErrorsCount = 0)
{
$json = new JsonFile($file);
$manifest = $json->read();

$errors = $this->linter->validate($manifest);
$this->assertCount($expectedErrorsCount, $errors);
}

/**
* @return array[]
*/
public function getLintData()
{
return array(
array(__DIR__.'/fixtures/sort-ok.json'),
array(__DIR__.'/fixtures/sort-ko.json', 6),
array(__DIR__.'/fixtures/sort-ko-deactivated.json'),
array(__DIR__.'/fixtures/sort-ko-no-config.json'),
);
}
}
16 changes: 16 additions & 0 deletions tests/fixtures/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "foo/bar",
"description": "Fake package. LULZ.",
"license": "MIT",
"require": {
"sllh/php-cs-fixer-styleci-bridge": "^2.0",
"aztech/layers": "0.1.*"
},
"require-dev": {
"sllh/php-cs-fixer-styleci-bridge": "^2.0",
"aztech/layers": "0.1.*"
},
"config": {
"sort-packages": true
}
}
36 changes: 36 additions & 0 deletions tests/fixtures/sort-ko-deactivated.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"require": {
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0",
"php": "^5.3"
},
"require-dev": {
"php": "^5.3",
"aztech/layers": "0.1.*",
"ext-aaa": "^1.0",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"conflict": {
"zzz/xxx": "^1.0",
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"replace": {
"zzz/xxx": "^1.0",
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"provide": {
"zzz/xxx": "^1.0",
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"suggest": {
"zzz/xxx": "^1.0",
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"config": {
"sort-packages": false
}
}
33 changes: 33 additions & 0 deletions tests/fixtures/sort-ko-no-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"require": {
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0",
"php": "^5.3"
},
"require-dev": {
"php": "^5.3",
"aztech/layers": "0.1.*",
"ext-aaa": "^1.0",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"conflict": {
"zzz/xxx": "^1.0",
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"replace": {
"zzz/xxx": "^1.0",
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"provide": {
"zzz/xxx": "^1.0",
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"suggest": {
"zzz/xxx": "^1.0",
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
}
}
36 changes: 36 additions & 0 deletions tests/fixtures/sort-ko.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"require": {
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0",
"php": "^5.3"
},
"require-dev": {
"php": "^5.3",
"aztech/layers": "0.1.*",
"ext-aaa": "^1.0",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"conflict": {
"zzz/xxx": "^1.0",
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"replace": {
"zzz/xxx": "^1.0",
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"provide": {
"zzz/xxx": "^1.0",
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"suggest": {
"zzz/xxx": "^1.0",
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"config": {
"sort-packages": true
}
}
31 changes: 31 additions & 0 deletions tests/fixtures/sort-ok.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"require": {
"php": "^5.3",
"ext-mbstring": "^1.0",
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"require-dev": {
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"conflict": {
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"replace": {
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"provide": {
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"suggest": {
"aztech/layers": "0.1.*",
"sllh/php-cs-fixer-styleci-bridge": "^2.0"
},
"config": {
"sort-packages": true
}
}

0 comments on commit 24980dc

Please sign in to comment.