diff --git a/src/Clue/PharComposer/App.php b/src/Clue/PharComposer/App.php
index 4e80879..be95e12 100644
--- a/src/Clue/PharComposer/App.php
+++ b/src/Clue/PharComposer/App.php
@@ -16,9 +16,6 @@ public function __construct()
$this->add(new Command\Build());
$this->add(new Command\Search());
$this->add(new Command\Install());
-
- // GUI feature disabled for now, see #35
- // $this->add(new Command\Gui());
}
/**
@@ -32,20 +29,11 @@ protected function getCommandName(InputInterface $input)
{
if ($input->getFirstArgument() === null && !$input->hasParameterOption(array('--help', '-h'))) {
$this->isDefault = true;
- return $this->getDefaultCommandName();
+ return 'search';
}
return parent::getCommandName($input);
}
- private function getDefaultCommandName()
- {
- $gui = $this->has('gui') ? $this->get('gui') : null;
- if ($gui instanceof Command\Gui && $gui->hasZenity()) {
- return 'gui';
- }
- return 'search';
- }
-
/**
* Overridden so that the application doesn't expect the command
* name to be the first argument.
diff --git a/src/Clue/PharComposer/Command/Build.php b/src/Clue/PharComposer/Command/Build.php
index c07e2b2..a0d9f1b 100644
--- a/src/Clue/PharComposer/Command/Build.php
+++ b/src/Clue/PharComposer/Command/Build.php
@@ -2,41 +2,41 @@
namespace Clue\PharComposer\Command;
-use Symfony\Component\Console\Formatter\OutputFormatterStyle;
-use Symfony\Component\Console\Helper\DialogHelper;
-use Symfony\Component\Console\Input\InputOption;
-use Symfony\Component\Console\Input\InputArgument;
+use Clue\PharComposer\Phar\Packager;
use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-use Clue\PharComposer\Phar\PharComposer;
-use InvalidArgumentException;
-use UnexpectedValueException;
-use Symfony\Component\Console\Output\Output;
-use Symfony\Component\Process\Process;
-use Symfony\Component\Process\ExecutableFinder;
-use Clue\PharComposer\Phar\Packager;
class Build extends Command
{
+ /** @var Packager */
+ private $packager;
+
+ public function __construct(Packager $packager = null)
+ {
+ parent::__construct();
+
+ if ($packager === null) {
+ $packager = new Packager();
+ }
+ $this->packager = $packager;
+ }
+
protected function configure()
{
$this->setName('build')
->setDescription('Build phar for the given composer project')
- ->addArgument('path', InputArgument::OPTIONAL, 'Path to project directory or composer.json', '.')
+ ->addArgument('project', InputArgument::OPTIONAL, 'Path to project directory or composer.json', '.')
->addArgument('target', InputArgument::OPTIONAL, 'Path to write phar output to (defaults to project name)');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
- $packager = new Packager();
- $packager->setOutput(function ($line) use ($output) {
- $output->write($line);
- });
-
- $packager->coerceWritable();
+ $this->packager->setOutput($output);
+ $this->packager->coerceWritable();
- $pharer = $packager->getPharer($input->getArgument('path'));
+ $pharer = $this->packager->getPharer($input->getArgument('project'));
$target = $input->getArgument('target');
if ($target !== null) {
diff --git a/src/Clue/PharComposer/Command/Gui.php b/src/Clue/PharComposer/Command/Gui.php
deleted file mode 100644
index 16cadea..0000000
--- a/src/Clue/PharComposer/Command/Gui.php
+++ /dev/null
@@ -1,283 +0,0 @@
-setName('gui')
- ->setDescription('Interactive GUI (requires Zenity, likely only on Linux/etc.)');
- }
-
- public function hasZenity()
- {
- return $this->hasBin('zenity');
- }
-
- private function hasBin($bin)
- {
- foreach (explode(PATH_SEPARATOR, getenv('PATH')) as $path) {
- $path = rtrim($path, '/') . '/' . $bin;
- if (file_exists($path)) {
- return true;
- }
- }
- return false;
- }
-
- protected function execute(InputInterface $input, OutputInterface $output)
- {
- $loop = Factory::create();
- $launcher = new Launcher($loop);
- $builder = new Builder($launcher);
-
- $packager = new Packager();
- $packager->setOutput(function ($line) use ($builder) {
- $builder->info(strip_tags($line))->waitReturn();
- });
- $packager->coerceWritable(0);
-
- foreach (array('gksudo', 'kdesudo', 'cocoasudo', 'sudo') as $bin) {
- if ($this->hasBin($bin)) {
- $packager->setBinSudo($bin);
- break;
- }
- }
-
- $packager->setOutput($output);
-
-
- $menu = $builder->listMenu(
- array(
- 'search' => 'Search package online',
- 'local' => 'Select local package',
- 'url' => 'Build from git-Repository',
- 'about' => 'About clue/phar-composer'
- ),
- 'Action'
- );
- $menu->setTitle('clue/phar-composer');
- $menu->setWindowIcon('info');
- $menu->setCancelLabel('Quit');
- $selection = $menu->waitReturn();
-
- if ($selection === 'search') {
- $pharer = $this->doSearch($builder, $packager);
- } elseif ($selection === 'local') {
- do {
- $dir = $builder->directorySelection()->waitReturn();
- if ($dir === false) {
- return;
- }
- try {
- $pharer = $packager->getPharer($dir);
- break;
- }
- catch (\Exception $e) {
- $builder->error('Could not initialize composer package:' . PHP_EOL . PHP_EOL . $e->getMessage())->waitReturn();
- }
- } while(true);
- } elseif ($selection === 'url') {
- $pharer = $this->doUrl($builder, $packager);
- } else {
- return;
- }
-
- if ($pharer === null) {
- return;
- }
-
- $action = $builder->listMenu(
- array(
- 'build' => 'Build project',
- 'install' => 'Install project system-wide'
- ),
- 'Action for "' . $pharer->getPackageRoot()->getName() .'"' /*,
- 'Quit' */
- )->waitReturn();
-
- if ($action === 'build') {
- $this->doBuild($builder, $packager, $pharer);
- } elseif ($action ==='install') {
- $this->doInstall($builder, $packager, $pharer);
- } else {
- return;
- }
-
- $builder->info('Successfully built ' . $pharer->getTarget() . '!')->waitReturn();
- }
-
- protected function doSearch(Builder $builder, Packager $packager)
- {
- $oldname = null;
-
- do {
- $dialog = $builder->entry('Search (partial) project name', $oldname);
- $dialog->setTitle('Search project name');
- $name = $dialog->waitReturn();
- if ($name === false) {
- return;
- }
- $oldname = $name;
-
- $pulsate = $builder->pulsate('Searching for "' . $name . '"...');
- $pulsate->setNoCancel(true);
- $pulsate->run();
-
- $packagist = new Client();
-
- $choices = array();
- foreach ($packagist->search($name) as $package) {
- /* @var $package Result */
-
- $choices[$package->getName()] = array(
- $package->getName(),
- mb_strimwidth($package->getDescription(), 0, 80, '…', 'utf-8'),
- $package->getDownloads()
- );
- }
-
- $pulsate->close();
-
- if (!$choices) {
- $builder->warning('No package matching "' . $name .'" found!')->waitReturn();
- $name = false;
- continue;
- }
-
- $table = $builder->table($choices, array('Name', 'Description', 'Downloads'), 'Select matching package');
- $table->setTitle('Select matching package');
- $table->setCancelLabel('Back to Search');
- $table->setWidth(1000);
- $table->setHeight(600);
-
- $name = $table->waitReturn();
- } while (is_bool($name));
-
- $pulsate = $builder->pulsate('Selected ' . $name . ', listing versions...');
- $pulsate->setNoCancel(true);
- $pulsate->run();
-
- $package = $packagist->get($name);
- /* @var $package Package */
-
- $choices = array();
- foreach ($package->getVersions() as $version) {
- /* @var $version Version */
-
- $time = new \DateTime($version->getTime());
- $time = $time->format('Y-m-d H:i:s');
-
- $bin = $version->getBin();
- if ($bin) {
- $bin = '☑ ' . array_shift($bin);
- } else {
- $bin = '☐ no executable bin';
- }
-
- $choices[$version->getVersion()] = array(
- $version->getVersion(),
- $time,
- $bin
- );
- }
-
- $pulsate->close();
-
- if (!$choices) {
- $builder->warning('No versions for package "' . $name .'" found!')->waitReturn();
- return;
- }
-
- $dialog = $builder->table($choices, array('Version', 'Date', 'Binary'), 'Select available version');
- $dialog->setWidth(800);
- $dialog->setHeight(300);
- $version = $dialog->waitReturn();
-
- if (is_bool($version)) {
- return;
- }
-
- $pulsate = $builder->pulsate('Installing to temporary directory...')->run();
- $pharer = $packager->getPharer($name, $version);
- $pulsate->close();
-
- return $pharer;
- }
-
- protected function doUrl(Builder $builder, Packager $packager)
- {
- do {
- $url = $builder->entry('Git URL to clone')->waitReturn();
- if ($url === false) {
- return;
- }
- $pulsate = $builder->pulsate('Cloning and installing from git...')->run();
- try {
- $pharer = $packager->getPharer($url);
- $pulsate->close();
-
- return $pharer;
- }
- catch (\Exception $e) {
- $pulsate->close();
-
- $builder->error('Unable to clone repository:' . PHP_EOL . PHP_EOL . $e->getMessage())->waitReturn();
- }
- } while(true);
- }
-
- protected function doInstall(Builder $builder, Packager $packager, PharComposer $pharer)
- {
- $pulsate = $builder->pulsate('Installing...')->run();
-
- $path = $packager->getSystemBin($pharer);
- $packager->install($pharer, $path);
-
- $pulsate->close();
- }
-
- protected function doBuild(Builder $builder, Packager $packager, PharComposer $pharer)
- {
- $pulsate = $builder->pulsate('Waiting for target file name...')->run();
-
- $save = $builder->fileSave('Location to write file to', $pharer->getTarget());
-
- $target = $save->waitReturn();
-
- if ($target === false) {
- return;
- }
-
- $pulsate->close();
- $pulsate = $builder->pulsate('Building target file...')->run();
-
- $pharer->setTarget($target);
- $pharer->build();
-
- $pulsate->close();
- }
-}
diff --git a/src/Clue/PharComposer/Command/Install.php b/src/Clue/PharComposer/Command/Install.php
index 1c8d0df..00a4e24 100644
--- a/src/Clue/PharComposer/Command/Install.php
+++ b/src/Clue/PharComposer/Command/Install.php
@@ -2,43 +2,55 @@
namespace Clue\PharComposer\Command;
-use Symfony\Component\Console\Command\Command;
use Clue\PharComposer\Phar\Packager;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Helper\DialogHelper;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Helper\DialogHelper;
class Install extends Command
{
+ /** @var Packager */
+ private $packager;
+
+ public function __construct(Packager $packager = null)
+ {
+ parent::__construct();
+
+ if ($packager === null) {
+ $packager = new Packager();
+ }
+ $this->packager = $packager;
+ }
+
protected function configure()
{
$this->setName('install')
->setDescription('Install phar into system wide binary directory')
- ->addArgument('name', InputArgument::OPTIONAL, 'Project name or path', '.')
- ->addArgument('path', InputArgument::OPTIONAL, 'Path to install to', '/usr/local/bin');
+ ->addArgument('project', InputArgument::OPTIONAL, 'Project name or path', '.')
+ ->addArgument('target', InputArgument::OPTIONAL, 'Path to install to', '/usr/local/bin');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
- $packager = new Packager();
- $packager->setOutput($output);
- $packager->coerceWritable();
+ $this->packager->setOutput($output);
+ $this->packager->coerceWritable();
- $pharer = $packager->getPharer($input->getArgument('name'));
+ $pharer = $this->packager->getPharer($input->getArgument('project'));
- $path = $packager->getSystemBin($pharer, $input->getArgument('path'));
+ $path = $this->packager->getSystemBin($pharer, $input->getArgument('target'));
if (is_file($path)) {
- $dialog = $this->getHelperSet()->get('dialog');
- /* @var $dialog DialogHelper */
+ $dialog = $this->getHelper('dialog');
+ assert($dialog instanceof DialogHelper);
if (!$dialog->askConfirmation($output, 'Overwrite existing file ' . $path . '? [y] > ')) {
$output->writeln('Aborting');
- return;
+ return 0;
}
}
- $packager->install($pharer, $path);
+ $this->packager->install($pharer, $path);
}
}
diff --git a/src/Clue/PharComposer/Command/Search.php b/src/Clue/PharComposer/Command/Search.php
index 74bc184..e29a894 100644
--- a/src/Clue/PharComposer/Command/Search.php
+++ b/src/Clue/PharComposer/Command/Search.php
@@ -3,52 +3,65 @@
namespace Clue\PharComposer\Command;
-use Symfony\Component\Console\Formatter\OutputFormatterStyle;
+use Clue\PharComposer\Phar\Packager;
+use Packagist\Api\Client;
+use Packagist\Api\Result\Package;
+use Packagist\Api\Result\Package\Version;
+use Packagist\Api\Result\Result;
+use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\DialogHelper;
-use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
-use Clue\PharComposer\Phar\PharComposer;
-use InvalidArgumentException;
-use UnexpectedValueException;
-use Symfony\Component\Console\Output\Output;
-use Symfony\Component\Process\Process;
-use Symfony\Component\Process\ExecutableFinder;
-use Packagist\Api\Client;
-use Packagist\Api\Result\Result;
-use Packagist\Api\Result\Package;
-use Packagist\Api\Result\Package\Version;
-use Clue\PharComposer\Phar\Packager;
class Search extends Command
{
+ /** @var Packager */
+ private $packager;
+
+ /** @var Client */
+ private $packagist;
+
+ public function __construct(Packager $packager = null, Client $packagist = null)
+ {
+ parent::__construct();
+
+ if ($packager === null) {
+ $packager = new Packager();
+ }
+ if ($packagist === null) {
+ $packagist = new Client();
+ }
+ $this->packager = $packager;
+ $this->packagist = $packagist;
+ }
+
protected function configure()
{
$this->setName('search')
->setDescription('Interactive search for project name')
- ->addArgument('name', InputArgument::OPTIONAL, 'Project name or path', null);
+ ->addArgument('project', InputArgument::OPTIONAL, 'Project name or path', null);
}
+ /**
+ * @param OutputInterface $output
+ * @param string $label
+ * @param array $choices
+ * @param ?string $abortable
+ * @return ?string
+ */
protected function select(OutputInterface $output, $label, array $choices, $abortable = null)
{
- $dialog = $this->getHelperSet()->get('dialog');
- /* @var $dialog DialogHelper */
+ $dialog = $this->getHelper('dialog');
+ assert($dialog instanceof DialogHelper);
if (!$choices) {
$output->writeln('No matching packages found');
- return;
+ return null;
}
// TODO: skip dialog, if exact match
- if ($abortable === true) {
- $abortable = 'Abort';
- } elseif ($abortable === false) {
- $abortable = null;
- }
-
$select = array_merge(array(0 => $abortable), array_values($choices));
if ($abortable === null) {
unset($select[0]);
@@ -56,7 +69,7 @@ protected function select(OutputInterface $output, $label, array $choices, $abor
$index = $dialog->select($output, $label, $select);
- if ($index == 0) {
+ if ($index === 0) {
return null;
}
@@ -66,58 +79,52 @@ protected function select(OutputInterface $output, $label, array $choices, $abor
protected function execute(InputInterface $input, OutputInterface $output)
{
- $packager = new Packager();
- $packager->setOutput($output);
- $packager->coerceWritable();
+ $this->packager->setOutput($output);
+ $this->packager->coerceWritable();
- $dialog = $this->getHelperSet()->get('dialog');
- /* @var $dialog DialogHelper */
+ $dialog = $this->getHelper('dialog');
+ assert($dialog instanceof DialogHelper);
- $name = $input->getArgument('name');
+ $project = $input->getArgument('project');
do {
- if ($name === null) {
+ if ($project === null) {
// ask for input
- $name = $dialog->ask($output, 'Enter (partial) project name > ');
+ $project = $dialog->ask($output, 'Enter (partial) project name > ');
} else {
- $output->writeln('Searching for ' . $name . '...');
+ $output->writeln('Searching for ' . $project . '...');
}
- $packagist = new Client();
-
$choices = array();
- foreach ($packagist->search($name) as $package) {
- /* @var $package Result */
+ foreach ($this->packagist->search($project) as $result) {
+ assert($result instanceof Result);
- $label = str_pad($package->getName(), 39) . ' ';
- $label = str_replace($name, '' . $name . '', $label);
- $label .= $package->getDescription();
+ $label = str_pad($result->getName(), 39) . ' ';
+ $label = str_replace($project, '' . $project . '', $label);
+ $label .= $result->getDescription();
- $label .= ' (⤓' . $package->getDownloads() . ')';
+ $label .= ' (⤓' . $result->getDownloads() . ')';
- $choices[$package->getName()] = $label;
+ $choices[$result->getName()] = $label;
}
- $name = $this->select($output, 'Select matching package', $choices, 'Start new search');
- } while ($name === null);
+ $project = $this->select($output, 'Select matching package', $choices, 'Start new search');
+ } while ($project === null);
- $output->writeln('Selected ' . $name . ', listing versions...');
+ $output->writeln('Selected ' . $project . ', listing versions...');
- $package = $packagist->get($name);
- /* @var $package Package */
+ $package = $this->packagist->get($project);
+ assert($package instanceof Package);
$choices = array();
foreach ($package->getVersions() as $version) {
- /* @var $version Version */
+ assert($version instanceof Version);
$label = $version->getVersion();
+ /* @var ?string $bin */
$bin = $version->getBin();
- if ($bin === null) {
- $label .= ' (no executable bin)';
- } else {
- $label .= ' (☑ executable bin)';
- }
+ $label .= $bin !== null ? ' (☑ executable bin)' : ' (no executable bin)';
$choices[$version->getVersion()] = $label;
}
@@ -135,17 +142,14 @@ protected function execute(InputInterface $input, OutputInterface $output)
);
if ($action === null) {
- return;
+ return 0;
}
-
-
- $pharer = $packager->getPharer($name, $version);
-
+ $pharer = $this->packager->getPharer($project, $version);
if ($action === 'install') {
- $path = $packager->getSystemBin($pharer);
- $packager->install($pharer, $path);
+ $path = $this->packager->getSystemBin($pharer);
+ $this->packager->install($pharer, $path);
} else {
$pharer->build();
}
diff --git a/src/Clue/PharComposer/Package/Bundle.php b/src/Clue/PharComposer/Package/Bundle.php
index 2face2b..31af0ee 100644
--- a/src/Clue/PharComposer/Package/Bundle.php
+++ b/src/Clue/PharComposer/Package/Bundle.php
@@ -2,8 +2,8 @@
namespace Clue\PharComposer\Package;
-use Symfony\Component\Finder\Finder;
use Clue\PharComposer\Logger;
+use Symfony\Component\Finder\Finder;
/**
* A bundle represents all resources from a package that should be bundled into
@@ -23,7 +23,7 @@ class Bundle implements \IteratorAggregate
*
* @param Package $package
* @param Logger $logger
- * @return Bundle
+ * @return self
*/
public static function from(Package $package, Logger $logger)
{
diff --git a/src/Clue/PharComposer/Package/Bundler/BundlerInterface.php b/src/Clue/PharComposer/Package/Bundler/BundlerInterface.php
index e09385b..15008ca 100644
--- a/src/Clue/PharComposer/Package/Bundler/BundlerInterface.php
+++ b/src/Clue/PharComposer/Package/Bundler/BundlerInterface.php
@@ -10,7 +10,7 @@ interface BundlerInterface
/**
* returns a bundle
*
- * @return Bundle
+ * @return \Clue\PharComposer\Package\Bundle
*/
public function bundle();
}
diff --git a/src/Clue/PharComposer/Package/Package.php b/src/Clue/PharComposer/Package/Package.php
index ae74856..9c4a8cd 100644
--- a/src/Clue/PharComposer/Package/Package.php
+++ b/src/Clue/PharComposer/Package/Package.php
@@ -2,17 +2,20 @@
namespace Clue\PharComposer\Package;;
-use Symfony\Component\Finder\SplFileInfo;
-use Clue\PharComposer\Package\Bundler\Explicit as ExplicitBundler;
+use Clue\PharComposer\Package\Bundler\BundlerInterface;
use Clue\PharComposer\Package\Bundler\Complete as CompleteBundler;
-use Clue\PharComposer\Package\Autoload;
+use Clue\PharComposer\Package\Bundler\Explicit as ExplicitBundler;
use Clue\PharComposer\Logger;
+use Symfony\Component\Finder\SplFileInfo;
/**
* The package represents either the main/root package or one of the vendor packages.
*/
class Package
{
+ private $package;
+ private $directory;
+
/**
* Instantiate package
*
@@ -143,7 +146,7 @@ public function getBlacklist()
*
* Only used for CompleteBundler at the moment
*
- * @return Closure
+ * @return \Closure
* @uses self::getBlacklist()
*/
public function getBlacklistFilter()
diff --git a/src/Clue/PharComposer/Phar/Packager.php b/src/Clue/PharComposer/Phar/Packager.php
index e7ab068..0ae4b39 100644
--- a/src/Clue/PharComposer/Phar/Packager.php
+++ b/src/Clue/PharComposer/Phar/Packager.php
@@ -32,6 +32,9 @@ public function setBinSudo($bin)
$this->binSudo = $bin;
}
+ /**
+ * @param OutputInterface|bool|callable $fn
+ */
public function setOutput($fn)
{
if ($fn instanceof OutputInterface) {
@@ -91,6 +94,14 @@ public function assertWritable()
}
}
+ /**
+ * @param string $path
+ * @param string $version
+ * @return PharComposer
+ * @throws UnexpectedValueException
+ * @throws InvalidArgumentException
+ * @throws RuntimeException
+ */
public function getPharer($path, $version = null)
{
if ($version !== null) {
diff --git a/tests/Command/BuildTest.php b/tests/Command/BuildTest.php
new file mode 100644
index 0000000..fa2056e
--- /dev/null
+++ b/tests/Command/BuildTest.php
@@ -0,0 +1,59 @@
+setAccessible(true);
+ $packager = $ref->getValue($command);
+
+ $this->assertInstanceOf('Clue\PharComposer\Phar\Packager', $packager);
+ }
+
+ public function testExecuteBuildWillBuildPharer()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->exactly(2))->method('getArgument')->withConsecutive(
+ array('project'),
+ array('target')
+ )->willReturnOnConsecutiveCalls('dir', null);
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $pharer = $this->getMockBuilder('Clue\PharComposer\Phar\PharComposer')->disableOriginalConstructor()->getMock();
+ $pharer->expects($this->never())->method('setTarget');
+ $pharer->expects($this->once())->method('build');
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+ $packager->expects($this->once())->method('setOutput')->with($output);
+ $packager->expects($this->once())->method('getPharer')->with('dir')->willReturn($pharer);
+
+ $command = new Build($packager);
+ $command->run($input, $output);
+ }
+
+ public function testExecuteBuildWillBuildPharerWithExplicitTarget()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->exactly(2))->method('getArgument')->withConsecutive(
+ array('project'),
+ array('target')
+ )->willReturnOnConsecutiveCalls('dir', 'targetDir');
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $pharer = $this->getMockBuilder('Clue\PharComposer\Phar\PharComposer')->disableOriginalConstructor()->getMock();
+ $pharer->expects($this->once())->method('setTarget')->with('targetDir');
+ $pharer->expects($this->once())->method('build');
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+ $packager->expects($this->once())->method('setOutput')->with($output);
+ $packager->expects($this->once())->method('getPharer')->with('dir')->willReturn($pharer);
+
+ $command = new Build($packager);
+ $command->run($input, $output);
+ }
+}
diff --git a/tests/Command/InstallTest.php b/tests/Command/InstallTest.php
new file mode 100644
index 0000000..34d2d38
--- /dev/null
+++ b/tests/Command/InstallTest.php
@@ -0,0 +1,119 @@
+setAccessible(true);
+ $packager = $ref->getValue($command);
+
+ $this->assertInstanceOf('Clue\PharComposer\Phar\Packager', $packager);
+ }
+
+ public function testExecuteInstallWillInstallPackager()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->exactly(2))->method('getArgument')->withConsecutive(
+ array('project'),
+ array('target')
+ )->willReturnOnConsecutiveCalls('dir', null);
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $pharer = $this->getMockBuilder('Clue\PharComposer\Phar\PharComposer')->disableOriginalConstructor()->getMock();
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+ $packager->expects($this->once())->method('setOutput')->with($output);
+ $packager->expects($this->once())->method('getPharer')->with('dir')->willReturn($pharer);
+ $packager->expects($this->once())->method('getSystemBin')->with($pharer, null)->willReturn('targetPath');
+ $packager->expects($this->once())->method('install')->with($pharer, 'targetPath');
+
+ $command = new Install($packager);
+ $command->run($input, $output);
+ }
+
+ public function testExecuteInstallWillInstallPackagerWithExplicitTarget()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->exactly(2))->method('getArgument')->withConsecutive(
+ array('project'),
+ array('target')
+ )->willReturnOnConsecutiveCalls('dir', 'targetDir');
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $pharer = $this->getMockBuilder('Clue\PharComposer\Phar\PharComposer')->disableOriginalConstructor()->getMock();
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+ $packager->expects($this->once())->method('setOutput')->with($output);
+ $packager->expects($this->once())->method('getPharer')->with('dir')->willReturn($pharer);
+ $packager->expects($this->once())->method('getSystemBin')->with($pharer, 'targetDir')->willReturn('targetPath');
+ $packager->expects($this->once())->method('install')->with($pharer, 'targetPath');
+
+ $command = new Install($packager);
+ $command->run($input, $output);
+ }
+
+ public function testExecuteInstallWillInstallPackagerWhenTargetPathAlreadyExistsAndDialogQuestionYieldsYes()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->exactly(2))->method('getArgument')->withConsecutive(
+ array('project'),
+ array('target')
+ )->willReturnOnConsecutiveCalls('dir', null);
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $dialogHelper = $this->getMock('Symfony\Component\Console\Helper\DialogHelper');
+ $dialogHelper->expects($this->once())->method('askConfirmation')->willReturn(true);
+
+ $helpers = new HelperSet(array(
+ 'dialog' => $dialogHelper
+ ));
+
+ $pharer = $this->getMockBuilder('Clue\PharComposer\Phar\PharComposer')->disableOriginalConstructor()->getMock();
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+ $packager->expects($this->once())->method('setOutput')->with($output);
+ $packager->expects($this->once())->method('getPharer')->with('dir')->willReturn($pharer);
+ $packager->expects($this->once())->method('getSystemBin')->with($pharer, null)->willReturn(__FILE__);
+ $packager->expects($this->once())->method('install')->with($pharer, __FILE__);
+
+ $command = new Install($packager);
+ $command->setHelperSet($helpers);
+ $command->run($input, $output);
+ }
+
+ public function testExecuteInstallWillNotInstallPackagerWhenTargetPathAlreadyExistsAndDialogQuestionShouldNotOverwrite()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->exactly(2))->method('getArgument')->withConsecutive(
+ array('project'),
+ array('target')
+ )->willReturnOnConsecutiveCalls('dir', null);
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+ $output->expects($this->once())->method('writeln')->with('Aborting');
+
+ $dialogHelper = $this->getMock('Symfony\Component\Console\Helper\DialogHelper');
+ $dialogHelper->expects($this->once())->method('askConfirmation')->willReturn(false);
+
+ $helpers = new HelperSet(array(
+ 'dialog' => $dialogHelper
+ ));
+
+ $pharer = $this->getMockBuilder('Clue\PharComposer\Phar\PharComposer')->disableOriginalConstructor()->getMock();
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+ $packager->expects($this->once())->method('setOutput')->with($output);
+ $packager->expects($this->once())->method('getPharer')->with('dir')->willReturn($pharer);
+ $packager->expects($this->once())->method('getSystemBin')->with($pharer, null)->willReturn(__FILE__);
+ $packager->expects($this->never())->method('install');
+
+ $command = new Install($packager);
+ $command->setHelperSet($helpers);
+ $command->run($input, $output);
+ }
+}
diff --git a/tests/Command/SearchTest.php b/tests/Command/SearchTest.php
new file mode 100644
index 0000000..01dbe3a
--- /dev/null
+++ b/tests/Command/SearchTest.php
@@ -0,0 +1,284 @@
+setAccessible(true);
+ $packager = $ref->getValue($command);
+
+ $ref = new ReflectionProperty($command, 'packagist');
+ $ref->setAccessible(true);
+ $packagist = $ref->getValue($command);
+
+ $this->assertInstanceOf('Clue\PharComposer\Phar\Packager', $packager);
+ $this->assertInstanceOf('Packagist\Api\Client', $packagist);
+ }
+
+ /**
+ * @expectedException RuntimeException
+ * @expectedExceptionMessage stop1
+ */
+ public function testExecuteWithoutProjectWillAskForProjectAndRunSearch()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->once())->method('getArgument')->with('project')->willReturn(null);
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $dialogHelper = $this->getMock('Symfony\Component\Console\Helper\DialogHelper');
+ $dialogHelper->expects($this->once())->method('ask')->willReturn('foo');
+
+ $helpers = new HelperSet(array(
+ 'dialog' => $dialogHelper
+ ));
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+
+ $packagist = $this->getMock('Packagist\Api\Client');
+ $packagist->expects($this->once())->method('search')->with('foo')->willThrowException(new RuntimeException('stop1'));
+
+ $command = new Search($packager, $packagist);
+ $command->setHelperSet($helpers);
+ $command->run($input, $output);
+ }
+
+ /**
+ * @expectedException RuntimeException
+ * @expectedExceptionMessage stop1
+ */
+ public function testExecuteWithProjectWillRunSearchWithoutAskingForProject()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->once())->method('getArgument')->with('project')->willReturn('foo');
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $dialogHelper = $this->getMock('Symfony\Component\Console\Helper\DialogHelper');
+ $dialogHelper->expects($this->never())->method('ask');
+
+ $helpers = new HelperSet(array(
+ 'dialog' => $dialogHelper
+ ));
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+
+ $packagist = $this->getMock('Packagist\Api\Client');
+ $packagist->expects($this->once())->method('search')->with('foo')->willThrowException(new RuntimeException('stop1'));
+
+ $command = new Search($packager, $packagist);
+ $command->setHelperSet($helpers);
+ $command->run($input, $output);
+ }
+
+ /**
+ * @expectedException RuntimeException
+ * @expectedExceptionMessage stop1
+ */
+ public function testExecuteWithProjectAndSearchReturnsNoMatchesWillReportAndAskForOtherProject()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->once())->method('getArgument')->with('project')->willReturn('foo');
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+ $output->expects($this->exactly(2))->method('writeln')->withConsecutive(
+ array('Searching for foo...'),
+ array('No matching packages found')
+ );
+
+ $dialogHelper = $this->getMock('Symfony\Component\Console\Helper\DialogHelper');
+ $dialogHelper->expects($this->once())->method('ask')->willThrowException(new RuntimeException('stop1'));
+
+ $helpers = new HelperSet(array(
+ 'dialog' => $dialogHelper
+ ));
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+
+ $packagist = $this->getMock('Packagist\Api\Client');
+ $packagist->expects($this->once())->method('search')->with('foo')->willReturn(array());
+
+ $command = new Search($packager, $packagist);
+ $command->setHelperSet($helpers);
+ $command->run($input, $output);
+ }
+
+ /**
+ * @expectedException RuntimeException
+ * @expectedExceptionMessage stop1
+ */
+ public function testExecuteWithProjectAndSearchReturnsOneMatchWillAskForProject()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->once())->method('getArgument')->with('project')->willReturn('foo');
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $dialogHelper = $this->getMock('Symfony\Component\Console\Helper\DialogHelper');
+ $dialogHelper->expects($this->once())->method('select')->willThrowException(new RuntimeException('stop1'));
+ $dialogHelper->expects($this->never())->method('ask');
+
+ $helpers = new HelperSet(array(
+ 'dialog' => $dialogHelper
+ ));
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+
+ $result = $this->getMock('Packagist\Api\Result\Result');
+
+ $packagist = $this->getMock('Packagist\Api\Client');
+ $packagist->expects($this->once())->method('search')->with('foo')->willReturn(array($result));
+
+ $command = new Search($packager, $packagist);
+ $command->setHelperSet($helpers);
+ $command->run($input, $output);
+ }
+
+ /**
+ * @expectedException RuntimeException
+ * @expectedExceptionMessage stop1
+ */
+ public function testExecuteWithProjectSelectedWillSearchVersions()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->once())->method('getArgument')->with('project')->willReturn('foo');
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+ $output->expects($this->exactly(2))->method('writeln')->withConsecutive(
+ array('Searching for foo...'),
+ array('Selected foo/bar, listing versions...')
+ );
+
+ $dialogHelper = $this->getMock('Symfony\Component\Console\Helper\DialogHelper');
+ $dialogHelper->expects($this->once())->method('select')->willReturn(1);
+ $dialogHelper->expects($this->never())->method('ask');
+
+ $helpers = new HelperSet(array(
+ 'dialog' => $dialogHelper
+ ));
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+
+ $result = $this->getMock('Packagist\Api\Result\Result');
+ $result->expects($this->exactly(2))->method('getName')->willReturn('foo/bar');
+
+ $packagist = $this->getMock('Packagist\Api\Client');
+ $packagist->expects($this->once())->method('search')->with('foo')->willReturn(array($result));
+ $packagist->expects($this->once())->method('get')->with('foo/bar')->willThrowException(new RuntimeException('stop1'));
+
+ $command = new Search($packager, $packagist);
+ $command->setHelperSet($helpers);
+ $command->run($input, $output);
+ }
+
+ public function testExecuteWithProjectAndVersionSelectedWillQuitWhenAskedForActionYieldsQuit()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->once())->method('getArgument')->with('project')->willReturn('foo');
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+
+ $dialogHelper = $this->getMock('Symfony\Component\Console\Helper\DialogHelper');
+ $dialogHelper->expects($this->exactly(3))->method('select')->willReturnOnConsecutiveCalls(1, 1, 0);
+
+ $helpers = new HelperSet(array(
+ 'dialog' => $dialogHelper
+ ));
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+
+ $result = $this->getMock('Packagist\Api\Result\Result');
+ $result->expects($this->exactly(2))->method('getName')->willReturn('foo/bar');
+
+ $version = $this->getMock('Packagist\Api\Result\Package\Version');
+ $version->expects($this->exactly(2))->method('getVersion')->willReturn('dev-master');
+
+ $package = $this->getMock('Packagist\Api\Result\Package');
+ $package->expects($this->once())->method('getVersions')->willReturn(array($version));
+
+ $packagist = $this->getMock('Packagist\Api\Client');
+ $packagist->expects($this->once())->method('search')->with('foo')->willReturn(array($result));
+ $packagist->expects($this->once())->method('get')->with('foo/bar')->willReturn($package);
+
+ $command = new Search($packager, $packagist);
+ $command->setHelperSet($helpers);
+ $command->run($input, $output);
+ }
+
+ public function testExecuteWithProjectAndVersionSelectedWillBuildWhenAskedForActionYieldsBuild()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->once())->method('getArgument')->with('project')->willReturn('foo');
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $dialogHelper = $this->getMock('Symfony\Component\Console\Helper\DialogHelper');
+ $dialogHelper->expects($this->exactly(3))->method('select')->willReturnOnConsecutiveCalls(1, 1, 1);
+
+ $helpers = new HelperSet(array(
+ 'dialog' => $dialogHelper
+ ));
+
+ $pharer = $this->getMockBuilder('Clue\PharComposer\Phar\PharComposer')->disableOriginalConstructor()->getMock();
+ $pharer->expects($this->once())->method('build');
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+ $packager->expects($this->once())->method('getPharer')->with('foo/bar', 'dev-master')->willReturn($pharer);
+
+ $result = $this->getMock('Packagist\Api\Result\Result');
+ $result->expects($this->exactly(2))->method('getName')->willReturn('foo/bar');
+
+ $version = $this->getMock('Packagist\Api\Result\Package\Version');
+ $version->expects($this->exactly(2))->method('getVersion')->willReturn('dev-master');
+
+ $package = $this->getMock('Packagist\Api\Result\Package');
+ $package->expects($this->once())->method('getVersions')->willReturn(array($version));
+
+ $packagist = $this->getMock('Packagist\Api\Client');
+ $packagist->expects($this->once())->method('search')->with('foo')->willReturn(array($result));
+ $packagist->expects($this->once())->method('get')->with('foo/bar')->willReturn($package);
+
+ $command = new Search($packager, $packagist);
+ $command->setHelperSet($helpers);
+ $command->run($input, $output);
+ }
+
+ public function testExecuteWithProjectAndVersionSelectedWillInstallWhenAskedForActionYieldsInstall()
+ {
+ $input = $this->getMock('Symfony\Component\Console\Input\InputInterface');
+ $input->expects($this->once())->method('getArgument')->with('project')->willReturn('foo');
+ $output = $this->getMock('Symfony\Component\Console\Output\OutputInterface');
+
+ $dialogHelper = $this->getMock('Symfony\Component\Console\Helper\DialogHelper');
+ $dialogHelper->expects($this->exactly(3))->method('select')->willReturnOnConsecutiveCalls(1, 1, 2);
+
+ $helpers = new HelperSet(array(
+ 'dialog' => $dialogHelper
+ ));
+
+ $pharer = $this->getMockBuilder('Clue\PharComposer\Phar\PharComposer')->disableOriginalConstructor()->getMock();
+ $pharer->expects($this->never())->method('build');
+
+ $packager = $this->getMock('Clue\PharComposer\Phar\Packager');
+ $packager->expects($this->once())->method('getPharer')->with('foo/bar', 'dev-master')->willReturn($pharer);
+ $packager->expects($this->once())->method('getSystemBin')->with($pharer)->willReturn('targetPath');
+ $packager->expects($this->once())->method('install')->with($pharer, 'targetPath');
+
+ $result = $this->getMock('Packagist\Api\Result\Result');
+ $result->expects($this->exactly(2))->method('getName')->willReturn('foo/bar');
+
+ $version = $this->getMock('Packagist\Api\Result\Package\Version');
+ $version->expects($this->exactly(2))->method('getVersion')->willReturn('dev-master');
+
+ $package = $this->getMock('Packagist\Api\Result\Package');
+ $package->expects($this->once())->method('getVersions')->willReturn(array($version));
+
+ $packagist = $this->getMock('Packagist\Api\Client');
+ $packagist->expects($this->once())->method('search')->with('foo')->willReturn(array($result));
+ $packagist->expects($this->once())->method('get')->with('foo/bar')->willReturn($package);
+
+ $command = new Search($packager, $packagist);
+ $command->setHelperSet($helpers);
+ $command->run($input, $output);
+ }
+}