diff --git a/src/Composer/Command/BaseDependencyCommand.php b/src/Composer/Command/BaseDependencyCommand.php index d3b690eca..e010c122a 100644 --- a/src/Composer/Command/BaseDependencyCommand.php +++ b/src/Composer/Command/BaseDependencyCommand.php @@ -152,7 +152,23 @@ abstract class BaseDependencyCommand extends BaseCommand } if ($inverted && $input->hasArgument(self::ARGUMENT_CONSTRAINT)) { - $this->getIO()->writeError('Not finding what you were looking for? Try calling `composer update "'.$input->getArgument(self::ARGUMENT_PACKAGE).':'.$input->getArgument(self::ARGUMENT_CONSTRAINT).'" --dry-run` to get another view on the problem.'); + $composerCommand = 'update'; + + foreach ($composer->getPackage()->getRequires() as $rootRequirement) { + if ($rootRequirement->getTarget() === $needle) { + $composerCommand = 'require'; + break; + } + } + + foreach ($composer->getPackage()->getDevRequires() as $rootRequirement) { + if ($rootRequirement->getTarget() === $needle) { + $composerCommand = 'require --dev'; + break; + } + } + + $this->getIO()->writeError('Not finding what you were looking for? Try calling `composer '.$composerCommand.' "'.$needle.':'.$textConstraint.'" --dry-run` to get another view on the problem.'); } return 0; diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index 621f984c2..40e566136 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -161,7 +161,9 @@ EOT $parsedConstraint = $parser->parseConstraints($constraint); $temporaryConstraints[$package] = $parsedConstraint; if (isset($rootRequirements[$package]) && !Intervals::haveIntersections($parsedConstraint, $rootRequirements[$package]->getConstraint())) { - throw new \InvalidArgumentException('The temporary constraint "'.$constraint.'" for "'.$package.'" must be a subset of the constraint in your composer.json ('.$rootRequirements[$package]->getPrettyConstraint().')'); + $io->writeError('The temporary constraint "'.$constraint.'" for "'.$package.'" must be a subset of the constraint in your composer.json ('.$rootRequirements[$package]->getPrettyConstraint().')'); + $io->write('Run `composer require '.$package.'` or `composer require '.$package.':'.$constraint.'` instead to replace the constraint'); + return self::FAILURE; } } diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index 02a5f9627..d10ad87a0 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -91,7 +91,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt 'svn' => 'Composer\Repository\Vcs\SvnDriver', ]; - $this->url = Platform::expandPath($repoConfig['url']); + $this->url = $repoConfig['url'] = Platform::expandPath($repoConfig['url']); $this->io = $io; $this->type = $repoConfig['type'] ?? 'vcs'; $this->isVerbose = $io->isVerbose(); diff --git a/tests/Composer/Test/Command/BaseDependencyCommandTest.php b/tests/Composer/Test/Command/BaseDependencyCommandTest.php index 78b41d223..8b0230dfc 100644 --- a/tests/Composer/Test/Command/BaseDependencyCommandTest.php +++ b/tests/Composer/Test/Command/BaseDependencyCommandTest.php @@ -396,11 +396,11 @@ OUTPUT $secondDevNestedRequiredPackage = self::getPackage('vendor2/package3', '1.4.0'); $this->createComposerLock( - [$someRequiredPackage], + [$someRequiredPackage], [$firstDevRequiredPackage, $secondDevRequiredPackage] ); $this->createInstalledJson( - [$someRequiredPackage], + [$someRequiredPackage], [$firstDevRequiredPackage, $secondDevRequiredPackage, $secondDevNestedRequiredPackage] ); @@ -425,7 +425,7 @@ OUTPUT << 'vendor1/package1', 'version' => '^1.3'], << satisfiable by root/req[1.0.0]. - root/req 1.0.0 requires dep/pkg ^1 -> found dep/pkg[1.0.0, 1.0.1, 1.0.2] but it conflicts with your temporary update constraint (dep/pkg:^2). +OUTPUT + ]; + + yield 'update with temporary constraint failing resolution on root package' => [ + $rootDepAndTransitiveDep, + ['--with' => ['root/req:^2']], + <<