From f1af16984e44aa4e04a416f26eb2973a2449784f Mon Sep 17 00:00:00 2001 From: Gusakov Nikita Date: Mon, 17 Mar 2014 15:26:19 +0400 Subject: [PATCH 1/7] [Command] Add suggests command --- doc/03-cli.md | 11 +++++ src/Composer/Command/SuggestsCommand.php | 59 ++++++++++++++++++++++++ src/Composer/Console/Application.php | 1 + 3 files changed, 71 insertions(+) create mode 100644 src/Composer/Command/SuggestsCommand.php diff --git a/doc/03-cli.md b/doc/03-cli.md index b8921511c..8c5bf2f05 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -294,6 +294,17 @@ in your browser. * **--homepage (-H):** Open the homepage instead of the repository URL. +## suggests + +To list all of vendors suggesting to install packages, you can use the `suggests` command. + + $ php composer.phar suggests + + +### Options + +* **--dev:** Show dev suggests. + ## depends The `depends` command tells you which other packages depend on a certain diff --git a/src/Composer/Command/SuggestsCommand.php b/src/Composer/Command/SuggestsCommand.php new file mode 100644 index 000000000..18e3cf788 --- /dev/null +++ b/src/Composer/Command/SuggestsCommand.php @@ -0,0 +1,59 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Command; + +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Gusakov Nikita + */ +class SuggestsCommand extends Command +{ + protected function configure() + { + $this + ->setName('suggests') + ->setDescription('Show packages suggests') + ->setDefinition(array( + new InputOption('dev', null, InputOption::VALUE_NONE, 'Show dev suggests'), + )) + ->setHelp(<<suggests command show packages that suggesting to install other packages. + +EOT + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $lockData = $this->getComposer()->getLocker()->getLockData(); + $this->printSuggests($output, $lockData['packages']); + if ($input->getOption('dev')) { + $this->printSuggests($output, $lockData['packages-dev']); + } + } + + private function printSuggests(OutputInterface $output, array $packages) + { + foreach ($packages as $package) { + if (isset($package['suggest'])) { + foreach ($package['suggest'] as $target => $reason) { + $output->writeln($package['name'].' suggests installing '.$target.' ('.$reason.')'); + } + } + } + } +} diff --git a/src/Composer/Console/Application.php b/src/Composer/Console/Application.php index ee4f4e9c0..62654bf8b 100644 --- a/src/Composer/Console/Application.php +++ b/src/Composer/Console/Application.php @@ -272,6 +272,7 @@ class Application extends BaseApplication $commands[] = new Command\SearchCommand(); $commands[] = new Command\ValidateCommand(); $commands[] = new Command\ShowCommand(); + $commands[] = new Command\SuggestsCommand(); $commands[] = new Command\RequireCommand(); $commands[] = new Command\DumpAutoloadCommand(); $commands[] = new Command\StatusCommand(); From 760eeb0b033c328462093d8440d40aff46726183 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 23 Jun 2015 21:04:06 +0200 Subject: [PATCH 2/7] reworked suggests command --- doc/03-cli.md | 7 ++-- src/Composer/Command/SuggestsCommand.php | 45 +++++++++++++++--------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 8c5bf2f05..5b6e0fb00 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -296,14 +296,11 @@ in your browser. ## suggests -To list all of vendors suggesting to install packages, you can use the `suggests` command. - - $ php composer.phar suggests - +Lists all packages suggested by currently installed set of packages. ### Options -* **--dev:** Show dev suggests. +* **--no-dev:** Exludes suggestions from `require-dev` packages. ## depends diff --git a/src/Composer/Command/SuggestsCommand.php b/src/Composer/Command/SuggestsCommand.php index 18e3cf788..fd2193f9a 100644 --- a/src/Composer/Command/SuggestsCommand.php +++ b/src/Composer/Command/SuggestsCommand.php @@ -14,44 +14,57 @@ namespace Composer\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Finder\Exception\AccessDeniedException; -/** - * @author Gusakov Nikita - */ class SuggestsCommand extends Command { protected function configure() { $this ->setName('suggests') - ->setDescription('Show packages suggests') + ->setDescription('Show package suggestions') ->setDefinition(array( - new InputOption('dev', null, InputOption::VALUE_NONE, 'Show dev suggests'), + new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'), )) ->setHelp(<<suggests command show packages that suggesting to install other packages. +The %command.name% command shows suggested packages. EOT - ); + ) + ; } protected function execute(InputInterface $input, OutputInterface $output) { - $lockData = $this->getComposer()->getLocker()->getLockData(); - $this->printSuggests($output, $lockData['packages']); - if ($input->getOption('dev')) { - $this->printSuggests($output, $lockData['packages-dev']); + $lock = $this->getComposer()->getLocker()->getLockData(); + + if (empty($lock)) { + throw new \RuntimeException('Lockfile seems to be empty?'); + } + + $stderr = $output; + if ($output instanceof ConsoleOutputInterface) { + $stderr = $output->getErrorOutput(); + } + + $packages = $lock['packages']; + + if (!$input->getOption('no-dev')) { + $packages += $lock['packages-dev']; } - } - private function printSuggests(OutputInterface $output, array $packages) - { foreach ($packages as $package) { - if (isset($package['suggest'])) { + if (!empty($package['suggest'])) { + $stderr->writeln(sprintf('%s suggests:', $package['name'])); foreach ($package['suggest'] as $target => $reason) { - $output->writeln($package['name'].' suggests installing '.$target.' ('.$reason.')'); + if (empty($reason)) { + $reason = '*'; + } + + $output->writeln(sprintf('%s: %s', $target, $reason)); } } } From 33f78b2ccc3fa55ab1ec01d910c7456d8160f510 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 23 Jun 2015 21:29:48 +0200 Subject: [PATCH 3/7] limit suggestions to optional list of packages --- src/Composer/Command/SuggestsCommand.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Composer/Command/SuggestsCommand.php b/src/Composer/Command/SuggestsCommand.php index fd2193f9a..73e988beb 100644 --- a/src/Composer/Command/SuggestsCommand.php +++ b/src/Composer/Command/SuggestsCommand.php @@ -12,6 +12,7 @@ namespace Composer\Command; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\ConsoleOutputInterface; @@ -27,6 +28,7 @@ class SuggestsCommand extends Command ->setDescription('Show package suggestions') ->setDefinition(array( new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'), + new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'), )) ->setHelp(<<getErrorOutput(); } - $packages = $lock['packages']; + $list = $lock['packages']; if (!$input->getOption('no-dev')) { - $packages += $lock['packages-dev']; + $list += $lock['packages-dev']; } - foreach ($packages as $package) { - if (!empty($package['suggest'])) { + $packages = $input->getArgument('packages'); + + foreach ($list as $package) { + if (!empty($package['suggest']) && (empty($packages) || in_array($package['name'], $packages))) { $stderr->writeln(sprintf('%s suggests:', $package['name'])); foreach ($package['suggest'] as $target => $reason) { if (empty($reason)) { From 680082c5fe54bf1afd40af3af7f312d1cea267fe Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 23 Jun 2015 22:03:35 +0200 Subject: [PATCH 4/7] output based purely on verbosity --- src/Composer/Command/SuggestsCommand.php | 34 ++++++++++++++---------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/Composer/Command/SuggestsCommand.php b/src/Composer/Command/SuggestsCommand.php index 73e988beb..13558b693 100644 --- a/src/Composer/Command/SuggestsCommand.php +++ b/src/Composer/Command/SuggestsCommand.php @@ -15,9 +15,7 @@ namespace Composer\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Finder\Exception\AccessDeniedException; class SuggestsCommand extends Command { @@ -47,11 +45,7 @@ EOT throw new \RuntimeException('Lockfile seems to be empty?'); } - $stderr = $output; - if ($output instanceof ConsoleOutputInterface) { - $stderr = $output->getErrorOutput(); - } - + $io = $this->getIO(); $list = $lock['packages']; if (!$input->getOption('no-dev')) { @@ -62,14 +56,26 @@ EOT foreach ($list as $package) { if (!empty($package['suggest']) && (empty($packages) || in_array($package['name'], $packages))) { - $stderr->writeln(sprintf('%s suggests:', $package['name'])); - foreach ($package['suggest'] as $target => $reason) { - if (empty($reason)) { - $reason = '*'; - } + $this->printSuggestions($package['name'], $package['suggest']); + } + } + } + + protected function printSuggestions($name, $suggests) + { + $io = $this->getIO(); + + foreach ($suggests as $target => $reason) { + if (empty($reason)) { + $reason = '*'; + } - $output->writeln(sprintf('%s: %s', $target, $reason)); - } + if ($io->isVeryVerbose()) { + $io->write(sprintf('%s suggests %s: %s', $name, $target, $reason)); + } elseif ($io->isVerbose()) { + $io->write(sprintf('%s suggests %s', $name, $target)); + } else { + $io->write(sprintf('%s', $target)); } } } From b523a226414738d4739eae423d151735406dd852 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Tue, 23 Jun 2015 22:44:02 +0200 Subject: [PATCH 5/7] updated doc --- doc/03-cli.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 5b6e0fb00..db5f70dfa 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -296,11 +296,15 @@ in your browser. ## suggests -Lists all packages suggested by currently installed set of packages. +Lists all packages suggested by currently installed set of packages. You can +optionally pass one or multiple package names in the format of `vendor/package` +to limit output to suggestions made by those packages only. ### Options * **--no-dev:** Exludes suggestions from `require-dev` packages. +* **-v[v]:** Increased verbosity adds suggesting package name (`-v`) and + reason for suggestion (`-vv`). ## depends From adc3e3a7f29ff7be3e02f2ec8cd00dfb47855738 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Wed, 24 Jun 2015 08:43:07 +0200 Subject: [PATCH 6/7] fixed typo (and auto whitespace) --- doc/03-cli.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index db5f70dfa..6182db682 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -87,7 +87,7 @@ resolution. installing a package, you can use `--dry-run`. This will simulate the installation and show you what would happen. * **--dev:** Install packages listed in `require-dev` (this is the default behavior). -* **--no-dev:** Skip installing packages listed in `require-dev`. The autoloader +* **--no-dev:** Skip installing packages listed in `require-dev`. The autoloader generation skips the `autoload-dev` rules. * **--no-autoloader:** Skips autoloader generation. * **--no-scripts:** Skips execution of scripts defined in `composer.json`. @@ -302,7 +302,7 @@ to limit output to suggestions made by those packages only. ### Options -* **--no-dev:** Exludes suggestions from `require-dev` packages. +* **--no-dev:** Excludes suggestions from `require-dev` packages. * **-v[v]:** Increased verbosity adds suggesting package name (`-v`) and reason for suggestion (`-vv`). @@ -387,7 +387,7 @@ sudo composer self-update ### Options * **--rollback (-r):** Rollback to the last version you had installed. -* **--clean-backups:** Delete old backups during an update. This makes the +* **--clean-backups:** Delete old backups during an update. This makes the current version of Composer the only backup available after the update. ## config From 3dffdc8705b24f8535c676e36e4e4d061acc9531 Mon Sep 17 00:00:00 2001 From: Rob Bast Date: Wed, 24 Jun 2015 11:06:21 +0200 Subject: [PATCH 7/7] don't suggest packages already installed --- src/Composer/Command/SuggestsCommand.php | 50 ++++++++++++++++-------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/Composer/Command/SuggestsCommand.php b/src/Composer/Command/SuggestsCommand.php index 13558b693..c6f7385fd 100644 --- a/src/Composer/Command/SuggestsCommand.php +++ b/src/Composer/Command/SuggestsCommand.php @@ -45,38 +45,54 @@ EOT throw new \RuntimeException('Lockfile seems to be empty?'); } - $io = $this->getIO(); - $list = $lock['packages']; + $packages = $lock['packages']; if (!$input->getOption('no-dev')) { - $list += $lock['packages-dev']; + $packages += $lock['packages-dev']; } - $packages = $input->getArgument('packages'); + $filter = $input->getArgument('packages'); + + foreach ($packages as $package) { + if (empty($package['suggest'])) { + continue; + } - foreach ($list as $package) { - if (!empty($package['suggest']) && (empty($packages) || in_array($package['name'], $packages))) { - $this->printSuggestions($package['name'], $package['suggest']); + if (!empty($filter) && !in_array($package['name'], $filter)) { + continue; } + + $this->printSuggestions($packages, $package['name'], $package['suggest']); } } - protected function printSuggestions($name, $suggests) + protected function printSuggestions($installed, $source, $suggestions) { - $io = $this->getIO(); + foreach ($suggestions as $suggestion => $reason) { + foreach ($installed as $package) { + if ($package['name'] === $suggestion) { + continue 2; + } + } - foreach ($suggests as $target => $reason) { if (empty($reason)) { $reason = '*'; } - if ($io->isVeryVerbose()) { - $io->write(sprintf('%s suggests %s: %s', $name, $target, $reason)); - } elseif ($io->isVerbose()) { - $io->write(sprintf('%s suggests %s', $name, $target)); - } else { - $io->write(sprintf('%s', $target)); - } + $this->printSuggestion($source, $suggestion, $reason); + } + } + + protected function printSuggestion($package, $suggestion, $reason) + { + $io = $this->getIO(); + + if ($io->isVeryVerbose()) { + $io->write(sprintf('%s suggests %s: %s', $package, $suggestion, $reason)); + } elseif ($io->isVerbose()) { + $io->write(sprintf('%s suggests %s', $package, $suggestion)); + } else { + $io->write(sprintf('%s', $suggestion)); } } }