How to update a single composer package? - php

I know that I can use composer update vendor/package but here's my case.
Composer is very slow when updating, I have around 6 packages installed and one local vcs package being loaded from a local folder. When I run composer update even for that specific local package, composer connects to Packagist to look for other updates and this process is very slow, I don't know if it's my computer or my internet. Is there a way I can tell composer to just update the package from local folder when I run composer update local/package without contacting Packagist and running through all the heavy json files it downloads?
Note:
I know how to load a local composer package. It's loading perfectly, it's just that I'm looking for a way to tell composer just to load the local package without contacting Packagist.
"repositories": [
{
"type": "vcs",
"url": "../local/package"
}
],
My problem is that it's slow to contact Packagist. Running composer update local/package -vvv Shows that it still downloads json files from packagist even if it's told to update just local/package.

There are multiple ways of speeding the Composer fetch up:
define a custom repo, which points to a local path and install with --prefer-source
"repositories": [
{
"type":"vcs",
"url":"/path/to/your/local/package/packageA"
}
],
"require":{
"package/packageA" : "dev-master"
}
Follow-up trick: if you exactly know the type of the repo, then specify it!
In other words: do not use "type":"vcs" if you can specify "type":"git" or "type":"svn". Composer will skip running through all the repo adapters to figure the correct one out.
you could setup Satis and define only the required packages for your project and their dependencies ("require-dependencies": "true"). This acts as a package proxy in front of packagist. You would simply fetch from the local Satis mirror/proxy.
Give this a try, to disable the default Packagist repository:
{
"repositories": [
{
"packagist": false
}
]
}

Related

Composer repository type depends on environment

