Tweak colors in the output, make sure we load the proper version according to stability flags and add outdated command, refs #5028

main
Jordi Boggiano 8 years ago
parent 9206c646a2
commit e7069dd5e8

@ -313,6 +313,7 @@ php composer.phar show monolog/monolog 1.0.2
### Options ### Options
* **--latest (-l):** List all installed packages including their latest version.
* **--all (-a):** List all packages available in all your repositories. * **--all (-a):** List all packages available in all your repositories.
* **--installed (-i):** List the packages that are installed (this is enabled by default, and deprecated). * **--installed (-i):** List the packages that are installed (this is enabled by default, and deprecated).
* **--platform (-p):** List only platform packages (php & extensions). * **--platform (-p):** List only platform packages (php & extensions).
@ -321,6 +322,18 @@ php composer.phar show monolog/monolog 1.0.2
* **--name-only (-N):** List package names only. * **--name-only (-N):** List package names only.
* **--path (-P):** List package paths. * **--path (-P):** List package paths.
## outdated
The `outdated` command shows a list of installed packages including their
current and latest versions. This is basically an alias for `composer show -l`.
The color coding is as such:
- **green**: Dependency is in the latest version and is up to date.
- **yellow**: Dependency has a new version available that includes backwards compatibility breaks according to semver, so upgrade when
you can but it may involve work.
- **red**: Dependency has a new version that is semver-compatible and you should upgrade it.
## browse / home ## browse / home
The `browse` (aliased to `home`) opens a package's repository URL or homepage The `browse` (aliased to `home`) opens a package's repository URL or homepage

@ -0,0 +1,58 @@
<?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\Util\ProcessExecutor;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\OutputInterface;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class OutdatedCommand extends ShowCommand
{
protected function configure()
{
$this
->setName('outdated')
->setDescription('Shows a list of installed packages including their latest version.')
->setDefinition(array(
new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
))
->setHelp(<<<EOT
The outdated command is just a proxy for `composer show -l`
The color coding for dependency versions is as such:
- green: Dependency is in the latest version and is up to date.
- yellow: Dependency has a new version available that includes backwards
compatibility breaks according to semver, so upgrade when you can but it
may involve work.
- red: Dependency has a new version that is semver-compatible and you should upgrade it.
EOT
)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// create new input without "global" command prefix
$input = new StringInput('show --latest '.ProcessExecutor::escape($input->getArgument('package')));
return $this->getApplication()->run($input, $output);
}
}

