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 #10939pull/10962/head
parent
595c47f7c9
commit
e59812c439
|
@ -119,6 +119,10 @@ Examples:
|
||||||
- redis
|
- redis
|
||||||
- templating
|
- 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.
|
Optional.
|
||||||
|
|
||||||
### homepage
|
### homepage
|
||||||
|
|
|
@ -13,7 +13,10 @@
|
||||||
namespace Composer\Command;
|
namespace Composer\Command;
|
||||||
|
|
||||||
use Composer\DependencyResolver\Request;
|
use Composer\DependencyResolver\Request;
|
||||||
|
use Composer\Package\CompletePackageInterface;
|
||||||
|
use Composer\Package\PackageInterface;
|
||||||
use Composer\Util\Filesystem;
|
use Composer\Util\Filesystem;
|
||||||
|
use Composer\Util\PackageSorter;
|
||||||
use Seld\Signal\SignalHandler;
|
use Seld\Signal\SignalHandler;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Composer\Console\Input\InputArgument;
|
use Composer\Console\Input\InputArgument;
|
||||||
|
@ -218,9 +221,36 @@ EOT
|
||||||
throw $e;
|
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';
|
$requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
|
||||||
$removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
|
$removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
|
||||||
$requirements = $this->formatRequirements($requirements);
|
|
||||||
|
|
||||||
// validate requirements format
|
// validate requirements format
|
||||||
$versionParser = new VersionParser();
|
$versionParser = new VersionParser();
|
||||||
|
@ -254,6 +284,7 @@ EOT
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$input->setOption('dev', true);
|
||||||
list($requireKey, $removeKey) = array($removeKey, $requireKey);
|
list($requireKey, $removeKey) = array($removeKey, $requireKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,34 @@ use Composer\Package\RootPackageInterface;
|
||||||
|
|
||||||
class PackageSorter
|
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
|
* Sorts packages by name
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue