Composer two packages conflicting on dependency version - composer-php

I already have the geoip2 package installed. When I installed it some time ago, it required guzzle 3.* so it installed guzzle 3.9.1 as one of its dependencies.
Now I want to install the predicitonio package, so I added it to my composer.json
"require": {
...
...
"geoip2/geoip2": "0.6.*",
"predictionio/predictionio": "~0.7.1"
}
The issue is predictionio requires guzzle 3.8.0 or 3.8.1, it won't accept the already installed 3.9.1 version.
I believe guzzle 3.8.0 would satisfy both geoip2 and predictionio, so the question is how can I downgrade guzzle, keeping in mind guzzle doesn't appear in my composer.json, only the composer.lock.
Below is the output when I run composer update predictionio/predictionio
Problem 1
- Installation request for predictionio/predictionio ~0.7.1 -> satisfiable by predictionio/predictionio[v0.7.1].
- Conclusion: remove guzzle/guzzle v3.9.1
- predictionio/predictionio v0.7.1 requires guzzle/guzzle ~3.8.0 -> satisfiable by guzzle/guzzle[v3.8.0, v3.8.1].
- Can only install one of: guzzle/guzzle[v3.9.1, v3.8.0].
- Can only install one of: guzzle/guzzle[v3.9.1, v3.8.1].
- Installation request for guzzle/guzzle == 3.9.1.0 -> satisfiable by guzzle/guzzle[v3.9.1].

You don't need to add Guzzle to your composer.json. All you have to do is updating Guzzle when you add the new package. (this will downgrade Guzzle to match PredictionIO's requirements)
Simply run
composer update predictionio/predictionio guzzle/guzzle
As you can see, you can provide multiple packages to composer update by separating them with a space. This is described in the documentation.

Some hints related to the question:
By running composer update named/package, you only allow this package to be added or it's version increased, but nothing else. The same (but only adding stuff) will happen with composer require named/package:~1.0 (this is a nice way to add stuff without having to mess with the json formatting).
The most simple solution when updating stuff is to only run composer update. Without a package name, ALL packages may be updated.
Updating everything might be a bit risky if you weren't careful with selecting your software packages. Personally I recommend using software that somehow seems to use semantic versioning, which very nicely allows to use the tilde version requirement in Composer. I'd say that everyone should try to use ~X.Y as the version description, because this allows for both patches as well as compatible updates to be installed.
Libraries you use should allow for enough loosely defined versions of THEIR dependencies. In your example, the predictionio/predictionio package requires guzzle/guzzle:~3.8.0 - they probably have reasons to do so, but in turn force everyone that tries to use their software to use Guzzle 3.8.0 or 3.8.1. I doubt the Guzzle maintainers will break backwards compatibility, because they know they create a very important, basic piece of software that is expected to work, and I think they will receive bug reports pretty soon should they break stuff nonetheless. I would very much like to see the dependencies of any library to allow for compatible updates without restriction, i.e. in this case ~3.8 would be much better.
Avoid depending on branches at all cost. If it is unavoidable to use a branch, assign it an alias version number: require: { "named/package": "dev-master as 1.2.2" } If no proper version number can be guessed from earlier releases, start with 0.0.0. That way you can switch to a released version later, which will integrate better into the rest of the version numbers.

If you want to install a specific version of a package, you can simply add this to your composer.json in the require section:
"guzzle/guzzle" : "3.8.0",
And then
composer update guzzle/guzzle

Related

composer require reading all version of all package, and take too many time

I'm using OroCommerce and want to add a new packge using composer require
Before install my wanted package, composer display message like this
Reading composer.json of {package_name} ({version})
Composer seems to read all version of all my installed package.
It take so many time to read all version (by example package oroinc/platform have 199 releases)
There is a way to prevent this behavior
I answer myself (in case someone as the same question)
It's no possible https://github.com/composer/composer/issues/5943

Change dependency of php-sass compiler

