From e3b6c67a449e9375385f596c2ab5cadcafdf1afc Mon Sep 17 00:00:00 2001 From: Nikita Konstantinov Date: Wed, 4 Sep 2019 21:48:40 +0300 Subject: [PATCH] Provide `--fixed` option for the `require` command, fixes #8303 --- src/Composer/Command/InitCommand.php | 11 ++++++----- src/Composer/Command/RequireCommand.php | 22 +++++++++++++++++++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/Composer/Command/InitCommand.php b/src/Composer/Command/InitCommand.php index 6cd722ad5..f4d6d99d3 100644 --- a/src/Composer/Command/InitCommand.php +++ b/src/Composer/Command/InitCommand.php @@ -400,7 +400,7 @@ EOT return $this->repos; } - protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable', $checkProvidedVersions = true) + final protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable', $checkProvidedVersions = true, $fixed = false) { if ($requires) { $requires = $this->normalizeRequirements($requires); @@ -410,7 +410,7 @@ EOT foreach ($requires as $requirement) { if (!isset($requirement['version'])) { // determine the best version automatically - list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability); + list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, null, null, $fixed); $requirement['version'] = $version; // replace package name from packagist.org @@ -423,7 +423,7 @@ EOT )); } else { // check that the specified version/constraint exists before we proceed - list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, $checkProvidedVersions ? $requirement['version'] : null, 'dev'); + list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $phpVersion, $preferredStability, $checkProvidedVersions ? $requirement['version'] : null, 'dev', $fixed); // replace package name from packagist.org $requirement['name'] = $name; @@ -700,10 +700,11 @@ EOT * @param string $preferredStability * @param string|null $requiredVersion * @param string $minimumStability + * @param bool $fixed * @throws \InvalidArgumentException * @return array name version */ - private function findBestVersionAndNameForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null) + private function findBestVersionAndNameForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null, $fixed = null) { // find the latest version allowed in this pool $versionSelector = new VersionSelector($this->getPool($input, $minimumStability)); @@ -777,7 +778,7 @@ EOT return array( $package->getPrettyName(), - $versionSelector->findRecommendedRequireVersion($package), + $fixed ? $package->getPrettyVersion() : $versionSelector->findRecommendedRequireVersion($package), ); } diff --git a/src/Composer/Command/RequireCommand.php b/src/Composer/Command/RequireCommand.php index 8f91b6675..c922875f8 100644 --- a/src/Composer/Command/RequireCommand.php +++ b/src/Composer/Command/RequireCommand.php @@ -49,6 +49,7 @@ class RequireCommand extends InitCommand new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'), new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'), new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'), + new InputOption('fixed', null, InputOption::VALUE_NONE, 'Write fixed version to the composer.json.'), new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'), new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'), new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'), @@ -120,6 +121,25 @@ EOT return 1; } + if ($input->getOption('fixed') === true) { + $config = $this->json->read(); + + $packageType = empty($config['type']) ? 'library' : $config['type']; + + /** + * @see https://github.com/composer/composer/pull/8313#issuecomment-532637955 + */ + if ($packageType !== 'project') { + $io->writeError('"--fixed" option is allowed for "project" package types only to prevent possible misuses.'); + + if (empty($config['type'])) { + $io->writeError('If your package is not library, you should explicitly specify "type" parameter in composer.json.'); + } + + return 1; + } + } + $composer = $this->getComposer(true, $input->getOption('no-plugins')); $repos = $composer->getRepositoryManager()->getRepositories(); @@ -137,7 +157,7 @@ EOT } $phpVersion = $this->repos->findPackage('php', '*')->getPrettyVersion(); - $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability, !$input->getOption('no-update')); + $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability, !$input->getOption('no-update'), $input->getOption('fixed')); $requireKey = $input->getOption('dev') ? 'require-dev' : 'require'; $removeKey = $input->getOption('dev') ? 'require' : 'require-dev';