Merge remote-tracking branch 'curry684/rewrite-depends'
commit
f681dbc51e
|
@ -328,34 +328,67 @@ to limit output to suggestions made by those packages only.
|
||||||
## depends
|
## depends
|
||||||
|
|
||||||
The `depends` command tells you which other packages depend on a certain
|
The `depends` command tells you which other packages depend on a certain
|
||||||
package. You can specify which link types (`require`, `require-dev`)
|
package. As with installation `require-dev` relationships are only considered
|
||||||
should be included in the listing. By default both are used.
|
for the root package.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
php composer.phar depends --link-type=require monolog/monolog
|
php composer.phar depends doctrine/lexer
|
||||||
|
doctrine/annotations v1.2.7 requires doctrine/lexer (1.*)
|
||||||
nrk/monolog-fluent requires monolog/monolog (~1.8)
|
doctrine/common v2.6.1 requires doctrine/lexer (1.*)
|
||||||
poc/poc requires monolog/monolog (^1.6)
|
|
||||||
propel/propel requires monolog/monolog (1.*)
|
|
||||||
symfony/monolog-bridge requires monolog/monolog (>=1.2)
|
|
||||||
symfony/symfony requires monolog/monolog (~1)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want, for example, find any installed package that is **not** allowing
|
You can optionally specify a version constraint after the package to limit the
|
||||||
Symfony version 3 or one of its components, you can run the following command:
|
search.
|
||||||
|
|
||||||
|
Add the `--tree` or `-t` flag to show a recursive tree of why the package is
|
||||||
|
depended upon, for example:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
php composer.phar depends symfony/symfony --with-replaces -im ^3.0
|
php composer.phar depends psr/log -t
|
||||||
|
psr/log 1.0.0 Common interface for logging libraries
|
||||||
|
|- aboutyou/app-sdk 2.6.11 (requires psr/log 1.0.*)
|
||||||
|
| `- __root__ (requires aboutyou/app-sdk ^2.6)
|
||||||
|
|- monolog/monolog 1.17.2 (requires psr/log ~1.0)
|
||||||
|
| `- laravel/framework v5.2.16 (requires monolog/monolog ~1.11)
|
||||||
|
| `- __root__ (requires laravel/framework ^5.2)
|
||||||
|
`- symfony/symfony v3.0.2 (requires psr/log ~1.0)
|
||||||
|
`- __root__ (requires symfony/symfony ^3.0)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
* **--link-type:** The link types to match on, can be specified multiple
|
* **--recursive (-r):** Recursively resolves up to the root package.
|
||||||
times.
|
* **--tree (-t):** Prints the results as a nested tree, implies -r.
|
||||||
* **--match-constraint (-m):** Filters the dependencies shown using this constraint.
|
|
||||||
* **--invert-match-constraint (-i):** Turns --match-constraint around into a blacklist
|
## prohibits
|
||||||
instead of a whitelist.
|
|
||||||
* **--with-replaces:** Search for replaced packages as well.
|
The `prohibits` command tells you which packages are blocking a given package
|
||||||
|
from being installed. Specify a version constraint to verify whether upgrades
|
||||||
|
can be performed in your project, and if not why not. See the following
|
||||||
|
example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
php composer.phar prohibits symfony/symfony 3.1
|
||||||
|
laravel/framework v5.2.16 requires symfony/var-dumper (2.8.*|3.0.*)
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that you can also specify platform requirements, for example to check
|
||||||
|
whether you can upgrade your server to PHP 8.0:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
php composer.phar prohibits php:8
|
||||||
|
doctrine/cache v1.6.0 requires php (~5.5|~7.0)
|
||||||
|
doctrine/common v2.6.1 requires php (~5.5|~7.0)
|
||||||
|
doctrine/instantiator 1.0.5 requires php (>=5.3,<8.0-DEV)
|
||||||
|
```
|
||||||
|
|
||||||
|
As with `depends` you can request a recursive lookup, which will list all
|
||||||
|
packages depending on the packages that cause the conflict.
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
* **--recursive (-r):** Recursively resolves up to the root package.
|
||||||
|
* **--tree (-t):** Prints the results as a nested tree, implies -r.
|
||||||
|
|
||||||
## validate
|
## validate
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
/**
|
/**
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class AboutCommand extends Command
|
class AboutCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,7 +30,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
*
|
*
|
||||||
* @author Nils Adermann <naderman@naderman.de>
|
* @author Nils Adermann <naderman@naderman.de>
|
||||||
*/
|
*/
|
||||||
class ArchiveCommand extends Command
|
class ArchiveCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,7 +18,7 @@ use Composer\IO\IOInterface;
|
||||||
use Composer\IO\NullIO;
|
use Composer\IO\NullIO;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Command\Command as BaseCommand;
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for Composer commands
|
* Base class for Composer commands
|
||||||
|
@ -26,7 +26,7 @@ use Symfony\Component\Console\Command\Command as BaseCommand;
|
||||||
* @author Ryan Weaver <ryan@knplabs.com>
|
* @author Ryan Weaver <ryan@knplabs.com>
|
||||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||||
*/
|
*/
|
||||||
abstract class Command extends BaseCommand
|
abstract class BaseCommand extends Command
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var Composer
|
* @var Composer
|
|
@ -0,0 +1,190 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Command;
|
||||||
|
|
||||||
|
use Composer\DependencyResolver\Pool;
|
||||||
|
use Composer\Package\Link;
|
||||||
|
use Composer\Package\PackageInterface;
|
||||||
|
use Composer\Repository\ArrayRepository;
|
||||||
|
use Composer\Repository\CompositeRepository;
|
||||||
|
use Composer\Repository\PlatformRepository;
|
||||||
|
use Composer\Plugin\CommandEvent;
|
||||||
|
use Composer\Plugin\PluginEvents;
|
||||||
|
use Composer\Package\Version\VersionParser;
|
||||||
|
use Symfony\Component\Console\Helper\Table;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base implementation for commands mapping dependency relationships.
|
||||||
|
*
|
||||||
|
* @author Niels Keurentjes <niels.keurentjes@omines.com>
|
||||||
|
*/
|
||||||
|
class BaseDependencyCommand extends BaseCommand
|
||||||
|
{
|
||||||
|
const ARGUMENT_PACKAGE = 'package';
|
||||||
|
const ARGUMENT_CONSTRAINT = 'constraint';
|
||||||
|
const OPTION_RECURSIVE = 'recursive';
|
||||||
|
const OPTION_TREE = 'tree';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set common options and arguments.
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this->setDefinition(array(
|
||||||
|
new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
|
||||||
|
new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::OPTIONAL, 'Optional version constraint', '*'),
|
||||||
|
new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
|
||||||
|
new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the command.
|
||||||
|
*
|
||||||
|
* @param InputInterface $input
|
||||||
|
* @param OutputInterface $output
|
||||||
|
* @param bool $inverted Whether to invert matching process (why-not vs why behaviour)
|
||||||
|
* @return int|null Exit code of the operation.
|
||||||
|
*/
|
||||||
|
protected function doExecute(InputInterface $input, OutputInterface $output, $inverted = false)
|
||||||
|
{
|
||||||
|
// Emit command event on startup
|
||||||
|
$composer = $this->getComposer();
|
||||||
|
$commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output);
|
||||||
|
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
|
||||||
|
|
||||||
|
// Prepare repositories and set up a pool
|
||||||
|
$platformOverrides = $composer->getConfig()->get('platform') ?: array();
|
||||||
|
$repository = new CompositeRepository(array(
|
||||||
|
new ArrayRepository(array($composer->getPackage())),
|
||||||
|
$composer->getRepositoryManager()->getLocalRepository(),
|
||||||
|
new PlatformRepository(array(), $platformOverrides),
|
||||||
|
));
|
||||||
|
$pool = new Pool();
|
||||||
|
$pool->addRepository($repository);
|
||||||
|
|
||||||
|
// Parse package name and constraint
|
||||||
|
list($needle, $textConstraint) = array_pad(explode(':', $input->getArgument(self::ARGUMENT_PACKAGE)),
|
||||||
|
2, $input->getArgument(self::ARGUMENT_CONSTRAINT));
|
||||||
|
|
||||||
|
// Find packages that are or provide the requested package first
|
||||||
|
$packages = $pool->whatProvides($needle);
|
||||||
|
if (empty($packages)) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include replaced packages for inverted lookups as they are then the actual starting point to consider
|
||||||
|
$needles = array($needle);
|
||||||
|
if ($inverted) {
|
||||||
|
foreach ($packages as $package) {
|
||||||
|
$needles = array_merge($needles, array_map(function (Link $link) {
|
||||||
|
return $link->getTarget();
|
||||||
|
}, $package->getReplaces()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse constraint if one was supplied
|
||||||
|
if ('*' !== $textConstraint) {
|
||||||
|
$versionParser = new VersionParser();
|
||||||
|
$constraint = $versionParser->parseConstraints($textConstraint);
|
||||||
|
} else {
|
||||||
|
$constraint = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse rendering options
|
||||||
|
$renderTree = $input->getOption(self::OPTION_TREE);
|
||||||
|
$recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE);
|
||||||
|
|
||||||
|
// Resolve dependencies
|
||||||
|
$results = $repository->getDependents($needles, $constraint, $inverted, $recursive);
|
||||||
|
if (empty($results)) {
|
||||||
|
$extra = (null !== $constraint) ? sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : '';
|
||||||
|
$this->getIO()->writeError(sprintf('<info>There is no installed package depending on "%s"%s</info>',
|
||||||
|
$needle, $extra));
|
||||||
|
} elseif ($renderTree) {
|
||||||
|
$root = $packages[0];
|
||||||
|
$this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root->getDescription()));
|
||||||
|
$this->printTree($output, $results);
|
||||||
|
} else {
|
||||||
|
$this->printTable($output, $results);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assembles and prints a bottom-up table of the dependencies.
|
||||||
|
*
|
||||||
|
* @param OutputInterface $output
|
||||||
|
* @param array $results
|
||||||
|
*/
|
||||||
|
protected function printTable(OutputInterface $output, $results)
|
||||||
|
{
|
||||||
|
$table = array();
|
||||||
|
$doubles = array();
|
||||||
|
do {
|
||||||
|
$queue = array();
|
||||||
|
$rows = array();
|
||||||
|
foreach($results as $result) {
|
||||||
|
/**
|
||||||
|
* @var PackageInterface $package
|
||||||
|
* @var Link $link
|
||||||
|
*/
|
||||||
|
list($package, $link, $children) = $result;
|
||||||
|
$unique = (string)$link;
|
||||||
|
if (isset($doubles[$unique])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$doubles[$unique] = true;
|
||||||
|
$version = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '-' : $package->getPrettyVersion();
|
||||||
|
$rows[] = array($package->getPrettyName(), $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint()));
|
||||||
|
$queue = array_merge($queue, $children);
|
||||||
|
}
|
||||||
|
$results = $queue;
|
||||||
|
$table = array_merge($rows, $table);
|
||||||
|
} while(!empty($results));
|
||||||
|
|
||||||
|
// Render table
|
||||||
|
$renderer = new Table($output);
|
||||||
|
$renderer->setStyle('compact')->setRows($table)->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively prints a tree of the selected results.
|
||||||
|
*
|
||||||
|
* @param OutputInterface $output
|
||||||
|
* @param array $results
|
||||||
|
* @param string $prefix
|
||||||
|
*/
|
||||||
|
protected function printTree(OutputInterface $output, $results, $prefix = '')
|
||||||
|
{
|
||||||
|
$count = count($results);
|
||||||
|
$idx = 0;
|
||||||
|
foreach($results as $key => $result) {
|
||||||
|
/**
|
||||||
|
* @var PackageInterface $package
|
||||||
|
* @var Link $link
|
||||||
|
*/
|
||||||
|
list($package, $link, $children) = $result;
|
||||||
|
$isLast = (++$idx == $count);
|
||||||
|
$versionText = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '' : $package->getPrettyVersion();
|
||||||
|
$packageText = rtrim(sprintf('%s %s', $package->getPrettyName(), $versionText));
|
||||||
|
$linkText = implode(' ', array($link->getDescription(), $link->getTarget(), $link->getPrettyConstraint()));
|
||||||
|
$output->write(sprintf("%s%s %s (%s)\n", $prefix, $isLast ? '`-' : '|-', $packageText, $linkText));
|
||||||
|
$this->printTree($output, $children, $prefix . ($isLast ? ' ' : '| '));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
/**
|
/**
|
||||||
* @author David Neilsen <petah.p@gmail.com>
|
* @author David Neilsen <petah.p@gmail.com>
|
||||||
*/
|
*/
|
||||||
class ClearCacheCommand extends Command
|
class ClearCacheCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,7 +27,7 @@ use Composer\Json\JsonFile;
|
||||||
* @author Joshua Estes <Joshua.Estes@iostudio.com>
|
* @author Joshua Estes <Joshua.Estes@iostudio.com>
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class ConfigCommand extends Command
|
class ConfigCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var Config
|
* @var Config
|
||||||
|
|
|
@ -46,7 +46,7 @@ use Composer\Package\Version\VersionParser;
|
||||||
* @author Tobias Munk <schmunk@usrbin.de>
|
* @author Tobias Munk <schmunk@usrbin.de>
|
||||||
* @author Nils Adermann <naderman@naderman.de>
|
* @author Nils Adermann <naderman@naderman.de>
|
||||||
*/
|
*/
|
||||||
class CreateProjectCommand extends Command
|
class CreateProjectCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,43 +12,25 @@
|
||||||
|
|
||||||
namespace Composer\Command;
|
namespace Composer\Command;
|
||||||
|
|
||||||
use Composer\DependencyResolver\Pool;
|
|
||||||
use Composer\Package\Link;
|
|
||||||
use Composer\Package\PackageInterface;
|
|
||||||
use Composer\Repository\ArrayRepository;
|
|
||||||
use Composer\Repository\CompositeRepository;
|
|
||||||
use Composer\Repository\PlatformRepository;
|
|
||||||
use Composer\Plugin\CommandEvent;
|
|
||||||
use Composer\Plugin\PluginEvents;
|
|
||||||
use Composer\Package\Version\VersionParser;
|
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Justin Rainbow <justin.rainbow@gmail.com>
|
* @author Niels Keurentjes <niels.keurentjes@omines.com>
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
|
||||||
*/
|
*/
|
||||||
class DependsCommand extends Command
|
class DependsCommand extends BaseDependencyCommand
|
||||||
{
|
{
|
||||||
protected $linkTypes = array(
|
/**
|
||||||
'require' => array('requires', 'requires'),
|
* Configure command metadata.
|
||||||
'require-dev' => array('devRequires', 'requires (dev)'),
|
*/
|
||||||
);
|
|
||||||
|
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
|
parent::configure();
|
||||||
|
|
||||||
$this
|
$this
|
||||||
->setName('depends')
|
->setName('depends')
|
||||||
->setDescription('Shows which packages depend on the given package')
|
->setAliases(array('why'))
|
||||||
->setDefinition(array(
|
->setDescription('Shows which packages cause the given package to be installed')
|
||||||
new InputArgument('package', InputArgument::REQUIRED, 'Package to inspect'),
|
|
||||||
new InputOption('link-type', '', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Link types to show (require, require-dev)', array_keys($this->linkTypes)),
|
|
||||||
new InputOption('match-constraint', 'm', InputOption::VALUE_REQUIRED, 'Filters the dependencies shown using this constraint', '*'),
|
|
||||||
new InputOption('invert-match-constraint', 'i', InputOption::VALUE_NONE, 'Turns --match-constraint around into a blacklist instead of whitelist'),
|
|
||||||
new InputOption('with-replaces', '', InputOption::VALUE_NONE, 'Search for replaced packages as well'),
|
|
||||||
))
|
|
||||||
->setHelp(<<<EOT
|
->setHelp(<<<EOT
|
||||||
Displays detailed information about where a package is referenced.
|
Displays detailed information about where a package is referenced.
|
||||||
|
|
||||||
|
@ -59,82 +41,15 @@ EOT
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the function.
|
||||||
|
*
|
||||||
|
* @param InputInterface $input
|
||||||
|
* @param OutputInterface $output
|
||||||
|
* @return int|null
|
||||||
|
*/
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
{
|
{
|
||||||
$composer = $this->getComposer();
|
return parent::doExecute($input, $output, false);
|
||||||
|
|
||||||
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'depends', $input, $output);
|
|
||||||
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
|
|
||||||
|
|
||||||
$platformOverrides = $composer->getConfig()->get('platform') ?: array();
|
|
||||||
$repo = new CompositeRepository(array(
|
|
||||||
new ArrayRepository(array($composer->getPackage())),
|
|
||||||
$composer->getRepositoryManager()->getLocalRepository(),
|
|
||||||
new PlatformRepository(array(), $platformOverrides),
|
|
||||||
));
|
|
||||||
$needle = $input->getArgument('package');
|
|
||||||
|
|
||||||
$pool = new Pool();
|
|
||||||
$pool->addRepository($repo);
|
|
||||||
|
|
||||||
$packages = $pool->whatProvides($needle);
|
|
||||||
if (empty($packages)) {
|
|
||||||
throw new \InvalidArgumentException('Could not find package "'.$needle.'" in your project.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$linkTypes = $this->linkTypes;
|
|
||||||
|
|
||||||
$types = array_map(function ($type) use ($linkTypes) {
|
|
||||||
$type = rtrim($type, 's');
|
|
||||||
if (!isset($linkTypes[$type])) {
|
|
||||||
throw new \InvalidArgumentException('Unexpected link type: '.$type.', valid types: '.implode(', ', array_keys($linkTypes)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $type;
|
|
||||||
}, $input->getOption('link-type'));
|
|
||||||
|
|
||||||
$versionParser = new VersionParser();
|
|
||||||
$constraint = $versionParser->parseConstraints($input->getOption('match-constraint'));
|
|
||||||
$matchInvert = $input->getOption('invert-match-constraint');
|
|
||||||
|
|
||||||
$needles = array($needle);
|
|
||||||
if (true === $input->getOption('with-replaces')) {
|
|
||||||
foreach ($packages as $package) {
|
|
||||||
$needles = array_merge($needles, array_map(function (Link $link) {
|
|
||||||
return $link->getTarget();
|
|
||||||
}, $package->getReplaces()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$messages = array();
|
|
||||||
$outputPackages = array();
|
|
||||||
$io = $this->getIO();
|
|
||||||
/** @var PackageInterface $package */
|
|
||||||
foreach ($repo->getPackages() as $package) {
|
|
||||||
foreach ($types as $type) {
|
|
||||||
/** @var Link $link */
|
|
||||||
foreach ($package->{'get'.$linkTypes[$type][0]}() as $link) {
|
|
||||||
foreach ($needles as $needle) {
|
|
||||||
if ($link->getTarget() === $needle && ($link->getConstraint()->matches($constraint) ? !$matchInvert : $matchInvert)) {
|
|
||||||
if (!isset($outputPackages[$package->getName()])) {
|
|
||||||
$messages[] = '<info>'.$package->getPrettyName() . '</info> ' . $linkTypes[$type][1] . ' ' . $needle .' (<info>' . $link->getPrettyConstraint() . '</info>)';
|
|
||||||
$outputPackages[$package->getName()] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($messages) {
|
|
||||||
sort($messages);
|
|
||||||
$io->write($messages);
|
|
||||||
} else {
|
|
||||||
$matchText = '';
|
|
||||||
if ($input->getOption('match-constraint') !== '*') {
|
|
||||||
$matchText = ' in versions '.($matchInvert ? 'not ' : '').'matching ' . $input->getOption('match-constraint');
|
|
||||||
}
|
|
||||||
$io->writeError('<info>There is no installed package depending on "'.$needle.'"'.$matchText.'.</info>');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
/**
|
/**
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class DiagnoseCommand extends Command
|
class DiagnoseCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
/** @var RemoteFileSystem */
|
/** @var RemoteFileSystem */
|
||||||
protected $rfs;
|
protected $rfs;
|
||||||
|
|
|
@ -21,7 +21,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
/**
|
/**
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class DumpAutoloadCommand extends Command
|
class DumpAutoloadCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,7 +21,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
/**
|
/**
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class GlobalCommand extends Command
|
class GlobalCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,7 +26,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
/**
|
/**
|
||||||
* @author Robert Schönthal <seroscho@googlemail.com>
|
* @author Robert Schönthal <seroscho@googlemail.com>
|
||||||
*/
|
*/
|
||||||
class HomeCommand extends Command
|
class HomeCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
|
|
|
@ -31,7 +31,7 @@ use Symfony\Component\Process\ExecutableFinder;
|
||||||
* @author Justin Rainbow <justin.rainbow@gmail.com>
|
* @author Justin Rainbow <justin.rainbow@gmail.com>
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class InitCommand extends Command
|
class InitCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
/** @var CompositeRepository */
|
/** @var CompositeRepository */
|
||||||
protected $repos;
|
protected $repos;
|
||||||
|
|
|
@ -26,7 +26,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
* @author Konstantin Kudryashov <ever.zet@gmail.com>
|
||||||
* @author Nils Adermann <naderman@naderman.de>
|
* @author Nils Adermann <naderman@naderman.de>
|
||||||
*/
|
*/
|
||||||
class InstallCommand extends Command
|
class InstallCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
/**
|
/**
|
||||||
* @author Benoît Merlet <benoit.merlet@gmail.com>
|
* @author Benoît Merlet <benoit.merlet@gmail.com>
|
||||||
*/
|
*/
|
||||||
class LicensesCommand extends Command
|
class LicensesCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* 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\Output\OutputInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Niels Keurentjes <niels.keurentjes@omines.com>
|
||||||
|
*/
|
||||||
|
class ProhibitsCommand extends BaseDependencyCommand
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Configure command metadata.
|
||||||
|
*/
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
parent::configure();
|
||||||
|
|
||||||
|
$this
|
||||||
|
->setName('prohibits')
|
||||||
|
->setAliases(array('why-not'))
|
||||||
|
->setDescription('Shows which packages prevent the given package from being installed')
|
||||||
|
->setHelp(<<<EOT
|
||||||
|
Displays detailed information about why a package cannot be installed.
|
||||||
|
|
||||||
|
<info>php composer.phar prohibits composer/composer</info>
|
||||||
|
|
||||||
|
EOT
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the function.
|
||||||
|
*
|
||||||
|
* @param InputInterface $input
|
||||||
|
* @param OutputInterface $output
|
||||||
|
* @return int|null
|
||||||
|
*/
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
return parent::doExecute($input, $output, true);
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
* @author Pierre du Plessis <pdples@gmail.com>
|
* @author Pierre du Plessis <pdples@gmail.com>
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class RemoveCommand extends Command
|
class RemoveCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,7 +23,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
/**
|
/**
|
||||||
* @author Fabien Potencier <fabien.potencier@gmail.com>
|
* @author Fabien Potencier <fabien.potencier@gmail.com>
|
||||||
*/
|
*/
|
||||||
class RunScriptCommand extends Command
|
class RunScriptCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var array Array with command events
|
* @var array Array with command events
|
||||||
|
|
|
@ -20,7 +20,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
/**
|
/**
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class ScriptAliasCommand extends Command
|
class ScriptAliasCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
private $script;
|
private $script;
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ use Composer\Plugin\PluginEvents;
|
||||||
/**
|
/**
|
||||||
* @author Robert Schönthal <seroscho@googlemail.com>
|
* @author Robert Schönthal <seroscho@googlemail.com>
|
||||||
*/
|
*/
|
||||||
class SearchCommand extends Command
|
class SearchCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected $matches;
|
protected $matches;
|
||||||
protected $lowMatches = array();
|
protected $lowMatches = array();
|
||||||
|
|
|
@ -30,7 +30,7 @@ use Symfony\Component\Finder\Finder;
|
||||||
* @author Kevin Ran <kran@adobe.com>
|
* @author Kevin Ran <kran@adobe.com>
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class SelfUpdateCommand extends Command
|
class SelfUpdateCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
const HOMEPAGE = 'getcomposer.org';
|
const HOMEPAGE = 'getcomposer.org';
|
||||||
const OLD_INSTALL_EXT = '-old.phar';
|
const OLD_INSTALL_EXT = '-old.phar';
|
||||||
|
|
|
@ -38,7 +38,7 @@ use Composer\Spdx\SpdxLicenses;
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
* @author Jérémy Romey <jeremyFreeAgent>
|
* @author Jérémy Romey <jeremyFreeAgent>
|
||||||
*/
|
*/
|
||||||
class ShowCommand extends Command
|
class ShowCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected $versionParser;
|
protected $versionParser;
|
||||||
protected $colors;
|
protected $colors;
|
||||||
|
|
|
@ -24,7 +24,7 @@ use Composer\Script\ScriptEvents;
|
||||||
* @author Tiago Ribeiro <tiago.ribeiro@seegno.com>
|
* @author Tiago Ribeiro <tiago.ribeiro@seegno.com>
|
||||||
* @author Rui Marinho <rui.marinho@seegno.com>
|
* @author Rui Marinho <rui.marinho@seegno.com>
|
||||||
*/
|
*/
|
||||||
class StatusCommand extends Command
|
class StatusCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,7 +17,7 @@ use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
class SuggestsCommand extends Command
|
class SuggestsCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,7 +28,7 @@ use Symfony\Component\Console\Question\Question;
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
* @author Nils Adermann <naderman@naderman.de>
|
* @author Nils Adermann <naderman@naderman.de>
|
||||||
*/
|
*/
|
||||||
class UpdateCommand extends Command
|
class UpdateCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,7 +29,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
* @author Robert Schönthal <seroscho@googlemail.com>
|
* @author Robert Schönthal <seroscho@googlemail.com>
|
||||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
*/
|
*/
|
||||||
class ValidateCommand extends Command
|
class ValidateCommand extends BaseCommand
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* configure
|
* configure
|
||||||
|
|
|
@ -279,33 +279,35 @@ class Application extends BaseApplication
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes all the composer commands
|
* Initializes all the composer commands.
|
||||||
*/
|
*/
|
||||||
protected function getDefaultCommands()
|
protected function getDefaultCommands()
|
||||||
{
|
{
|
||||||
$commands = parent::getDefaultCommands();
|
$commands = array_merge(parent::getDefaultCommands(), array(
|
||||||
$commands[] = new Command\AboutCommand();
|
new Command\AboutCommand(),
|
||||||
$commands[] = new Command\ConfigCommand();
|
new Command\ConfigCommand(),
|
||||||
$commands[] = new Command\DependsCommand();
|
new Command\DependsCommand(),
|
||||||
$commands[] = new Command\InitCommand();
|
new Command\ProhibitsCommand(),
|
||||||
$commands[] = new Command\InstallCommand();
|
new Command\InitCommand(),
|
||||||
$commands[] = new Command\CreateProjectCommand();
|
new Command\InstallCommand(),
|
||||||
$commands[] = new Command\UpdateCommand();
|
new Command\CreateProjectCommand(),
|
||||||
$commands[] = new Command\SearchCommand();
|
new Command\UpdateCommand(),
|
||||||
$commands[] = new Command\ValidateCommand();
|
new Command\SearchCommand(),
|
||||||
$commands[] = new Command\ShowCommand();
|
new Command\ValidateCommand(),
|
||||||
$commands[] = new Command\SuggestsCommand();
|
new Command\ShowCommand(),
|
||||||
$commands[] = new Command\RequireCommand();
|
new Command\SuggestsCommand(),
|
||||||
$commands[] = new Command\DumpAutoloadCommand();
|
new Command\RequireCommand(),
|
||||||
$commands[] = new Command\StatusCommand();
|
new Command\DumpAutoloadCommand(),
|
||||||
$commands[] = new Command\ArchiveCommand();
|
new Command\StatusCommand(),
|
||||||
$commands[] = new Command\DiagnoseCommand();
|
new Command\ArchiveCommand(),
|
||||||
$commands[] = new Command\RunScriptCommand();
|
new Command\DiagnoseCommand(),
|
||||||
$commands[] = new Command\LicensesCommand();
|
new Command\RunScriptCommand(),
|
||||||
$commands[] = new Command\GlobalCommand();
|
new Command\LicensesCommand(),
|
||||||
$commands[] = new Command\ClearCacheCommand();
|
new Command\GlobalCommand(),
|
||||||
$commands[] = new Command\RemoveCommand();
|
new Command\ClearCacheCommand(),
|
||||||
$commands[] = new Command\HomeCommand();
|
new Command\RemoveCommand(),
|
||||||
|
new Command\HomeCommand(),
|
||||||
|
));
|
||||||
|
|
||||||
if ('phar:' === substr(__FILE__, 0, 5)) {
|
if ('phar:' === substr(__FILE__, 0, 5)) {
|
||||||
$commands[] = new Command\SelfUpdateCommand();
|
$commands[] = new Command\SelfUpdateCommand();
|
||||||
|
|
|
@ -64,6 +64,14 @@ class Link
|
||||||
$this->prettyConstraint = $prettyConstraint;
|
$this->prettyConstraint = $prettyConstraint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDescription()
|
||||||
|
{
|
||||||
|
return $this->description;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -24,7 +24,7 @@ use Composer\Semver\Constraint\Constraint;
|
||||||
*
|
*
|
||||||
* @author Nils Adermann <naderman@naderman.de>
|
* @author Nils Adermann <naderman@naderman.de>
|
||||||
*/
|
*/
|
||||||
class ArrayRepository implements RepositoryInterface
|
class ArrayRepository extends BaseRepository
|
||||||
{
|
{
|
||||||
/** @var PackageInterface[] */
|
/** @var PackageInterface[] */
|
||||||
protected $packages;
|
protected $packages;
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Repository;
|
||||||
|
|
||||||
|
use Composer\Package\RootPackageInterface;
|
||||||
|
use Composer\Semver\Constraint\ConstraintInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common ancestor class for generic repository functionality.
|
||||||
|
*
|
||||||
|
* @author Niels Keurentjes <niels.keurentjes@omines.com>
|
||||||
|
*/
|
||||||
|
abstract class BaseRepository implements RepositoryInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns a list of links causing the requested needle packages to be installed, as an associative array with the
|
||||||
|
* dependent's name as key, and an array containing in order the PackageInterface and Link describing the relationship
|
||||||
|
* as values. If recursive lookup was requested a third value is returned containing an identically formed array up
|
||||||
|
* to the root package.
|
||||||
|
*
|
||||||
|
* @param string|string[] $needle The package name(s) to inspect.
|
||||||
|
* @param ConstraintInterface|null $constraint Optional constraint to filter by.
|
||||||
|
* @param bool $invert Whether to invert matches to discover reasons for the package *NOT* to be installed.
|
||||||
|
* @param bool $recurse Whether to recursively expand the requirement tree up to the root package.
|
||||||
|
* @return array An associative array of arrays as described above.
|
||||||
|
*/
|
||||||
|
public function getDependents($needle, $constraint = null, $invert = false, $recurse = true)
|
||||||
|
{
|
||||||
|
$needles = is_array($needle) ? $needle : array($needle);
|
||||||
|
$results = array();
|
||||||
|
|
||||||
|
// Loop over all currently installed packages.
|
||||||
|
foreach ($this->getPackages() as $package) {
|
||||||
|
$links = $package->getRequires();
|
||||||
|
|
||||||
|
// Replacements are considered valid reasons for a package to be installed during forward resolution
|
||||||
|
if (!$invert) {
|
||||||
|
$links += $package->getReplaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Require-dev is only relevant for the root package
|
||||||
|
if ($package instanceof RootPackageInterface) {
|
||||||
|
$links += $package->getDevRequires();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cross-reference all discovered links to the needles
|
||||||
|
foreach ($links as $link) {
|
||||||
|
foreach ($needles as $needle) {
|
||||||
|
if ($link->getTarget() === $needle) {
|
||||||
|
if (is_null($constraint) || (($link->getConstraint()->matches($constraint) === !$invert))) {
|
||||||
|
$results[$link->getSource()] = array($package, $link, $recurse ? $this->getDependents($link->getSource(), null, false, true) : array());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ksort($results);
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ use Composer\Package\PackageInterface;
|
||||||
*
|
*
|
||||||
* @author Beau Simensen <beau@dflydev.com>
|
* @author Beau Simensen <beau@dflydev.com>
|
||||||
*/
|
*/
|
||||||
class CompositeRepository implements RepositoryInterface
|
class CompositeRepository extends BaseRepository
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* List of repositories
|
* List of repositories
|
||||||
|
|
Loading…
Reference in New Issue