I want to use the scss compiler for Laravel: https://github.com/panique/laravel-sass. This uses v0.0.14 of leafo/scssphp as a compiler. To upgrade this to the latest version (now v0.7.1) I need to make a change in the composer.json.
But whatever I try, when running composer update I get the notification that panique/laravel-sass dev-master requires leafo/scssphp v0.0.14.
What is the correct way to upgrade the compiler?
Thanks in advance
As you can see in the composer.json of lavarel-sass in https://github.com/panique/laravel-sass/blob/master/composer.json, there is an explicit dependency to v0.0.14 of scssphp. You cannot change this, this needs to be done by the maintainer of lavarel-sass. And even providing ways to override this will cause lavarel-sass to stop working correctly, as the gap between 0.0.14 and 0.7.1 is huge

Is there a way to tell Composer to install a package regardless of it's requirements?

I am working on a CakePHP 3.0 project which I want to update to 3.1-RC1. When I try do so I get an error:
Problem 1
- akkaweb/cakephp-facebook dev-master requires cakephp/cakephp 3.0.x-dev -> satisfiable by cakephp/cakephp[3.0.x-dev].
Now this plugin in question hasn't been updated in 6 months and I suspect it might work OK in CakePHP 3.1, so I would like to try it out.
How do I tell Composer to ignore this particular version incompatibility and proceed to update my CakePHP package?
I am aware of version aliases, but I only want the exception to be for the plugin in question, and not for everything else.
You should be frightened when you want to use a software that isn't maintained, hasn't released any tagged versions, and depends on developer branch versions of other important software. I wouldn't use this package at all. It will harm you in the long term, even if you made Composer install it.
If the current author does not respond to your contact attempts, you should be able to fork the project (in compliance with the license it gave you) and start maintaining the package by fixing the problems you have. Because that's what you'd have to do anyways when using unmaintained software. It will allow you to use this package in a much cleaner way, instead of coming up with a dirty Composer hack to make it install.

Is there a tool that describes updated dependencies in Composer?

You do a composer update and get a list of a few updates:
- Installing cakephp/cakephp (3.0.12)
- Installing cakephp/debug_kit (3.1.10)
- Installing cakephp/bake (1.0.13)
- Installing aws/aws-sdk-php (3.3.1)
- Updating admad/cakephp-jwt-auth dev-master (9a20b56 => e1bb793)
Checking out e1bb793e334b11bdaa19fb653f4b89a4544524f5
Being a conscientious developer, you want to know what's new in CakePHP 3.0.11 and Bake 1.0.13 and all of the rest, to make sure that you're not introducing breaking changes into your project (or if so, that you go fix them right away). You start to dig through Packagist, follow its links through to Github, then find the release tags. Sure, it doesn't take too incredibly long for a project that has only a few dependencies, but what about one with a few dozen?
Which leads to my question -- is there a tool that could automate this process, to automatically give you links to the release notes for the new versions that composer just pulled down for you? Or, even better, displays that information right in your command line?
Yes, there is a Composer Plugin called Composer Changelogs.
It gives a summary of the modified packages with links to release and compare urls.
In other words: after an update or install you get links to the release tag, the release notes and the commits difference between the last and the new release tag for each package.
https://github.com/pyrech/composer-changelogs

Exclude a package from updating in composer

