How to include Composer dependencies in a Git repo - php

When creating sites using a framework like Silverstripe I often want to use helper modules like gridfieldextensions and lumberjack.
I therefore use composer require to add the dependencies.
However when I follow my regular development work flow and use git add -A to add the module to the repo rather than the code being added to the repo I get a reference to it.
This causes problems when I then try to clone the site elsewhere (using Jenkins or another developer). The git clone or git pull leaves an empty directory.
I solve this by deleting the .git dir of the module and adding all the files.
Is there a better way to do this? Is using git submodule an option?

Somewhere i found a good .gitignore file that ignores everything and i have to tell it to include the custom modules for my project. It's like:
# ignore everything...
/*
# ...but
!/.htaccess
!/.gitignore
!/composer.json
!/composer.lock
!/Capfile
!/Gemfile
!/favicon.ico
!/touch-icon-*
!/mysite
!/some-module
#...other modules
# theme stuff
!/themes/
**/.sass-cache
**/node_modules
!**/node_modules/_manifest_exclude
#no assets in general, but /assets/.htaccess
!/assets
/assets/*
!assets/.htaccess
As FinBoWa already said you need the composer.json and composer.lock file in your project and running
composer install
on another machine it'll install the packages in the versions saved in the composer.lock file on that machine
composer install --no-dev
will only install the "normal" requirements, no dev-requirements like phpunit or other stuff you only need for developing or testing but not live
composer install --no-dev -o
will also optimize (-o) the auto loader, so it'll be a bit faster.
composer update
will update your packages, which might have funny side effects and break your site. So use it carefully and test afterwards.
composer update silverstripe/framework
will just update that package and finally
composer update silverstripe/*
will update all packages by the vendor silverstripe (e.g. framework and cms package)
See also:
gitignore documentation
composer documentation

Related

What exactly is the difference between project and library types in composer?

I have a hard time figuring this out; I am also puzzled of the connection - if any - with the create-project command.
As far as I can tell, the only difference between install and create-project is the execution of post-root-package-install and post-create-project-cmd hooks...
Can someone shed some more light on this?
My goal is to set up a composer infrastructure where I run create-project and this sets up a project skeleton (creates and sets directory permissions, creates default configuration files, creates blank data stores)
What exactly is the difference between project and library types in composer?
Practically, there is none. It doesn't affect how composer gets executed. You can use both install and create-project with both types of package types.
This metadata is meant to inform plugins, IDE, or even packagist.org when parsing composer.json, but on a vainilla installation, there is no practical difference in using one or the other.
(Docs on package types)
As far as I can tell, the only difference between install and create-project is the execution of post-root-package-install and post-create-project-cmd hooks.
The docs are your friends:
You can use Composer to create new projects from an existing package. This is the equivalent of doing a git clone/svn checkout followed by a composer install of the vendors.
Any time you do create-project, install is executed as well. Which means that the install hooks are executed as well.
First it clones the whole package via the appropriate CVS (git, usually), and then immediately executes composer install. By default, it removes CVS information (e.g. the .git directory), unless one uses the --keep-vcs option.
create-project is useful to bootstrap applications, so the app's directory is setup beyond what downloading composer`s dependencies would do. You can create a skeleton directory structure, etc.
Usually one would have a package proper (that could be required into an application), and a "application-skeleton" package, that would include the directory structure and would depend on the original package.
I'm posting a more succint answer to my questions, based on experimentation:
What is the difference between project and library types?
Absolutely none as far as composer is concerned. Some plugins might implement logic to treat the two package types differently though.
How does that relate to require, install, create-project commands?
In no way whatsoever. The project in package type has nothing to do with project in create-project.
How does create-project work?
Let's say we are talking about a single <package>. We have 2 workflows:
composer init <project_path> && composer require <package>
composer create-project <package> <project_path>
The first workflow will create a blank root package and add <package> as a requirement to it.
The second workflow will "clone" <package> into <project_path> as the root package.
NB: If you are working with local path type repos for development, create-project will actually create <project_path> as a symlink to <package>'s source dir. This is the default behavior of path repos, and probably a miss for composer in the need to treat create-project differently. This can create a heap of confusion (as you might be inadvertently changing and adding to <package>s sources while thinking you are just editing project_path). So for local development and testing, you are better off with cp -A rather than composer create-project.

Update project created with composer create-project

There are some frameworks like laravel which recommend installation using create-project.
It would be hard to update projects like this through composer, because
The composer create-project creates the skeleton with all initial
routes in your configuration etc.
From the very very first moment you are starting to change the default
routes, removing the default controllers and changing the default
views, your project would be out of sync. because meanwhile laravel
changes the skeleton to newer versions with some new default routes
etc or event changes directory structure.
However, I've recently seen that phpmyadmin recommends composer create-project as a possible installation method.
As phpmyadmin does not simply provide some skeleton files to be modified by the user, but a complete, finished web-app, I'd like to know what's the best way to update a phpmyadmin installation created like that?
I don't know whether there is an official way to do this.
According to the docs, create-project is the equivalent of:
doing a git clone/svn checkout followed by a composer install of the vendors.
If you haven't modified any of the files, I think the easiest way would be to just delete the directory and run composer create-project again.
If you have modified some of the files, you could do a git merge (if the project uses git) and run composer update again.
If you haven't yet created the project, you could run create-project with the --keep-vcs flag and then every time you want to update it, you can cd to the project and run:
git pull origin <version>
composer update
If you have already installed the project without --keep-vcs, then you'll have to make the directory a git repository and then add the project's repository as remote. To find the project's repository, search for it on Packagist. For example, for phpmyadmin:
cd phpmyadmin
git init
git add .
git commit -m "Add initial files"
git remote add git#github.com:phpmyadmin/composer.git
git pull origin <version> --allow-unrelated-histories -Xtheirs
composer update
Some of your changes might be lost with the above git pull though so make a backup (and maybe research other ways to merge unrelated histories).

Install FOSUserBundle after cloning from Git

I've created my own site on my local computer and it works wonderfully. I'm having tons of fun developing with it. But when it came time to move it to my server and test I ran into issue.
I'm using the FOSUserBundle. Obviously being a Git of it's own, when I did a git commit and push, git ignored everything in vendor/friendsofsymfony/user-bundle. So when I cloned to my server, the folder came empty, and of course now my site doesn't work.
I want to do this the right way. So if it means destroying the git repo and doing it a different way, I'm ok with that.
So far I've tried.
Following the original install instructions for FOSUserBundle
Running the following:
composer update friendsofsymfony/user-bundle
composer install friendsofsymfony/user-bundle
Both return "nothing to update/install"
I've also tried clearing composer's cache between each command attempt.
rm -rf ~/.composer/cache
Answer is in the comments. Ignore vendor/ use composer to install the appropriate files.
also this Symfony project cloned with git vendors not installed
What it sounds like your trying to do is create a mywebsite parent repo within which you have a third party child repo that has the FOSUserBundle code. This uses git submodules and requires related submodule commands like git submodule init.
The ... directory is there, but empty. You must run two commands: git submodule init to initialize your local configuration file, and git submodule update to fetch all the data from that project and check out the appropriate commit listed in your superproject...
I don't know anything about composer. Here is how you could do it with git.
cd mywebsite
git init
git submodule add <url-to-FOSUserBundle-repo>
You should now have a directory structure like this:
mywebsite
.git
.gitmodules
FOSUserBunder
.git
See also http://git-scm.com/book/en/v2/Git-Tools-Submodules

installing laravel --prefer-dist

I am following the Laravel installation on their website
and I came across this line
composer create-project laravel/laravel --prefer-dist
Now, what exactly does the --prefer-dist part mean? I can't see anything on their documentation.
Thanks in advance.
--prefer-dist and --prefer-source are the two options of composer which included in various documentations with a lack of proper explanation.
--prefer-dist would try to download and unzip archives of the dependencies using GitHub or another API when available. This is used for faster downloading of dependencies in most cases. It doesn't download the whole VCS history of the dependencies and it should be better cached. Also archives on GitHub could exclude some files you don't need for just using the dependency with .gitattributes exclude directive.
--prefer-source would try to clone and keep the whole VCS repository of the dependencies when available. This is useful when you want to have the original VCS repositories cloned in your vendor/ folder. E.g. you might want to work on the dependencies - modify them, fork them, submit pull requests etc. while also using them as part of the bigger project which requires them in the first place.
Simply speaking, the --prefer-source option will prefer to create a package directory that is a "version control repository", which is equivalent to you typing:
$ git clone ...
or
$ svn checkout ...
On the other hand, the --prefer-dist option will prefer to create a non-"version control repository", which is equivalent to you typing:
$ git clone ... ; rm -fr dir/.git
or
$ svn export ...
Remember that, these are only preferences, if a dependency is required using a VCS repository which does not provide archives such as GitHub API, then the only available option is to clone the repository.
It's all available here: https://getcomposer.org/doc/03-cli.md#install
--prefer-dist: Reverse of --prefer-source, composer will install from dist if possible. This can speed up installs substantially on build
servers and other use cases where you typically do not run updates of
the vendors. It is also a way to circumvent problems with git if you
do not have a proper setup.
As per the link :
https://getcomposer.org/doc/03-cli.md#install
Here is the documentation statement for the question :-
--prefer-install: There are two ways of downloading a package: source and dist. Composer uses dist by default. If you pass --prefer-install=source (or --prefer-source) Composer will install from source if there is one. This is useful if you want to make a bugfix to a project and get a local git clone of the dependency directly. To get the legacy behavior where Composer use source automatically for dev versions of packages, use --prefer-install=auto. See also config.preferred-install. Passing this flag will override the config value.

How to force composer to reinstall a library?

I'm using the ZF2 skeleton app and it has a .gitignore that prevents external libraries from being commited to git. While debugging I like to go and change stuff here and there in the libraries' source to learn how things work. If these were version controlled it would be very easy to revert them back to their original state.
How can I force Composer to reinstall a particular framework so that I can get a fresh -unmodified- copy again?
PS: Please don't suggest removing the .gitignore file since it's there for a reason; it prevents my third party libraries from getting into my app's repository. I can always install them during an automated deployment.
The same applies to Laravel framework: it also gitignores the vendor folder.
First execute composer clearcache
Then clear your vendors folder
rm -rf vendor/*
or better yet just remove the specific module which makes problems to avoid having to download all over again.
You can use the --prefer-source flag for composer to checkout external packages with the VCS information (if any available). You can simply revert to the original state. Also if you issue the composer update command composer will detect any changes you made locally and ask if you want to discard them.
Your .gitignore file is related to your root project (ZF2 skeleton) and it prevents the vendor dir (where your third party libs are) from committing to your own VCS. The ignore file is unrelated to the git repo's of your vendors.
I didn't want to delete all the packages in vendor/ directory, so here is how I did it:
rm -rf vendor/package-i-messed-up
composer install again
What I did:
Deleted that particular library's folder
composer update --prefer-source vendor/library-name
It fetches the library again along with it's git repo
The relevant feature request is https://github.com/composer/composer/issues/3112
In 2021-05 the "reinstall" command patch got merged: https://github.com/composer/composer/pull/9915 - it is available in composer version 2.1.0 and all later ones.
The reinstall command is merged and availabe since 2.1.0:
composer reinstall <package-name> # Removes and installs the package.
Short answer
you can execute it in one cli command with &&:
composer remove vendor/package && composer require vendor/package:version
Detailed answer
Remove existing package by command:
composer remove vendor/package
this will remove folder of package from /vendor, row from composer.json and whole record of package from composer.lock right way with removing not used dependencies and not removing dependencies which used by another packages
Then install preferred one with command:
composer require vendor/package:version
this will install package with desired version right way with adding row to composer.json, adding record to composer.lock and all needed dependent packages
if there would be package which is used in more that one package, Composer
will try to install version which fits all using packages. If it will not resolve this it will crash with corresponding error message
Links
How to install a specific version of package using Composer?
How to remove a package from Laravel using composer?
Install, Uninstall and Update Modules Themes etc with Composer: https://modulesunraveled.com/drupal-8-composer-and-configuration-management/installing-and-uninstalling-modules-composer
Reinstall the dependencies. Remove the vendor folder (manually) or via rm command (if you are in the project folder, sure) on Linux before:
rm -rf vendor/
composer update -v
https://www.dev-metal.com/composer-problems-try-full-reset/
As user #aaracrr pointed out in a comment on another answer probably the best answer is to re-require the package with the same version constraint.
ie.
composer require vendor/package
or specifying a version constraint
composer require vendor/package:^1.0.0
For some reason no one suggested the obvious and the most straight forward way to force re-install:
> composer remove vendor-name/package-name && composer vendor-name/package-name
Be aware that this exact command will install latest version of the package. If you was using old version of the package and package does not have backward compatibility this will brake version compatibility. You might consider backing up your composer.json first.
Since Composer 2.1 you can do
composer reinstall vendor/package
see https://getcomposer.org/doc/03-cli.md#reinstall
In 2022
You can use composer status to list the libraries you changed.
Then composer resinstall vendor/package to overwrite the changes.
This does not change the version of the installed library like the solutions with composer require or composer install.

Categories