From 04d2acda2941ac813ff61e3698d2766b76003988 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Fri, 23 Mar 2012 20:58:12 +0100 Subject: [PATCH] Add docs about satis & why repositories are not loaded recursively --- doc/05-repositories.md | 26 +++++--- .../handling-private-packages-with-satis.md | 65 +++++++++++++++++++ ...-composer-load-repositories-recursively.md | 34 ++++++++++ 3 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 doc/articles/handling-private-packages-with-satis.md create mode 100644 doc/faqs/why-can't-composer-load-repositories-recursively.md diff --git a/doc/05-repositories.md b/doc/05-repositories.md index cd8b94a89..bb08a897b 100644 --- a/doc/05-repositories.md +++ b/doc/05-repositories.md @@ -20,7 +20,7 @@ In fact, internally composer sees every version as a separate package. While this distinction does not matter when you are using composer, it's quite important when you want to change it. -In addition to the name and the version, there is useful data. The information +In addition to the name and the version, there is useful metadata. The information most relevant for installation is the source definition, which describes where to get the package contents. The package data points to the contents of the package. And there are two options here: dist and source. @@ -38,11 +38,16 @@ be preferred. ### Repository -A repository is a package source. It's a list of packages, of which you can -pick some to install. +A repository is a package source. It's a list of packages/versions. Composer +will look in all your repositories to find the packages your project requires. -You can also add more repositories to your project by declaring them in -`composer.json`. +By default only the Packagist repository is registered in Composer. You can +add more repositories to your project by declaring them in `composer.json`. + +Repositories are only available to the root package and the repositories +defined in your dependencies will not be loaded. Read the +[FAQ entry](faqs/why-can't-composer-load-repositories-recursively.md) if you +want to learn why. ## Types @@ -229,7 +234,9 @@ There are a few tools that can help you create a `composer` repository. The underlying application used by packagist is open source. This means that you can just install your own copy of packagist, re-brand, and use it. It's really -quite straight-forward to do. +quite straight-forward to do. However due to its size and complexity, for most +small and medium sized companies willing to track a few packages will be better +off using Satis. Packagist is a Symfony2 application, and it is [available on GitHub](https://github.com/composer/packagist). It uses composer internally and @@ -249,12 +256,13 @@ You give it a `composer.json` containing repositories, typically VCS and package repository definitions. It will fetch all the packages that are `require`d and dump a `packages.json` that is your `composer` repository. -Check [the satis GitHub repository](https://github.com/composer/satis) for more +Check [the satis GitHub repository](https://github.com/composer/satis) and +the [Satis article](articles/handling-private-packages-with-satis.md) for more information. -## Disabling packagist +## Disabling Packagist -You can disable the default packagist repository by adding this to your +You can disable the default Packagist repository by adding this to your `composer.json`: { diff --git a/doc/articles/handling-private-packages-with-satis.md b/doc/articles/handling-private-packages-with-satis.md new file mode 100644 index 000000000..aa6b360a5 --- /dev/null +++ b/doc/articles/handling-private-packages-with-satis.md @@ -0,0 +1,65 @@ +# Handling private packages with Satis + +Satis can be used to host the metadata of your company's private packages, or +your own. It basically acts as a micro-packagist. You can get it from +[GitHub](http://github.com/composer/satis). + +## Setup + +For example let's assume you have a few packages you want to reuse across your +company but don't really want to open-source. You would first define a Satis +configuration file, which is basically a stripped-down version of a +`composer.json` file. It contains a few repositories, and then you use the require +key to say which packages it should dump in the static repository it creates. + +Here is an example configuration, you see that it holds a few VCS repositories, +but those could be any types of [repositories](../05-repositories.md). Then +the require just lists all the packages we need, using a `"*"` constraint to +make sure all versions are selected. + + { + "repositories": [ + { "type": "vcs", "url": "http://github.com/mycompany/privaterepo" }, + { "type": "vcs", "url": "http://svn.example.org/private/repo" }, + { "type": "vcs", "url": "http://github.com/mycompany/privaterepo2" } + ], + "require": { + "company/package": "*", + "company/package2": "*", + "company/package3": "*" + } + } + +Once you did this, you just run `php bin/satis build `. +For example `php bin/satis build config.json web/` would read the `config.json` +file and build a static repository inside the `web/` directory. + +When you ironed out that process, what you would typically do is run this +command as a cron job on a server. It would then update all your package info +much like Packagist does. + +Note that if your private packages are hosted on GitHub, your server should have +an ssh key that gives it access to those packages, and then you should add +the `--no-interaction` (or `-n`) flag to the command to make sure it falls back +to ssh key authentication instead of prompting for a password. This is also a +good trick for continuous integration servers. + +Set up a virtual-host that points to that `web/` directory, let's say it is +`packages.example.org`. + +## Usage + +In your projects all you need to add now is your own composer repository using +the `packages.example.org` as URL, then you can require your private packages and +everything should work smoothly. You don't need to copy all your repositories +in every project anymore. Only that one unique repository that will update +itself. + + { + "repositories": [ { "type": "composer", "url": "http://packages.example.org/" } ], + "require": { + "company/package": "1.2.0", + "company/package2": "1.5.2", + "company/package3": "dev-master" + } + } diff --git a/doc/faqs/why-can't-composer-load-repositories-recursively.md b/doc/faqs/why-can't-composer-load-repositories-recursively.md new file mode 100644 index 000000000..88eccaedb --- /dev/null +++ b/doc/faqs/why-can't-composer-load-repositories-recursively.md @@ -0,0 +1,34 @@ +# Why can't Composer load repositories recursively? + +You may run into problems when using custom repositories because Composer does +not load the repositories of your requirements, so you have to redefine those +repositories in all your `composer.json` files. + +Before going into details as to why this is like that, you have to understand +that the main use of custom VCS & package repositories is to temporarily try +some things, or use a fork of a project until your pull request is merged, etc. +You should not use them to keep track of private packages. For that you should +look into [setting up Satis](../articles/handling-private-packages-with-satis.md) +for your company or even for yourself. + +There are three ways the dependency solver could work with custom repositories: + +- Fetch the repositories of root package, get all the packages from the defined +repositories, resolve requirements. This is the current state and it works well +except for the limitation of not loading repositories recursively. + +- Fetch the repositories of root package, while initializing packages from the +defined repos, initialize recursively all repos found in those packages, and +their package's packages, etc, then resolve requirements. It could work, but it +slows down the initialization a lot since VCS repos can each take a few seconds, +and it could end up in a completely broken state since many versions of a package +could define the same packages inside a package repository, but with different +dist/source. There are many many ways this could go wrong. + +- Fetch the repositories of root package, then fetch the repositories of the +first level depencies, then fetch the repositories of their dependencies, etc, +then resolve requirements. This sounds more efficient, but it suffers from the +same problems than the second solution, because loading the repositories of the +dependencies is not as easy as it sounds. You need to load all the repos of all +the potential matches for a requirement, which again might have conflicting +package definitions.