1
0
Fork 0

Add prompt suggesting using --dev when require command is used with dev packages (#10960)

* Add prompt suggesting using --dev when require command is used with packages which appear to be dev, fixes #10939
pull/10962/head
Jordi Boggiano 2022-07-21 14:40:21 +02:00 committed by GitHub
parent 595c47f7c9
commit e59812c439
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 1 deletions

View File

@ -119,6 +119,10 @@ Examples:
- redis
- templating
> **Note**: Some special keywords trigger `composer require` without the
> `--dev` option to prompt users if they would like to add these packages to
> `require-dev` instead of `require`. These are: `dev`, `testing`, `static analysis`.
Optional.
### homepage

View File

@ -13,7 +13,10 @@
namespace Composer\Command;
use Composer\DependencyResolver\Request;
use Composer\Package\CompletePackageInterface;
use Composer\Package\PackageInterface;
use Composer\Util\Filesystem;
use Composer\Util\PackageSorter;
use Seld\Signal\SignalHandler;
use Symfony\Component\Console\Input\InputInterface;
use Composer\Console\Input\InputArgument;
@ -218,9 +221,36 @@ EOT
throw $e;
}
$requirements = $this->formatRequirements($requirements);
if (!$input->getOption('dev') && $io->isInteractive()) {
$devPackages = [];
$devTags = ['dev', 'testing', 'static analysis'];
$currentRequiresByKey = $this->getPackagesByRequireKey();
foreach ($requirements as $name => $version) {
// skip packages which are already in the composer.json as those have already been decided
if (isset($currentRequiresByKey[$name])) {
continue;
}
$pkg = PackageSorter::getMostCurrentVersion($this->getRepos()->findPackages($name));
if ($pkg instanceof CompletePackageInterface && count(array_intersect($devTags, array_map('strtolower', $pkg->getKeywords()))) > 0) {
$devPackages[] = $name;
}
}
if (count($devPackages) === count($requirements)) {
$plural = count($requirements) > 1 ? 's' : '';
$plural2 = count($requirements) > 1 ? 'are' : 'is';
$io->warning('The package'.$plural.' you required '.$plural2.' recommended to be placed in require-dev but you did not use --dev.');
if ($io->askConfirmation('<info>Do you want to re-run the command with --dev?</> [<comment>yes</>]? ')) {
$input->setOption('dev', true);
}
}
}
$requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
$removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
$requirements = $this->formatRequirements($requirements);
// validate requirements format
$versionParser = new VersionParser();
@ -254,6 +284,7 @@ EOT
return 0;
}
$input->setOption('dev', true);
list($requireKey, $removeKey) = array($removeKey, $requireKey);
}
}

View File

@ -17,6 +17,34 @@ use Composer\Package\RootPackageInterface;
class PackageSorter
{
/**
* Returns the most recent version of a set of packages
*
* This is ideally the default branch version, or failing that it will return the package with the highest version
*
* @template T of PackageInterface
* @param array<T> $packages
* @return ($packages is non-empty-array<T> ? T : T|null)
*/
public static function getMostCurrentVersion(array $packages): ?PackageInterface
{
return array_reduce($packages, function ($carry, $pkg) {
if ($carry === null) {
return $pkg;
}
if ($pkg->isDefaultBranch()) {
return $pkg;
}
if (!$carry->isDefaultBranch() && version_compare($carry->getVersion(), $pkg->getVersion(), '<')) {
return $pkg;
}
return $carry;
});
}
/**
* Sorts packages by name
*