New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
composer require
ing a provided package fails
#10489
Comments
Well, you say that you expect a failure when running a partial update, but you complain about an error when using require to do the same. So I don't understand your report. What do you actually expect to happen during your If your need is to get the solver report with the problem output, instead of a message saying |
@stof the second example is just an elaboration on this setup, and gives an example where the install would fail (constraining versions etc does not change anything). Check the first simple example again; there, the |
Is the reason maybe that |
Yup that's it, composer/src/Composer/Command/InitCommand.php Lines 517 to 550 in 3ae1111
Not trivial to solve then I guess 😬 |
Indeed, you can workaround by bypassing the version guessing perhaps (i.e. specifically providing a constraint I'm not so sure what else to offer here. |
A constraint doesn't help; I don't think the code looks at the I wonder... is it really necessary for this code to check, this early, if a package exists? At least in the case where an explicit version requirement is given, why check if it exists... that's done again later by the solver, no? What I'm trying to do is attempt the installation in an atomic manner; that's why I'd like to use Unfortunately, |
I feel like this should, in principle, be possible. The Just skipping the Take just Composer itself as an example project... shouldn't a (will update title and a bit of the description to reflect this) |
composer require
ing a package together with its provide failscomposer require
ing a provided package fails
…looking up the preferred version (init & require command), refs composer#10489
There is a slightly expanded example further down that explains the why of this, but let's start with a simple case.
My
composer.json
:This installs fine:
Then I want that
heroku-sys/ext-mbstring
package, but that might be provided by a polyfill, so I want to try and install that package in a variant that providesheroku-sys/ext-mbstring.native
, without changing any of the already locked dependencies, so Icomposer require
them together, which gives an error:However, changing
composer.json
as follows:And then confining
composer update
to just those two packages works fine:Am I understanding
composer require
wrong, or is this a bug? :)Second example
Take a fresh checkout of Composer itself. One of its dependencies is
symfony/console
, whichprovide
s the virtual packagepsr/log-implementation
.It's possible to add
psr/log-implementation
tocomposer.json
and runcomposer update
(orcomposer update psr/log-implementation
), butcomposer require psr/log-implementation
fails:The reason is in
InitCommand::determineRequirements()
(RequireCommand
extendsInitCommand
), where$this->findBestVersionAndNameForPackage()
is called even when a version requirement is given.Removing the
else
block in that method solves it:Why did I encounter this?
Heroku translates a project's
composer.lock
to a "platform"composer.json
and uses that to install PHP and its dependencies. The README on it has all the details, but basically, if this operation succeeds, then the followingcomposer install
is guaranteed to have its platform dependencies satisfied.There is an edge case: if a userland package declares a PHP extension as
provide
d (a "polyfill"), then a potentially native version of that extension will not be selected by the solver, because the polyfill is explicitly required and satisfies this requirement.Imagine this example:
PHP
is available in versions 7.1, 7.2, 7.3, 7.4, 8.0, 8.1.ext-mcrypt
is available forPHP
7.1 only - it was removed in PHP 7.2.composer.json
requirement forPHP
is unbounded enough to allow the installation of 7.1 or later.composer.json
requiresext-mcrypt
, but alsophpseclib/mcrypt_compat
(which is a polyfill thatprovide
sext-mcrypt
), so that it's all installable on PHP versions 7.2 and later:Installing this gives PHP 8.1, as expected:
But we want to try installing a native version of
ext-mcrypt
. We're a dumb piece of code that goes through all the userlandprovide
declarations for extensions in order, and attempts to install a native variant. If that works, great, the polyfill will now fall back to faster, native code. If not, no harm done.We have no idea that
ext-mcrypt
is old and not available on modern PHP versions anymore. We're generic code. We're also not in the business of solving dependency graphs. We just want to try and install the native variant without affecting the already installed set of packages.So, since
composer require
doesn't work as reported in this issue, we instead addheroku-sys/ext-mcrypt.native
tocomposer.json
:If we now simply run
composer update
, it will downgrade PHP to 7.1:But as a user, you don't want that! You want the latest possible versions of everything, and the polyfill makes sure that your stuff works even though the extension isn't available for a more recent PHP.
Whereas
composer update heroku-sys/ext-mcrypt heroku-sys/ext-mcrypt.native
fails, as it should in this case:This is great! We don't want to downgrade your dependencies in this case and just continue; but for other extensions, this might work - think all the
symfony/polyfill
packages forext-mbstring
and so forth, where this operation would succeed.I suppose changing
composer.json
programmatically and runningcomposer update
is a viable workaround for the moment, but it would still be great if a simplercomposer require
were possible:The text was updated successfully, but these errors were encountered: