diff --git a/doc/03-cli.md b/doc/03-cli.md index 123dd4044..0f8d1d8f4 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -321,6 +321,8 @@ php composer.phar show monolog/monolog 1.0.2 * **--tree (-t):** List your dependencies as a tree. If you pass a package name it will show the dependency tree for that package. * **--name-only (-N):** List package names only. * **--path (-P):** List package paths. +* **--outdated (-o):** Implies --latest, but this lists *only* packages that have a newer version available. +* **--direct (-D):** Restricts the list of packages to your direct dependencies. ## outdated @@ -334,6 +336,11 @@ The color coding is as such: you can but it may involve work. - **red**: Dependency has a new version that is semver-compatible and you should upgrade it. +### Options + +* **--outdated (-o):** Lists *only* packages that have a newer version available. +* **--direct (-D):** Restricts the list of packages to your direct dependencies. + ## browse / home The `browse` (aliased to `home`) opens a package's repository URL or homepage diff --git a/src/Composer/Command/OutdatedCommand.php b/src/Composer/Command/OutdatedCommand.php index ee843afe1..141e42ce1 100644 --- a/src/Composer/Command/OutdatedCommand.php +++ b/src/Composer/Command/OutdatedCommand.php @@ -16,6 +16,7 @@ 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\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; /** @@ -30,6 +31,8 @@ class OutdatedCommand extends ShowCommand ->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.'), + new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated'), + new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'), )) ->setHelp(<<getArgument('package') ? ProcessExecutor::escape($input->getArgument('package')) : ''; - $input = new StringInput('show --latest '.$pkg); + $args = array($input->getArgument('package') ? ProcessExecutor::escape($input->getArgument('package')) : ''); + $args[] = $input->getOption('outdated') ? ProcessExecutor::escape('--outdated') : ''; + $args[] = $input->getOption('direct') ? ProcessExecutor::escape('--direct') : ''; + $input = new StringInput('show --latest '.implode(' ', $args)); return $this->getApplication()->run($input, $output); } diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 69128bd05..2c544ddf2 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -70,6 +70,8 @@ class ShowCommand extends BaseCommand new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'), new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'), new InputOption('latest', 'l', InputOption::VALUE_NONE, 'Show the latest version'), + new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show the latest version but only for packages that are outdated'), + new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'), )) ->setHelp(<<writeError('You are using the deprecated option "installed". Only installed packages are shown by default now. The --all option can be used to show all packages.'); } + if ($input->getOption('outdated')) { + $input->setOption('latest', true); + } + + if ($input->getOption('direct') && ($input->getOption('all') || $input->getOption('available') || $input->getOption('platform'))) { + $io->writeError('The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)'); + + return 1; + } + if ($input->getOption('tree') && ($input->getOption('all') || $input->getOption('available'))) { $io->writeError('The --tree (-t) option is not usable in combination with --all or --available (-a)'); - return 0; + return 1; } // init repos @@ -185,12 +197,7 @@ EOT // show tree view if requested if ($input->getOption('tree')) { - $rootPackage = $this->getComposer()->getPackage(); - $rootRequires = array_map( - 'strtolower', - array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires())) - ); - + $rootRequires = $this->getRootRequires(); foreach ($installedRepo->getPackages() as $package) { if (in_array($package->getName(), $rootRequires, true)) { $this->displayPackageTree($package, $installedRepo, $repos); @@ -212,6 +219,11 @@ EOT $packageFilter = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i'; } + $packageListFilter = array(); + if ($input->getOption('direct')) { + $packageListFilter = $this->getRootRequires(); + } + foreach ($repos as $repo) { if ($repo === $platformRepo) { $type = 'platform:'; @@ -236,7 +248,9 @@ EOT || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<') ) { if (!$packageFilter || preg_match($packageFilter, $package->getName())) { - $packages[$type][$package->getName()] = $package; + if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) { + $packages[$type][$package->getName()] = $package; + } } } } @@ -291,17 +305,20 @@ EOT $writeDescription = !$input->getOption('name-only') && !$input->getOption('path') && ($nameLength + $versionLength + $latestLength + 24 <= $width); foreach ($packages[$type] as $package) { if (is_object($package)) { + $latestPackackage = null; + if ($showLatest && isset($latestPackages[$package->getPrettyName()])) { + $latestPackackage = $latestPackages[$package->getPrettyName()]; + } + if ($input->getOption('outdated') && $latestPackackage && $latestPackackage->getFullPrettyVersion() === $package->getFullPrettyVersion()) { + continue; + } + $io->write($indent . str_pad($package->getPrettyName(), $nameLength, ' '), false); if ($writeVersion) { $io->write(' ' . str_pad($package->getFullPrettyVersion(), $versionLength, ' '), false); } - $latestPackackage = null; - if ($showLatest && isset($latestPackages[$package->getPrettyName()])) { - $latestPackackage = $latestPackages[$package->getPrettyName()]; - } - if ($writeLatest && $latestPackackage) { $latestVersion = $latestPackackage->getFullPrettyVersion(); $style = $this->getVersionStyle($latestVersion, $package); @@ -352,6 +369,15 @@ EOT } } + protected function getRootRequires() + { + $rootPackage = $this->getComposer()->getPackage(); + return array_map( + 'strtolower', + array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires())) + ); + } + protected function getVersionStyle($latestVersion, $package) { if ($latestVersion === $package->getFullPrettyVersion()) {