I want to add repositories in my composer.json where the source depends on the application environment. For example, if I am in local environment, I want to include repositories from a local file path and if it is in production, then I want to include from GIT.
In local:
"repositories": [
{
"type": "path",
"url": "../local-path"
},
]
In production:
"repositories": [
{
"type": "vcs",
"url": "https://github.com/...."
},
]
In my .env file is an APP_ENV variable. Are there any possibilities to achive this?
I think this isn't a great idea because you have a risk of potentially committing your composer.lock file from the wrong environment and deploying it. Hopefully you have stricter deployment checks in place though!
I don't have an exact solution, but some options instead:
Use a Composer config file locally
No need for separate composer file
Might get finicky about versions (I've had trouble getting composer to symlink before)
Should allow you to only maintain one composer.json and only touch the config file when you add new local repos
Documentation
In this example I created a project with a simple composer.json.
{
"name": "mickadoo/test",
"type": "project",
"require": {
"mickadoo/basedata": "dev-master"
}
}
I added a single requirement which is a package I put on packagist myself years ago.
I then created a dummy library to test it locally with the same name. It was in a library directory which contained only a composer.json file. The goal is to check if composer will install this empty library (no requirements) instead of the online one.
{
"name": "mickadoo/basedata",
"type": "library",
"require": {}
}
I then added a config.json file to the project root with configuration telling composer to add a local repo one directory up:
{
"repositories": [
{
"type": "path",
"url": "../library"
}
]
}
After all that I tried first running composer update and setting the COMPOSER_HOME env variable to my current directory. This ensures that composer will pick up the config.json and merge it into the configuration it's using.
$ COMPOSER_HOME=$PWD composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
- Installing mickadoo/basedata (dev-master): Symlinking from ../library
Writing lock file
Generating autoload files
I then deleted everything I did because I've messed around with local paths in composer before and know it can be frustrating to get working:
$ rm -rf vendor/ && rm composer.lock
Finally I tried just running composer update as normal, hoping it would skip the config.json and just pull the package from Github.
$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 14 installs, 0 updates, 0 removals
- Installing symfony/polyfill-apcu (v1.13.1): Downloading (100%)
- Installing psr/log (1.1.2): Downloading (100%)
... more package installs from Github here....
Writing lock file
Generating autoload files
Which it did!
Use a separate composer.json
Keeps things pretty visible
Separate composer.lock file
Documentation
This would mean maintaining two separate files, like composer.local.json and composer.json. It might be tedious, but at least it's clear what's going on. Based on your COMPOSER env variable you can change which filename it's using
I see here a couple of options.
Use a local path to a repository. Then on the dev env checkout different one than on the production. But this would require to keep the local repository in sync with the remote.
Define dist and source for the repository and then differentiate it running composer commands (--prefer-dist on prod, --prefer-source on dev).
Build your own plugin https://getcomposer.org/doc/articles/plugins.md which would jump into action before certain events https://getcomposer.org/doc/articles/scripts.md#event-names
Another option would be to have composer.json file for production and composer-dev.json for development and run the second with setting system ENV variable first:
COMPOSER=composer-dev.json php composer install
But this can produce some incompatibility issues (when you forgot to move a package from composer-dev.json to production composer.json.

How to develop with symlinked composer package, but build from a vcs repository?

While refactoring legacy code, I try to work on a composer package while at the same time work on a project which uses this package.
Composer allows me to add local path repositories for retrieving the package in-development, and symlinking this package into my project.
<composer.json excerpt>
"repositories": [
{
"type": "path",
"url": "../my-package/",
"options": {
"symlink": true
}
}
],
...
"require": {
"my/package": "#dev"
}
I then do
composer update my/package --prefer-source
Which symlinks just fine. However, when building my project on a CI server, I want the project to retrieve the package from a remote git repository, this is why I added the vcs section to my composer.json.
{
"type": "vcs",
"url": "git#bitbucket.org:my/package.git"
}
However, during building via composer install it still tries to retrieve the package locally, which is not available on the CI server of course. I guess because my composer.lock explicitly says that the package is retrieved from a path.
How can I make it work smoothly, both locally and on the CI server? I seem to lack a decent workflow.
What I tried so far:
adding my/package again as a dev-package, but apparently the composer.json will remove if from the no-dev packages automatically then. Also, I do not know how to tell composer to use the path repository for the dev requirement, and the vcs repository for the no-dev requirement.
After tons of hours searching for a suitable workflow, I found out one. Hope it can help you.
Since repository-dev (like require-dev for repository) doesn't exist and will not exist soon (see this), we need to make two composer.json files. Let's say we call the second one composer-dev.json. I think you should commit both and having both up-to-date. To tell composer to use composer-dev.json, you need to put COMPOSER=composer-dev.json in front of every composer command. To illustrate, see this :
composer.json
{
"repositories":[
{
"type": "vcs",
"url": "{repo}"
}
],
"require": {
"vendor/package": "{version}",
}
}
composer-dev.json
{
"repositories":[
{
"type": "path",
"url": "path/to/your/package",
"options": {
"symlink": true
}
}
],
"require": {
"vendor/package" : "{version}",
}
}
As you can see, the composer.json contains the 'vcs' repository and the composer-dev.json contains the 'path' repository.
To initialise your application and start developing :
COMPOSER=composer-dev.json composer update
Composer created the vendor directory and symlink your package folder to vendor/package. It also created a composer-dev.lock file which you should commit for deployment.
To install new package :
COMPOSER=composer-dev.json composer require vendor/package
Remember that composer.json have to be up-to-date, so you have to put all new lines in it.
To build your application :
COMPOSER=composer-dev.json composer install
Which should throw you :
[RuntimeException]
Source path "path/to/your/package" is not found for package vendor/package
Now you can run :
composer update --no-dev vendor/package
or if you need specific version :
composer update --no-dev vendor/package:{version}
Notice that there is no COMPOSER=composer-dev.json in front of the last command since we are using composer.json in order to use our vcs repository. This last command will also install all missing packages.
I hope it was usefull !

Composer - Set local repo as the first preference

I have just setup a local repo on my PC, and its working very well.
But the problem is when I am installing a package the composer tool checks the packagist repo first instead of my local repo. I want the local repo to be checked first. How can fix this??.
here is my global config.json
{
"repositories": {
"local": {
"type": "composer",
"url": "http://localhost:9090"
}
}
Any help?
Is Satis running?
Please browse http://localhost:9090 to make that sure.
Satis needs to run properly and must list your packages, before you can work with composer.json (or even move things to config.json).
The basic guide for setting up Satis is over here: https://getcomposer.org/doc/articles/handling-private-packages-with-satis.md#satis .
If you can't get Satis running, post your satis.json.
You could try removing the key local from config.json and add "packagist": false instead (to disable Packagist lookups).
{
"repositories": [
{ "packagist": false },
{
"type": "composer",
"url": "http://localhost:9090"
}
]
}
I think the solution is to combine
- the setting "packagist":false on your projects
- with "require-dependencies": true on your satis config.
This means that all packages you require are not fetched directly by Composer from Packagist (its off), but indirectly via the Satis server.
Satis will contact Packagist and download the packages to your Satis space (local package cache) and Composer grabs them from there.
I cannot disable packagist since I need it for other packages.
When you allow Satis to fetch them, you can disable packagist globally for projects. The directives require-dependencies and require-all might help.

Composer not installing or updating package

I create a package and pushed it to github, My composer.json for that package looks like such:
{
"name": "adam.balan/AisisAjax",
"description": "This is a component for AisisCore, that is - it should be installed to the Components section of the web based framework for wordpress.",
"license": "GPL v3",
"authors": [
{
"name": "Adam Kyle Balan",
"email": "AdamKyleBalan#gmail.com"
}
],
"minimum-stability": "dev",
"require": {
}
}
It all works fine for me - for using composer install the first time, how ever if I make a change and push it to the repository and run composer install (or even delete the vendor folder and run the command again to do a fresh install) I get a version that reflects the first commit I ever did to this repo. In other words my chanegs do not show up in whats being downloaded.
I have read about caching issues with composer and went to C:\Users\<user>\AppData\Local\Composer and deleted all the files in there - same issue.
What gives?
If you do not use a defined version that is tagged in the repository, but a branch you are developing on, Composer detects which commit was downloaded and will always download that exact commit if you only "install".
If you want Composer to update any dependency, you have to call composer update.
Note that Composer creates a lock file that contains this info, because the usual case is that someone wants to restore the exact combination of dependencies that were used when the software was composed. If you develop actively on the software, simply update your dependencies more often. :)

Where do PHP Composer Packages Come From?

When I run
$ composer.phar install
where do the packages that get installed come from?
I understand that Packagist is the default repository for PHP packages, and that lacking a different package in composer.json, this is where composer will look for packages.
However, what I'm not clear on is how Composer and Packagist interact.
Does Composer download files directly from packagist.org
Or does Composer get a git/svn/hg repository link from packagist and download the files from the repository directly?
Or something else?
It depends on the contents of your composer.json file.
For example, if your composer.json contained simply
{
"require": {
"phpunit/phpunit": "3.8.*#dev"
}
}
then composer searches packagist, and finds phpunit here:
https://packagist.org/packages/phpunit/phpunit
which tells composer to load phpunit from here:
https://github.com/sebastianbergmann/phpunit.git
If instead your composer.json contained
{
"repositories": [
{
"type": "vcs",
"url": "http://github.com/sebastianbergmann/phpunit"
}
],
"require": {
"phpunit/phpunit": "3.8.*#dev"
}
}
then composer will not look to packagist, but go directly to github to download the repo.
The packages registered on Packagist are usually the "authoritative" version of the package (not a fork), but I have found several instances where this is NOT the case, so you should check it to be sure you are pulling the package you expect.
Packagist.org offers users to register their software there by pointing Packagist to read their composer.json file that is published somewhere on the web.
The usual case would be some of the common open source hosters like github, which makes it really easy because composer can deal with such a git repo right away. You could however host your own git or svn or hg repository, or even just publish ready-made ZIP or TGZ files for each software version.
Composer downloads directly from the source, e.g. Packagist only knows those source and tells your composer instance where to go. It does this by downloading a bunch of json files from Packagist.org that have all the infos. This is way easier than to find out where the libraries that you want are hosted and add this info as a repository entry into your local composer.json file. :)

Categories