Browse Source

Merge branch 'docs-improve'

* docs-improve:
  Docs: cleanup version branches section
  Docs: those/these composer/Composer
  Docs: notice => note
  Docs: Fix shell sample output
  Docs: Add back a second clear note about hardcoded versions in VCS
  Docs: HHVM is not called HipHop
  Docs: versions plural, and update == rm lock&install
  Docs: don't use short forms, it => composer
  Docs: composer.lock lists versions, not constraints
  Docs: superfluous comma & it => Composer
  The confusing part is probably rather constraints and how versions work, not what they are
  Docs: Clarify what "It" stands for
  Finished reworking docs to clarify points about versioning (fixes #6088)
  Updated basic usage and versions pages to clarify how versioning and package resolution works (refs #6088)
  Added some useful overview information about repositories in the Basic Usage documentation.
Nils Adermann 8 years ago
parent
commit
001fe8afcf
4 changed files with 246 additions and 166 deletions
  1. 131 76
      doc/01-basic-usage.md
  2. 21 81
      doc/02-libraries.md
  3. 5 4
      doc/04-schema.md
  4. 89 5
      doc/articles/versions.md

+ 131 - 76
doc/01-basic-usage.md

@@ -18,7 +18,7 @@ other metadata as well.
 ### The `require` Key
 
 The first (and often only) thing you specify in `composer.json` is the
-[`require`](04-schema.md#require) key. You're simply telling Composer which
+[`require`](04-schema.md#require) key. You are simply telling Composer which
 packages your project depends on.
 
 ```json
@@ -33,36 +33,56 @@ As you can see, [`require`](04-schema.md#require) takes an object that maps
 **package names** (e.g. `monolog/monolog`) to **version constraints** (e.g.
 `1.0.*`).
 
+Composer uses this information to search for the right set of files in package
+"repositories" that you register using the [`repositories`](04-schema.md#repositories)
+key, or in Packagist, the default package respository. In the above example,
+since no other repository has been registered in the `composer.json` file, it is
+assumed that the `monolog/monolog` package is registered on Packagist. (See more
+about Packagist [below](#packagist), or read more about repositories
+[here](05-repositories.md).
+
 ### Package Names
 
 The package name consists of a vendor name and the project's name. Often these
-will be identical - the vendor name just exists to prevent naming clashes. It
-allows two different people to create a library named `json`, which would then
-just be named `igorw/json` and `seldaek/json`.
-
-Here we are requiring `monolog/monolog`, so the vendor name is the same as the
-project's name. For projects with a unique name this is recommended. It also
-allows adding more related projects under the same namespace later on. If you
-are maintaining a library, this would make it really easy to split it up into
-smaller decoupled parts.
-
-### Package Versions
-
-In the previous example we were requiring version
-[`1.0.*`](http://semver.mwl.be/#?package=monolog%2Fmonolog&version=1.0.*) of
-Monolog. This means any version in the `1.0` development branch. It is the
-equivalent of saying versions that match `>=1.0 <1.1`.
-
-Version constraints can be specified in several ways, read
-[versions](articles/versions.md) for more in-depth information on this topic.
-
-### Stability
-
-By default only stable releases are taken into consideration. If you would
-like to also get RC, beta, alpha or dev versions of your dependencies you can
-do so using [stability flags](04-schema.md#package-links). To change that for
-all packages instead of doing per dependency you can also use the
-[minimum-stability](04-schema.md#minimum-stability) setting.
+will be identical - the vendor name just exists to prevent naming clashes. For
+example, it would allow two different people to create a library named `json`.
+One might be named `igorw/json` while the other might be `seldaek/json`.
+
+Read more about publishing packages and package naming [here](02-libraries.md).
+(Note that you can also specify "platform packages" as dependencies, allowing
+you to require certain versions of server software. See
+[platform packages](#platform-packages) below.)
+
+### Package Version Constraints
+
+In our example, we are requesting the Monolog package with the version constraint
+[`1.0.*`](http://semver.mwl.be/#?package=monolog%2Fmonolog&version=1.0.*).
+This means any version in the `1.0` development branch, or any version that is
+greater than or equal to 1.0 and less than 1.1 (`>=1.0 <1.1`).
+
+Please read [versions](articles/versions.md) for more in-depth information on
+versions, how versions relate to each other, and on version constraints.
+
+> **How does Composer download the right files?** When you specify a dependency in
+> `composer.json`, Composer first takes the name of the package that you have requested
+> and searches for it in any repositories that you have registered using the
+> [`repositories`](04-schema.md#repositories) key. If you have not registered
+> any extra repositories, or it does not find a package with that name in the
+> repositories you have specified, it falls back to Packagist (more [below](#packagist)).
+>
+> When Composer finds the right package, either in Packagist or in a repo you have specified,
+> it then uses the versioning features of the package's VCS (i.e., branches and tags)
+> to attempt to find the best match for the version constraint you have specified. Be sure to read
+> about versions and package resolution in the [versions article](articles/versions.md).
+
+> **Note:** If you are trying to require a package but Composer throws an error
+> regarding package stability, the version you have specified may not meet your
+> default minimum stability requirements. By default only stable releases are taken
+> into consideration when searching for valid package versions in your VCS.
+>
+> You might run into this if you are trying to require dev, alpha, beta, or RC
+> versions of a package. Read more about stability flags and the `minimum-stability`
+> key on the [schema page](04-schema.md).
 
 ## Installing Dependencies
 
@@ -73,48 +93,63 @@ To install the defined dependencies for your project, just run the
 php composer.phar install
 ```
 
-This will find the latest version of `monolog/monolog` that matches the
-supplied version constraint and download it into the `vendor` directory.
-It's a convention to put third party code into a directory named `vendor`.
-In case of Monolog it will put it into `vendor/monolog/monolog`.
-
-> **Tip:** If you are using git for your project, you probably want to add
-> `vendor` in your `.gitignore`. You really don't want to add all of that
-> code to your repository.
-
-You will notice the [`install`](03-cli.md#install) command also created a
-`composer.lock` file.
-
-## `composer.lock` - The Lock File
-
-After installing the dependencies, Composer writes the list of the exact
-versions it installed into a `composer.lock` file. This locks the project
-to those specific versions.
-
-**Commit your application's `composer.lock` (along with `composer.json`)
-into version control.**
+When you run this command, one of two things may happen:
 
-This is important because the [`install`](03-cli.md#install) command checks
-if a lock file is present, and if it is, it downloads the versions specified
-there (regardless of what `composer.json` says).
+### Installing Without `composer.lock`
 
-This means that anyone who sets up the project will download the exact same
-version of the dependencies. Your CI server, production machines, other
-developers in your team, everything and everyone runs on the same dependencies,
-which mitigates the potential for bugs affecting only some parts of the
-deployments. Even if you develop alone, in six months when reinstalling the
-project you can feel confident the dependencies installed are still working even
-if your dependencies released many new versions since then.
+If you have never run the command before and there is also no `composer.lock` file present,
+Composer simply resolves all dependencies listed in your `composer.json` file and downloads
+the latest version of their files into the `vendor` directory in your project. (The `vendor`
+directory is the conventional location for all third-party code in a project). In our
+example from above, you would end up with the Monolog source files in
+`vendor/monolog/monolog/`. If Monolog listed any dependencies, those would also be in
+folders under `vendor/`.
 
-If no `composer.lock` file exists, Composer will read the dependencies and
-versions from `composer.json` and  create the lock file after executing the
-[`update`](03-cli.md#update) or the [`install`](03-cli.md#install) command.
-
-This means that if any of the dependencies get a new version, you won't get the
-updates automatically. To update to the new version, use the
+> **Tip:** If you are using git for your project, you probably want to add
+> `vendor` in your `.gitignore`. You really don't want to add all of that
+> third-party code to your versioned repository.
+
+When Composer has finished installing, it writes all of the packages and the exact versions
+of them that it downloaded to the `composer.lock` file, locking the project to those specific
+versions. You should commit the `composer.lock` file to your project repo so that all people
+working on the project are locked to the same versions of dependencies (more below).
+
+### Installing With `composer.lock`
+
+This brings us to the second scenario. If there is already a `composer.lock` file as well as a
+`composer.json` file when you run `composer install`, it means either you ran the
+`install` command before, or someone else on the project ran the `install` command and
+committed the `composer.lock` file to the project (which is good).
+
+Either way, running `install` when a `composer.lock` file is present resolves and installs
+all dependencies that you listed in `composer.json`, but Composer uses the exact versions listed
+in `composer.lock` to ensure that the package versions are consistent for everyone
+working on your project. As a result you will have all dependencies requested by your
+`composer.json` file, but they may not all be at the very latest available versions
+(some of the dependencies listed in the `composer.lock` file may have released newer versions since
+the file was created). This is by design, it ensures that your project does not break because of
+unexpected changes in dependencies.
+
+### Commit Your `composer.lock` File to Version Control
+
+Committing this file to VC is important because it will cause anyone who sets
+up the project to use the exact same
+versions of the dependencies that you are using. Your CI server, production
+machines, other developers in your team, everything and everyone runs on the
+same dependencies, which mitigates the potential for bugs affecting only some
+parts of the deployments. Even if you develop alone, in six months when
+reinstalling the project you can feel confident the dependencies installed are
+still working even if your dependencies released many new versions since then.
+(See note below about using the `update` command.)
+
+## Updating Dependencies to their Latest Versions
+
+As mentioned above, the `composer.lock` file prevents you from automatically getting
+the latest versions of your dependencies. To update to the latest versions, use the
 [`update`](03-cli.md#update) command. This will fetch the latest matching
-versions (according to your `composer.json` file) and also update the lock file
-with the new version.
+versions (according to your `composer.json` file) and update the lock file
+with the new versions. (This is equivalent to deleting the `composer.lock` file
+and running `install` again.)
 
 ```sh
 php composer.phar update
@@ -136,30 +171,50 @@ php composer.phar update monolog/monolog [...]
 [Packagist](https://packagist.org/) is the main Composer repository. A Composer
 repository is basically a package source: a place where you can get packages
 from. Packagist aims to be the central repository that everybody uses. This
-means that you can automatically `require` any package that is available there.
+means that you can automatically `require` any package that is available there,
+without further specifying where Composer should look for the package.
 
 If you go to the [Packagist website](https://packagist.org/) (packagist.org),
 you can browse and search for packages.
 
 Any open source project using Composer is recommended to publish their packages
-on Packagist. A library doesn't need to be on Packagist to be used by Composer,
+on Packagist. A library does not need to be on Packagist to be used by Composer,
 but it enables discovery and adoption by other developers more quickly.
 
+## Platform packages
+
+Composer has platform packages, which are virtual packages for things that are
+installed on the system but are not actually installable by Composer. This
+includes PHP itself, PHP extensions and some system libraries.
+
+* `php` represents the PHP version of the user, allowing you to apply
+  constraints, e.g. `>=5.4.0`. To require a 64bit version of php, you can
+  require the `php-64bit` package.
+
+* `hhvm` represents the version of the HHVM runtime and allows you to apply
+  a constraint, e.g., '>=2.3.3'.
+
+* `ext-<name>` allows you to require PHP extensions (includes core
+  extensions). Versioning can be quite inconsistent here, so it's often
+  a good idea to just set the constraint to `*`.  An example of an extension
+  package name is `ext-gd`.
+
+* `lib-<name>` allows constraints to be made on versions of libraries used by
+  PHP. The following are available: `curl`, `iconv`, `icu`, `libxml`,
+  `openssl`, `pcre`, `uuid`, `xsl`.
+
+You can use [`show --platform`](03-cli.md#show) to get a list of your locally
+available platform packages.
+
 ## Autoloading
 
 For libraries that specify autoload information, Composer generates a
-`vendor/autoload.php` file. You can simply include this file and you will get
-autoloading for free.
+`vendor/autoload.php` file. You can simply include this file and start
+using the classes that those libraries provide without any extra work:
 
 ```php
 require __DIR__ . '/vendor/autoload.php';
-```
-
-This makes it really easy to use third party code. For example: If your project
-depends on Monolog, you can just start using classes from it, and they will be
-autoloaded.
 
-```php
 $log = new Monolog\Logger('name');
 $log->pushHandler(new Monolog\Handler\StreamHandler('app.log', Monolog\Logger::WARNING));
 $log->addWarning('Foo');

+ 21 - 81
doc/02-libraries.md

@@ -8,7 +8,7 @@ Composer.
 As soon as you have a `composer.json` in a directory, that directory is a
 package. When you add a [`require`](04-schema.md#require) to a project, you are
 making a package that depends on other packages. The only difference between
-your project and libraries is that your project is a package without a name.
+your project and a library is that your project is a package without a name.
 
 In order to make that package installable you need to give it a name. You do
 this by adding the [`name`](04-schema.md#name) property in `composer.json`:
@@ -29,40 +29,18 @@ name. Supplying a vendor name is mandatory.
 > username is usually a good bet. While package names are case insensitive, the
 > convention is all lowercase and dashes for word separation.
 
-## Platform packages
+## Library Versioning
 
-Composer has platform packages, which are virtual packages for things that are
-installed on the system but are not actually installable by Composer. This
-includes PHP itself, PHP extensions and some system libraries.
+In the vast majority of cases, you will be maintaining your library using some
+sort of version control system like git, svn, hg or fossil. In these cases,
+Composer infers versions from your VCS and you **should not** specify a version
+in your `composer.json` file. (See the [Versions article](articles/versions.md)
+to learn about how Composer uses VCS branches and tags to resolve version
+constraints.)
 
-* `php` represents the PHP version of the user, allowing you to apply
-  constraints, e.g. `>=5.4.0`. To require a 64bit version of php, you can
-  require the `php-64bit` package.
-
-* `hhvm` represents the version of the HHVM runtime (aka HipHop Virtual
-  Machine) and allows you to apply a constraint, e.g., '>=2.3.3'.
-
-* `ext-<name>` allows you to require PHP extensions (includes core
-  extensions). Versioning can be quite inconsistent here, so it's often
-  a good idea to just set the constraint to `*`.  An example of an extension
-  package name is `ext-gd`.
-
-* `lib-<name>` allows constraints to be made on versions of libraries used by
-  PHP. The following are available: `curl`, `iconv`, `icu`, `libxml`,
-  `openssl`, `pcre`, `uuid`, `xsl`.
-
-You can use [`show --platform`](03-cli.md#show) to get a list of your locally
-available platform packages.
-
-## Specifying the version
-
-When you publish your package on Packagist, it is able to infer the version
-from the VCS (git, svn, hg, fossil) information. This means you don't have to
-explicitly declare it. Read [tags](#tags) and [branches](#branches) to see how
-version numbers are extracted from these.
-
-If you are creating packages by hand and really have to specify it explicitly,
-you can just add a `version` field:
+If you are maintaining packages by hand (i.e., without a VCS), you'll need to
+specify the version explicitly by adding a `version` value in your `composer.json`
+file:
 
 ```json
 {
@@ -70,57 +48,19 @@ you can just add a `version` field:
 }
 ```
 
-> **Note:** You should avoid specifying the version field explicitly, because
-> for tags the value must match the tag name.
-
-### Tags
-
-For every tag that looks like a version, a package version of that tag will be
-created. It should match 'X.Y.Z' or 'vX.Y.Z', with an optional suffix of
-`-patch` (`-p`), `-alpha` (`-a`), `-beta` (`-b`) or `-RC`. The suffix can also
-be followed by a number.
-
-Here are a few examples of valid tag names:
-
-- 1.0.0
-- v1.0.0
-- 1.10.5-RC1
-- v4.4.4-beta2
-- v2.0.0-alpha
-- v2.0.4-p1
-
-> **Note:** Even if your tag is prefixed with `v`, a
-> [version constraint](01-basic-usage.md#package-versions) in a `require`
-> statement has to be specified without prefix (e.g. tag `v1.0.0` will result
-> in version `1.0.0`).
-
-### Branches
-
-For every branch, a package development version will be created. If the branch
-name looks like a version, the version will be `{branchname}-dev`. For example,
-the branch `2.0` will get the `2.0.x-dev` version (the `.x` is added for
-technical reasons, to make sure it is recognized as a branch). The `2.0.x`
-branch would also be valid and be turned into `2.0.x-dev` as well. If the
-branch does not look like a version, it will be `dev-{branchname}`. `master`
-results in a `dev-master` version.
-
-Here are some examples of version branch names:
-
-- 1.x
-- 1.0 (equals 1.0.x)
-- 1.1.x
-
-> **Note:** When you install a development version, it will be automatically
-> pulled from its `source`. See the [`install`](03-cli.md#install) command
-> for more details.
+> **Note:** When you add a hardcoded version to a VCS, the version will conflict
+> with tag names. Composer will not be able to determine the version number.
 
-### Aliases
+### VCS Versioning
 
-It is possible to alias branch names to versions. For example, you could alias
-`dev-master` to `1.0.x-dev`, which would allow you to require `1.0.x-dev` in
-all the packages.
+Composer uses your VCS's branch and tag features to resolve the version
+constraints you specify in your `require` field to specific sets of files.
+When determining valid available versions, Composer looks at all of your tags
+and branches and translates their names into an internal list of options that
+it then matches against the version constraint you provided.
 
-See [Aliases](articles/aliases.md) for more information.
+For more on how Composer treats tags and branches and how it resolves package
+version constraints, read the [versions](articles/versions.md) article.
 
 ## Lock file
 

+ 5 - 4
doc/04-schema.md

@@ -255,7 +255,8 @@ Optional.
 ### Package links
 
 All of the following take an object which maps package names to
-[version constraints](01-basic-usage.md#package-versions).
+versions of the package via version constraints. Read more about
+versions [here](articles/versions.md).
 
 Example:
 
@@ -688,9 +689,9 @@ it in your file to avoid surprises.
 
 All versions of each package are checked for stability, and those that are less
 stable than the `minimum-stability` setting will be ignored when resolving
-your project dependencies. Specific changes to the stability requirements of
-a given package can be done in `require` or `require-dev` (see
-[package links](#package-links)).
+your project dependencies. (Note that you can also specify stability requirements
+on a per-package basis using stability flags in the version constraints that you
+specify in a `require` block (see [package links](#package-links) for more details).
 
 Available options (in order of stability) are `dev`, `alpha`, `beta`, `RC`,
 and `stable`.

+ 89 - 5
doc/articles/versions.md

@@ -1,10 +1,93 @@
 <!--
-    tagline: Version constraints explained.
+    tagline: Versions explained.
 -->
 
 # Versions
 
-## Basic Constraints
+## Composer Versions vs VCS Versions
+
+Because Composer is heavily geared toward utilizing version control systems
+like git, the term "version" can be a little ambiguous. In the sense of a
+version control system, a "version" is a specific set of files that contain
+specific data. In git terminology, this is a "ref", or a specific commit,
+which may be represented by a branch HEAD or a tag. When you check out that
+version in your VCS -- for example, tag `v1.1` or commit `e35fa0d` --, you're
+asking for a single, known set of files, and you always get the same files back.
+
+In Composer, what's often referred to casually as a version -- that is,
+the string that follows the package name in a require line (e.g., `~1.1` or
+`1.2.*`) -- is actually more specifically a version constraint. Composer
+uses version constraints to figure out which refs in a VCS it should be
+checking out (or simply to verify that a given library is acceptable in
+the case of a statically-maintained library with a `version` specification
+in `composer.json`).
+
+## VCS Tags and Branches
+
+*For the following discussion, let's assume the following sample library
+repository:*
+
+```sh
+~/my-library$ git branch
+v1
+v2
+my-feature
+nother-feature
+
+~/my-library$ git tag
+v1.0
+v1.0.1
+v1.0.2
+v1.1-BETA
+v1.1-RC1
+v1.1-RC2
+v1.1
+v1.1.1
+v2.0-BETA
+v2.0-RC1
+v2.0
+v2.0.1
+v2.0.2
+```
+
+### Tags
+
+Normally, Composer deals with tags (as opposed to branches -- if you don't
+know what this means, read up on
+[version control systems](https://en.wikipedia.org/wiki/Version_control#Common_vocabulary)).
+When you write a version constraint, it may reference a specific tag (e.g.,
+`1.1`) or it may reference a valid range of tags (e.g., `>=1.1 <2.0`, or
+`~4.0`). To resolve these constraints, Composer first asks the VCS to list
+all available tags, then creates an internal list of available versions based
+on these tags. In the above example, composer's internal list includes versions
+`1.0`, `1.0.1`, `1.0.2`, the beta release of `1.1`, the first and second
+release candidates of `1.1`, the final release version `1.1`, etc.... (Note
+that Composer automatically removes the 'v' prefix in the actual tagname to
+get a valid final version number.)
+
+When Composer has a complete list of available versions from your VCS, it then
+finds the highest version that matches all version constraints in your project
+(it's possible that other packages require more specific versions of the
+library than you do, so the version it chooses may not always be the highest
+available version) and it downloads a zip archive of that tag to unpack in the
+correct location in your `vendor` directory.
+
+### Branches
+
+If you want Composer to check out a branch instead of a tag, you need to point it to the branch using the special `dev-*` prefix (or sometimes suffix; see below). If you're checking out a branch, it's assumed that you want to *work* on the branch and Composer actually clones the repo into the correct place in your `vendor` directory. For tags, it just copies the right files without actually cloning the repo. (You can modify this behavior with --prefer-source and --prefer-dist, see [install options](03-cli.md#install).) 
+
+In the above example, if you wanted to check out the `my-feature` branch, you would specify `dev-my-feature` as the version constraint in your `require` clause. This would result in Composer cloning the `my-library` repository into my `vendor` directory and checking out the `my-feature` branch.
+
+When branch names look like versions, we have to clarify for composer that we're trying to check out a branch and not a tag. In the above example, we have two version branches: `v1` and `v2`. To get Composer to check out one of these branches, you must specify a version constraint that looks like this: `v1.x-dev`. The `.x` is an arbitrary string that Composer requires to tell it that we're talking about the `v1` branch and not a `v1` tag (alternatively, you can just name the branch `v1.x` instead of `v1`). In the case of a branch with a version-like name (`v1`, in this case), you append `-dev` as a suffix, rather than using `dev-` as a prefix.
+
+### Minimum Stability
+
+There's one more thing that will affect which files are checked out of a library's VCS and added to your project: Composer allows you to specify stability constraints to limit which tags are considered valid. In the above example, note that the library released a beta and two release candidates for version `1.1` before the final official release. To receive these versions when running `composer install` or `composer update`, we have to explicitly tell Composer that we are ok with release candidates and beta releases (and alpha releases, if we want those). This can be done using either a project-wide `minimum-stability` value in `composer.json` or using "stability flags" in version constraints. Read more on the [schema page](04-schema.md#minimum-stability).
+
+## Writing Basic Version Constraints
+
+Now that you have an idea of how Composer sees versions, let's talk about how
+to specify version constraints for your project dependencies.
 
 ### Exact
 
@@ -87,7 +170,7 @@ library code.
 
 Example: `^1.2.3`
 
-## Stability
+## Stability Constraints
 
 If you are using a constraint that does not explicitly define a stability,
 Composer will default internally to `-dev` or `-stable`, depending on the
@@ -113,8 +196,9 @@ Examples:
 To allow various stabilities without enforcing them at the constraint level
 however, you may use [stability-flags](../04-schema.md#package-links) like
 `@<stability>` (e.g. `@dev`) to let composer know that a given package
-can be installed in a different stability than your default
-[minimum-stability](../04-schema.md#minimum-stability) setting.
+can be installed in a different stability than your default minimum-stability
+setting. All available stability flags are listed on the minimum-stability
+section of the [schema page](../04-schema.md#minimum-stability).
 
 ## Test version constraints