1
0
Fork 0

Added a tree view of required packages

pull/2600/head
Jérémy Romey 2014-01-15 20:58:29 +01:00
parent fbab2bfa17
commit 36271a7dd1
2 changed files with 154 additions and 22 deletions

View File

@ -299,6 +299,7 @@ php composer.phar show monolog/monolog 1.0.2
* **--installed (-i):** List the packages that are installed. * **--installed (-i):** List the packages that are installed.
* **--platform (-p):** List only platform packages (php & extensions). * **--platform (-p):** List only platform packages (php & extensions).
* **--self (-s):** List the root package info. * **--self (-s):** List the root package info.
* **--tree (-t):** List the dependencies as a tree.
## browse / home ## browse / home

View File

@ -19,6 +19,7 @@ use Composer\Package\CompletePackageInterface;
use Composer\Semver\VersionParser; use Composer\Semver\VersionParser;
use Composer\Plugin\CommandEvent; use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents; use Composer\Plugin\PluginEvents;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
@ -33,10 +34,12 @@ use Composer\Spdx\SpdxLicenses;
/** /**
* @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>
* @author Jérémy Romey <jeremyFreeAgent>
*/ */
class ShowCommand extends Command class ShowCommand extends Command
{ {
protected $versionParser; protected $versionParser;
protected $colors;
protected function configure() protected function configure()
{ {
@ -53,6 +56,7 @@ class ShowCommand extends Command
new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'), new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'),
new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'), new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'),
new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'), new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'),
new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'),
)) ))
->setHelp(<<<EOT ->setHelp(<<<EOT
The show command displays detailed information about a package, or The show command displays detailed information about a package, or
@ -66,6 +70,7 @@ EOT
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$this->versionParser = new VersionParser; $this->versionParser = new VersionParser;
$this->initStyles($output);
// init repos // init repos
$platformRepo = new PlatformRepository; $platformRepo = new PlatformRepository;
@ -99,6 +104,10 @@ EOT
$repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos)); $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
} }
if ($input->getOption('tree')) {
$repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
}
if ($composer) { if ($composer) {
$commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output); $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output);
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
@ -117,7 +126,10 @@ EOT
$versions = array($package->getPrettyVersion() => $package->getVersion()); $versions = array($package->getPrettyVersion() => $package->getVersion());
} }
$this->printMeta($package, $versions, $installedRepo); if ($input->getOption('tree')) {
$this->displayPackageTree($package, $installedRepo, $repos, $output);
} else {
$this->printMeta($package, $versions, $installedRepo, $repos);
$this->printLinks($package, 'requires'); $this->printLinks($package, 'requires');
$this->printLinks($package, 'devRequires', 'requires (dev)'); $this->printLinks($package, 'devRequires', 'requires (dev)');
if ($package->getSuggests()) { if ($package->getSuggests()) {
@ -129,6 +141,10 @@ EOT
$this->printLinks($package, 'provides'); $this->printLinks($package, 'provides');
$this->printLinks($package, 'conflicts'); $this->printLinks($package, 'conflicts');
$this->printLinks($package, 'replaces'); $this->printLinks($package, 'replaces');
}
$this->printLinks($package, 'provides');
$this->printLinks($package, 'conflicts');
$this->printLinks($package, 'replaces');
return; return;
} }
@ -136,6 +152,7 @@ EOT
// list packages // list packages
$packages = array(); $packages = array();
$allRepos = $repos;
if ($repos instanceof CompositeRepository) { if ($repos instanceof CompositeRepository) {
$repos = $repos->getRepositories(); $repos = $repos->getRepositories();
} elseif (!is_array($repos)) { } elseif (!is_array($repos)) {
@ -170,7 +187,7 @@ EOT
} }
$tree = !$input->getOption('platform') && !$input->getOption('installed') && !$input->getOption('available'); $tree = !$input->getOption('platform') && !$input->getOption('installed') && !$input->getOption('available');
$indent = $tree ? ' ' : ''; $indent = $tree && $input->getOption('installed') ? ' ' : '';
foreach (array('<info>platform</info>:' => true, '<comment>available</comment>:' => false, '<info>installed</info>:' => true) as $type => $showVersion) { foreach (array('<info>platform</info>:' => true, '<comment>available</comment>:' => false, '<info>installed</info>:' => true) as $type => $showVersion) {
if (isset($packages[$type])) { if (isset($packages[$type])) {
if ($tree) { if ($tree) {
@ -206,6 +223,9 @@ EOT
$writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion && ($nameLength + $versionLength + 3 <= $width); $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion && ($nameLength + $versionLength + 3 <= $width);
$writeDescription = !$input->getOption('name-only') && !$input->getOption('path') && ($nameLength + ($showVersion ? $versionLength : 0) + 24 <= $width); $writeDescription = !$input->getOption('name-only') && !$input->getOption('path') && ($nameLength + ($showVersion ? $versionLength : 0) + 24 <= $width);
foreach ($packages[$type] as $package) { foreach ($packages[$type] as $package) {
if ($input->getOption('tree') && $input->getOption('installed')) {
$this->displayPackageTree($package, $installedRepo, $allRepos, $output);
} else {
if (is_object($package)) { if (is_object($package)) {
$output->write($indent . str_pad($package->getPrettyName(), $nameLength, ' '), false); $output->write($indent . str_pad($package->getPrettyName(), $nameLength, ' '), false);
@ -221,13 +241,14 @@ EOT
} }
$output->write(' ' . $description); $output->write(' ' . $description);
} }
} else {
$output->write($indent . $package);
}
if ($writePath) { if ($writePath) {
$path = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n"); $path = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
$output->write(' ' . $path); $output->write(' ' . $path);
} }
} else {
$output->write($indent . $package);
} }
$io->write(''); $io->write('');
} }
@ -415,4 +436,114 @@ EOT
$io->write('<info>license</info> : ' . $out); $io->write('<info>license</info> : ' . $out);
} }
} }
/**
* Init styles for tree
*
* @param OutputInterface $output
*/
protected function initStyles(OutputInterface $output)
{
$this->colors = array(
'green',
'yellow',
'blue',
'magenta',
'cyan',
);
foreach ($this->colors as $color) {
$style = new OutputFormatterStyle($color);
$output->getFormatter()->setStyle($color, $style);
}
}
/**
* Display the tree
*
* @param PackageInterface|string $package
* @param RepositoryInterface $installedRepo
* @param RepositoryInterface $distantRepos
* @param OutputInterface $output
*/
protected function displayPackageTree($package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos, OutputInterface $output)
{
$packagesInTree = array();
$packagesInTree[] = $package;
if (is_object($package)) {
$output->write(sprintf('<info>%s</info>', $package->getPrettyName()));
$output->write(' ' . $package->getPrettyVersion());
$output->write(' ' . strtok($package->getDescription(), "\r\n"));
} else {
$output->write(sprintf('<info>%s</info>', $package));
}
$output->writeln('');
if (is_object($package)) {
$requires = $package->getRequires();
$treeBar = '├';
$j = 0;
$total = count($requires);
foreach ($requires as $requireName => $require) {
$j++;
if ($j == 0) {
$output->writeln($treeBar);
}
if ($j == $total) {
$treeBar = '└';
}
$level = 1;
$color = $this->colors[$level];
$info = sprintf('%s──<%s>%s</%s> %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint());
$output->writeln($info);
$treeBar = str_replace('└', ' ', $treeBar);
$packagesInTree[] = $requireName;
$this->displayTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree, $output, $treeBar, $level + 1);
}
}
}
/**
* Display a package tree
*
* @param string $name
* @param PackageInterface|string $package
* @param RepositoryInterface $installedRepo
* @param RepositoryInterface $distantRepos
* @param array $packagesInTree
* @param OutputInterface $output
* @param string $previousTreeBar
* @param integer $level
*/
protected function displayTree($name, $package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos, array $packagesInTree, OutputInterface $output, $previousTreeBar = '├', $level = 1)
{
$previousTreeBar = str_replace('├', '│', $previousTreeBar);
list($package, $versions) = $this->getPackage($installedRepo, $distantRepos, $name, $package->getPrettyConstraint() == 'self.version' ? $package->getConstraint() : $package->getPrettyConstraint());
if (is_object($package)) {
$requires = $package->getRequires();
$treeBar = $previousTreeBar . ' ├';
$i = 0;
$total = count($requires);
foreach ($requires as $requireName => $require) {
$i++;
if ($i == $total) {
$treeBar = $previousTreeBar . ' └';
}
$colorIdent = $level % count($this->colors);
$color = $this->colors[$colorIdent];
$info = sprintf('%s──<%s>%s</%s> %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint());
$output->writeln($info);
$treeBar = str_replace('└', ' ', $treeBar);
if (!in_array($requireName, $packagesInTree)) {
$packagesInTree[] = $requireName;
$this->displayTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree, $output, $treeBar, $level + 1);
}
}
}
}
} }