@ -16,6 +16,7 @@ use Composer\DependencyResolver\Pool;
use Composer\DependencyResolver\DefaultPolicy; use Composer\DependencyResolver\DefaultPolicy;
use Composer\Package\CompletePackageInterface; use Composer\Package\CompletePackageInterface;
use Composer\Package\Version\VersionParser; use Composer\Package\Version\VersionParser;
use Composer\Package\BasePackage;
use Composer\Package\Version\VersionSelector; use Composer\Package\Version\VersionSelector;
use Composer\Plugin\CommandEvent; use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents; use Composer\Plugin\PluginEvents;
@ -34,6 +35,8 @@ use Composer\Repository\PlatformRepository;
use Composer\Repository\RepositoryInterface; use Composer\Repository\RepositoryInterface;
use Composer\Repository\RepositoryFactory; use Composer\Repository\RepositoryFactory;
use Composer\Spdx\SpdxLicenses; use Composer\Spdx\SpdxLicenses;
use Composer\Composer;
use Composer\Semver\Semver;
/** /**
* @author Robert Schönthal <seroscho@googlemail.com> * @author Robert Schönthal <seroscho@googlemail.com>
@ -46,9 +49,6 @@ class ShowCommand extends BaseCommand
protected $versionParser; protected $versionParser;
protected $colors; protected $colors;
/** @var CompositeRepository */
protected $repos;
/** @var Pool */ /** @var Pool */
private $pool; private $pool;
@ -106,6 +106,7 @@ EOT
$platformOverrides = $composer->getConfig()->get('platform') ?: array(); $platformOverrides = $composer->getConfig()->get('platform') ?: array();
} }
$platformRepo = new PlatformRepository(array(), $platformOverrides); $platformRepo = new PlatformRepository(array(), $platformOverrides);
$phpVersion = $platformRepo->findPackage('php', '*')->getVersion();
if ($input->getOption('self')) { if ($input->getOption('self')) {
$package = $this->getComposer()->getPackage(); $package = $this->getComposer()->getPackage();
@ -139,6 +140,11 @@ EOT
$composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent); $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
} }
if ($input->getOption('latest') && null === $composer) {
$io->writeError('No composer.json found in the current directory, disabling "latest" option');
$input->setOption('latest', false);
}
$packageFilter = $input->getArgument('package'); $packageFilter = $input->getArgument('package');
// show single package or single version // show single package or single version
@ -157,8 +163,8 @@ EOT
$this->displayPackageTree($package, $installedRepo, $repos); $this->displayPackageTree($package, $installedRepo, $repos);
} else { } else {
$latestVersion = null; $latestVersion = null;
if ($input->getOption('latest')) { if ($input->getOption('latest') && $composer) {
$latestVersion = $this->findBestVersionForPackage($package->getName(), null); $latestVersion = $this->findBestVersionForPackage($package->getName(), $composer, $phpVersion);
} }
$this->printMeta($package, $versions, $installedRepo, $latestVersion); $this->printMeta($package, $versions, $installedRepo, $latestVersion);
$this->printLinks($package, 'requires'); $this->printLinks($package, 'requires');
@ -285,9 +291,9 @@ EOT
} }
if ($writeLatest) { if ($writeLatest) {
$latestVersion = $this->findBestVersionForPackage($package->getName()); $latestVersion = $this->findBestVersionForPackage($package->getName(), $composer, $phpVersion);
$type = $latestVersion == $package->getFullPrettyVersion() ? 'info' : 'comment'; $style = $this->getVersionStyle($latestVersion, $package);
$io->write(' <'.$type.'>' . str_pad($latestVersion, $latestLength, ' ') . '</'.$type.'>', false); $io->write(' <'.$style.'>' . str_pad($latestVersion, $latestLength, ' ') . '</'.$style.'>', false);
} }
if ($writeDescription) { if ($writeDescription) {
@ -315,6 +321,22 @@ EOT
} }
} }
protected function getVersionStyle($latestVersion, $package)
{
if ($latestVersion === $package->getFullPrettyVersion()) {
// print green as it's up to date
return 'info';
}
if ($latestVersion && Semver::satisfies($latestVersion, '^'.$package->getVersion())) {
// print red as it needs an immediate semver-compliant upgrade
return 'highlight';
}
// print yellow as it needs an upgrade but has potential BC breaks so is not urgent
return 'comment';
}
/** /**
* finds a package by name and version if provided * finds a package by name and version if provided
* *
@ -376,7 +398,8 @@ EOT
$io->write('<info>keywords</info> : ' . join(', ', $package->getKeywords() ?: array())); $io->write('<info>keywords</info> : ' . join(', ', $package->getKeywords() ?: array()));
$this->printVersions($package, $versions, $installedRepo); $this->printVersions($package, $versions, $installedRepo);
if ($latestVersion) { if ($latestVersion) {
$io->write('<info>latest</info> : ' . $latestVersion); $style = $this->getVersionStyle($latestVersion, $package);
$io->write('<info>latest</info> : <'.$style.'>' . $latestVersion . '</'.$style.'>');
} }
$io->write('<info>type</info> : ' . $package->getType()); $io->write('<info>type</info> : ' . $package->getType());
$this->printLicenses($package); $this->printLicenses($package);
@ -621,41 +644,30 @@ EOT
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
* @return string|null * @return string|null
*/ */
private function findBestVersionForPackage($name) private function findBestVersionForPackage($name, Composer $composer, $phpVersion)
{ {
// find the latest version allowed in this pool // find the latest version allowed in this pool
$versionSelector = new VersionSelector($this->getPool()); $versionSelector = new VersionSelector($this->getPool($composer));
$package = $versionSelector->findBestCandidate($name); $stability = $composer->getPackage()->getMinimumStability();
$flags = $composer->getPackage()->getStabilityFlags();
if (isset($flags[$name])) {
$stability = array_search($flags[$name], BasePackage::$stabilities, true);
}
$package = $versionSelector->findBestCandidate($name, null, $phpVersion, $stability);
if ($package) { if ($package) {
return $package->getPrettyVersion(); return $package->getPrettyVersion();
} }
} }
protected function getRepos() private function getPool(Composer $composer)
{
if (!$this->repos) {
$this->repos = new CompositeRepository(array_merge(
array(new PlatformRepository),
RepositoryFactory::defaultRepos($this->getIO())
));
}
return $this->repos;
}
private function getPool()
{ {
if (!$this->pool) { if (!$this->pool) {
$this->pool = new Pool($this->getMinimumStability()); $this->pool = new Pool($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
$this->pool->addRepository($this->getRepos()); $this->pool->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
} }
return $this->pool; return $this->pool;
} }
private function getMinimumStability()
{
return 'stable';
}
} }

@ -116,7 +116,7 @@ class Application extends BaseApplication
} }
} }
if ($commandName !== 'global') { if ($commandName !== 'global' && $commandName !== 'outdated') {
$io->writeError(sprintf( $io->writeError(sprintf(
'Running %s (%s) with %s on %s', 'Running %s (%s) with %s on %s',
Composer::VERSION, Composer::VERSION,
@ -339,6 +339,7 @@ class Application extends BaseApplication
new Command\RemoveCommand(), new Command\RemoveCommand(),
new Command\HomeCommand(), new Command\HomeCommand(),
new Command\ExecCommand(), new Command\ExecCommand(),
new Command\OutdatedCommand(),
)); ));
if ('phar:' === substr(__FILE__, 0, 5)) { if ('phar:' === substr(__FILE__, 0, 5)) {

Loading…
Cancel
Save