Skip to content
This repository has been archived by the owner on Mar 7, 2023. It is now read-only.

Commit

Permalink
Merge branch 'feature/1'
Browse files Browse the repository at this point in the history
Closes #1
  • Loading branch information
michalbundyra committed Oct 11, 2017
2 parents d982a27 + a324b9b commit 97c241b
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 18 deletions.
41 changes: 31 additions & 10 deletions src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Composer\Composer;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\DependencyResolver\Pool;
use Composer\EventDispatcher\EventDispatcher;
use Composer\EventDispatcher\EventSubscriberInterface;
Expand Down Expand Up @@ -37,6 +36,9 @@ class Plugin implements PluginInterface, EventSubscriberInterface
/** @var Composer */
private $composer;

/** @var string[] */
private $installedPackages;

/** @var IOInterface */
private $io;

Expand All @@ -58,6 +60,11 @@ public function activate(Composer $composer, IOInterface $io)
{
$this->composer = $composer;
$this->io = $io;

$installedPackages = $this->composer->getRepositoryManager()->getLocalRepository()->getPackages();
foreach ($installedPackages as $package) {
$this->installedPackages[$package->getName()] = $package->getPrettyVersion();
}
}

public function onPostPackage(PackageEvent $event)
Expand Down Expand Up @@ -145,14 +152,28 @@ private function runInstaller(RootPackageInterface $rootPackage, array $packages

private function promptForPackageVersion($name)
{
$validator = function ($input) {
$input = trim($input);
return $input ?: false;
};
// Package is currently installed. Add it to root composer.json
if (isset($this->installedPackages[$name])) {
$this->io->write(sprintf(
'Added package <info>%s</info> to composer.json with constraint <info>%s</info>;'
. ' to upgrade, run <info>composer require %s:VERSION</info>',
$name,
'^' . $this->installedPackages[$name],
$name
));

return '^' . $this->installedPackages[$name];
}

$constraint = $this->io->askAndValidate(
sprintf('Enter the version of %s to require (or leave blank to use the latest version): ', $name),
$validator
sprintf(
'Enter the version of <info>%s</info> to require (or leave blank to use the latest version): ',
$name
),
function ($input) {
$input = trim($input);
return $input ?: false;
}
);

if ($constraint === false) {
Expand Down Expand Up @@ -184,11 +205,11 @@ private function createInstaller(Composer $composer, IOInterface $io, RootPackag
);
}

private function hasPackage($name)
private function hasPackage($package)
{
$requires = $this->composer->getPackage()->getRequires();
foreach ($requires as $link) {
if (strtolower($link->getTarget()) === strtolower($name)) {
foreach ($requires as $name => $link) {
if (strtolower($name) === strtolower($package)) {
return true;
}
}
Expand Down
113 changes: 105 additions & 8 deletions test/PluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Composer\Package\RootPackageInterface;
use Composer\Package\Version\VersionSelector;
use Composer\Repository\RepositoryManager;
use Composer\Repository\WritableRepositoryInterface;
use org\bovigo\vfs\vfsStream;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
Expand All @@ -37,11 +38,24 @@ class PluginTest extends TestCase
/** @var IOInterface|ObjectProphecy */
private $io;

/** @var WritableRepositoryInterface */
private $localRepository;

protected function setUp()
{
parent::setUp();

$this->localRepository = $this->prophesize(WritableRepositoryInterface::class);
$this->localRepository->getPackages()->willReturn([]);

$repositoryManager = $this->prophesize(RepositoryManager::class);
$repositoryManager->getLocalRepository()->willReturn($this->localRepository->reveal());

$this->composer = $this->prophesize(Composer::class);
$this->composer->getRepositoryManager()
->willReturn($repositoryManager->reveal())
->shouldBeCalled();

$this->io = $this->prophesize(IOInterface::class);

$this->plugin = new Plugin();
Expand Down Expand Up @@ -244,7 +258,8 @@ public function testInstallSingleDependencyOnPackageUpdate()
$this->composer->getConfig()->willReturn($config->reveal());

$this->io->askAndValidate(
'Enter the version of extra-dependency-foo to require (or leave blank to use the latest version): ',
'Enter the version of <info>extra-dependency-foo</info> to require'
. ' (or leave blank to use the latest version): ',
Argument::type('callable')
)->willReturn('17.0.1-dev');

Expand Down Expand Up @@ -316,7 +331,8 @@ public function testInstallSingleDependencyOnPackageInstall()
$this->composer->getConfig()->willReturn($config->reveal());

$this->io->askAndValidate(
'Enter the version of extra-dependency-foo to require (or leave blank to use the latest version): ',
'Enter the version of <info>extra-dependency-foo</info> to require'
. ' (or leave blank to use the latest version): ',
Argument::type('callable')
)->willReturn('17.0.1-dev');

Expand Down Expand Up @@ -396,7 +412,8 @@ public function testInstallOneDependenciesWhenOneIsAlreadyInstalled()
$this->composer->getConfig()->willReturn($config->reveal());

$this->io->askAndValidate(
'Enter the version of extra-dependency-foo to require (or leave blank to use the latest version): ',
'Enter the version of <info>extra-dependency-foo</info> to require'
. ' (or leave blank to use the latest version): ',
Argument::type('callable')
)->willReturn('17.0.1-dev');

Expand Down Expand Up @@ -474,7 +491,8 @@ public function testInstallSingleDependencyAndAutomaticallyChooseLatestVersion()
$this->composer->getConfig()->willReturn($config->reveal());

$this->io->askAndValidate(
'Enter the version of extra-dependency-foo to require (or leave blank to use the latest version): ',
'Enter the version of <info>extra-dependency-foo</info> to require'
. ' (or leave blank to use the latest version): ',
Argument::type('callable')
)->willReturn(false);

Expand All @@ -500,6 +518,11 @@ public function testInstallSingleDependencyAndAutomaticallyChooseLatestVersion()
$this->setUpPool();

$this->assertNull($this->plugin->onPostPackage($event->reveal()));

$json = file_get_contents(vfsStream::url('project/composer.json'));
$composer = json_decode($json, true);
$this->assertTrue(isset($composer['require']['extra-dependency-foo']));
$this->assertSame('13.4.2', $composer['require']['extra-dependency-foo']);
}

public function testInstallSingleDependencyAndAutomaticallyChooseLatestVersionNotFoundMatchingPackage()
Expand Down Expand Up @@ -532,7 +555,8 @@ public function testInstallSingleDependencyAndAutomaticallyChooseLatestVersionNo
$this->composer->getConfig()->willReturn($config->reveal());

$this->io->askAndValidate(
'Enter the version of extra-dependency-foo to require (or leave blank to use the latest version): ',
'Enter the version of <info>extra-dependency-foo</info> to require'
. ' (or leave blank to use the latest version): ',
Argument::type('callable')
)->willReturn(false);

Expand All @@ -551,6 +575,82 @@ public function testInstallSingleDependencyAndAutomaticallyChooseLatestVersionNo
$this->plugin->onPostPackage($event->reveal());
}

public function testUpdateComposerWithCurrentlyInstalledVersion()
{
$installedPackage = $this->prophesize(PackageInterface::class);
$installedPackage->getName()->willReturn('extra-dependency-foo');
$installedPackage->getPrettyVersion()->willReturn('0.5.1');

$this->localRepository->getPackages()->willReturn([$installedPackage->reveal()]);
$this->plugin->activate($this->composer->reveal(), $this->io->reveal());

/** @var PackageInterface|ObjectProphecy $package */
$package = $this->prophesize(PackageInterface::class);
$package->getName()->willReturn('some/component');
$package->getExtra()->willReturn([
'dependency' => [
'extra-dependency-foo',
],
]);

$operation = $this->prophesize(InstallOperation::class);
$operation->getPackage()->willReturn($package->reveal());

$event = $this->prophesize(PackageEvent::class);
$event->isDevMode()->willReturn(true);
$event->getOperation()->willReturn($operation->reveal());

$config = $this->prophesize(Config::class);
$config->get('sort-packages')->willReturn(true);
$config->get(Argument::any())->willReturn(null);

$rootPackage = $this->prophesize(RootPackageInterface::class);
$rootPackage->getRequires()->willReturn([]);
$rootPackage->setRequires(Argument::that(function ($arguments) {
if (! is_array($arguments)) {
return false;
}

if (! isset($arguments['extra-dependency-foo'])) {
return false;
}

$argument = $arguments['extra-dependency-foo'];

if (! $argument instanceof Link) {
return false;
}

if ($argument->getTarget() !== 'extra-dependency-foo') {
return false;
}

if ($argument->getConstraint()->getPrettyString() !== '^0.5.1') {
return false;
}

if ($argument->getDescription() !== 'requires') {
return false;
}

return true;
}))->shouldBeCalled();
$rootPackage->getMinimumStability()->willReturn('stable');

$this->composer->getPackage()->willReturn($rootPackage);
$this->composer->getConfig()->willReturn($config->reveal());

$this->setUpComposerInstaller(['extra-dependency-foo']);
$this->setUpComposerJson();

$this->assertNull($this->plugin->onPostPackage($event->reveal()));

$json = file_get_contents(vfsStream::url('project/composer.json'));
$composer = json_decode($json, true);
$this->assertTrue(isset($composer['require']['extra-dependency-foo']));
$this->assertSame('^0.5.1', $composer['require']['extra-dependency-foo']);
}

public function testComposerInstallerFactory()
{
$r = new ReflectionProperty($this->plugin, 'installerFactory');
Expand All @@ -563,9 +663,6 @@ public function testComposerInstallerFactory()
$this->composer->getDownloadManager()
->willReturn($this->prophesize(DownloadManager::class))
->shouldBeCalled();
$this->composer->getRepositoryManager()
->willReturn($this->prophesize(RepositoryManager::class))
->shouldBeCalled();
$this->composer->getLocker()
->willReturn($this->prophesize(Locker::class))
->shouldBeCalled();
Expand Down

0 comments on commit 97c241b

Please sign in to comment.