Whenever I try to add a new package using composer like
"composer require packagename/package" or use "composer.phar update", I am getting all the installed packages updated. Is there any option in composer to exclude some package that I don't need to get updated?
run this command and see what is your package version:
composer show -i
go to composer.json and edit which package you want never change by composer update and write version correctly for that :
"jacopo/laravel-authentication-acl": "1.3.*",
change to :
"jacopo/laravel-authentication-acl": "1.3.11",
Done! now if you run composer update this package not update.
From my experience, the best way to exclude 1 or some packages is to use --interactive in composer update.
$ composer update --interactive
When you do this you can select which package you want to update and skip the package that you don't want to update.
You can supply the name(s) of a one or more packages to update:
composer update vendor1/package1 vendor1/package2 vendor2/*
and this will only update those packages.
This isn't specifically excluding, it's including, but it certainly makes updating specific packages much faster.
To avoid the update on using the require command, you'd could hand-craft the composer.json, (which isn't so hard) then run the above targetted update on the package you just added.
Also use --no-dev to exclude development packages (if you are not developing the packages you are depending on e.g. in production). This also speeds up the dependency analysis.
If you feel the need to exclude some of your packages from being updated, I'd consider this the beginning of getting into a dependency mess. You should clean up your dependencies now before it gets worse.
From my experience, the topmost reason not wanting to update a dependency is when you used a branch of a package instead of a released version. You should try to fix this as thoroughly as possible:
If you are using your own packages, tag a release version for the commits you want to use. Then switch your software to either use that exact version, or use a wildcard version requirement like 1.0.*, ~1.2 or ^1.3.4.
If you are using external code that you cannot influence directly, try to contact the developers of that code and ask them to tag a version. Tagging versions is important to maintain a sane dependency tree.
If you cannot make the external developers tag a version, find a way to tag it yourself:
Clone their repository on Github, tag a version, and include your copy of the repository instead of going to packagist.org.
Create the necessary metadata in a "type=package" repository entry in your composer.json file.
Or at the very least, when depending on the branch, assign it a version alias to allow for a smoother transition later when the external project starts tagging their versions. Note that this will not fix your current problems at all, but it may make things better in the future.
If all else fails, you might point to a certain commit id in your composer.json. This will
In general, you should always be able to run composer update unconditionally. If not, this is a warning sign for dependencies not properly declared in your own composer.json file.
The second reason for not wanting to update is incompatible changes in a package that were tagged as a bug fix instead of a major version increase. The solution for this would be simple:
First you'd have to investigate the reason for such an error: Was it really an incompatible API change? If yes, raise an issue with the developers of that package. They should create a new bug fix version with that incompatible update rolled back or fixed, and if they want to keep their change, they should tag it with a minor or major version increment, depending on what they changed.
If however you incorrectly used their code, somehow not using the public API, a bug fix is unlikely. You should try fixing your code by not using stuff that is not supposed to be the public API. For example, in recent versions of Symfony, the public API is explicitly tagged in the code and documentation - using something else will break at some point, even when doing "compatible" version updates like from 2.6.x to 2.7.x.
Another way to fix it would be to exclude the newer version inside the composer.json file: Instead of "external/package":"~1.2" you'd put "external/package":"~1.2,!1.2.5" if you find that version 1.2.5 broke your software. Or maybe you are afraid of further updates also breaking your software, you'd put in "external/package":"~1.2,!>=1.2.5".
One more thing to add: If you run composer require, you won't get updates for packages that are already installed. They are fixed. The required package will be selected based on all the installed versions, and it will only be installed if there is a version available that is compatible with all the versions already installed. Note that this will not work correctly if there are dependencies on branches of packages in both your own composer.json and the new package. The reason is that the branch name will be the same, but you'll never know which commit was being used. Maybe the new package uses a very recent commit of dev-master of a third package, and your own software a very old one, and there have been incompatible changes in between - this will break things without Composer being able to detect it.
Using composer require packagename/package, you require a new package and you get a partial update for just packagename/package and its dependencies.
composer update packagename/package can be used to trigger the same partial update, but then in case you already have packagename/package in your composer.json.
One workaround is to use replace property, however there isn't dedicated command for that, so you can run composer require foo/bar as usual (which will create composer.json), then add a new replace section for the package to ignore.
Or create composer.json file on your own. Here is the example:
{
"require": {
"radic/tmp-underscore-php": "1.2.0"
},
"replace": {
"patchwork/utf8": "*"
}
}
Once you run composer install, the required package patchwork/utf8 won't be downloaded.

Resources