# Package ID Specifications

## Package ID specifications

Subcommands of Cargo frequently need to refer to a particular package within a
dependency graph for various operations like updating, cleaning, building, etc.
To solve this problem, Cargo supports *Package ID Specifications*. A specification
is a string which is used to uniquely refer to one package within a graph of
packages.

The specification may be fully qualified, such as
`registry+https://github.com/rust-lang/crates.io-index#regex@1.4.3` or it may be
abbreviated, such as `regex`. The abbreviated form may be used as long as it
uniquely identifies a single package in the dependency graph. If there is
ambiguity, additional qualifiers can be added to make it unique. For example,
if there are two versions of the `regex` package in the graph, then it can be
qualified with a version to make it unique, such as `regex@1.4.3`.

Package ID specifications output by cargo, for example in [cargo metadata](../commands/cargo-metadata.md) output, are fully qualified.

### Specification grammar

The formal grammar for a Package Id Specification is:

```notrust
spec := pkgname |
        [ kind "+" ] proto "://" hostname-and-path [ "?" query] [ "#" ( pkgname | semver ) ]
query = ( "branch" | "tag" | "rev" ) "=" ref
pkgname := name [ ("@" | ":" ) semver ]
semver := digits [ "." digits [ "." digits [ "-" prerelease ] [ "+" build ]]]

kind = "registry" | "git" | "path"
proto := "http" | "git" | "file" | ...
```

Here, brackets indicate that the contents are optional.

The URL form can be used for git dependencies, or to differentiate packages
that come from different sources such as different registries.

### Example specifications

The following are references to the `regex` package on `crates.io`:

| Spec                                                              | Name    | Version |
|:------------------------------------------------------------------|:-------:|:-------:|
| `regex`                                                           | `regex` | `*`     |
| `regex@1.4`                                                       | `regex` | `1.4.*` |
| `regex@1.4.3`                                                     | `regex` | `1.4.3` |
| `https://github.com/rust-lang/crates.io-index#regex`              | `regex` | `*`     |
| `https://github.com/rust-lang/crates.io-index#regex@1.4.3`        | `regex` | `1.4.3` |
| `registry+https://github.com/rust-lang/crates.io-index#regex@1.4.3` | `regex` | `1.4.3` |

The following are some examples of specs for several different git dependencies:

| Spec                                                       | Name             | Version  |
|:-----------------------------------------------------------|:----------------:|:--------:|
| `https://github.com/rust-lang/cargo#0.52.0`                | `cargo`          | `0.52.0` |
| `https://github.com/rust-lang/cargo#cargo-platform@0.1.2`  | <nobr>`cargo-platform`</nobr> | `0.1.2`  |
| `ssh://git@github.com/rust-lang/regex.git#regex@1.4.3`     | `regex`          | `1.4.3`  |
| `git+ssh://git@github.com/rust-lang/regex.git#regex@1.4.3` | `regex`          | `1.4.3`  |
| `git+ssh://git@github.com/rust-lang/regex.git?branch=dev#regex@1.4.3` | `regex`          | `1.4.3`  |

Local packages on the filesystem can use `file://` URLs to reference them:

| Spec                                        | Name  | Version |
|:--------------------------------------------|:-----:|:-------:|
| `file:///path/to/my/project/foo`            | `foo` | `*`     |
| `file:///path/to/my/project/foo#1.1.8`      | `foo` | `1.1.8` |
| `path+file:///path/to/my/project/foo#1.1.8` | `foo` | `1.1.8` |

### Brevity of specifications

The goal of this is to enable both succinct and exhaustive syntaxes for
referring to packages in a dependency graph. Ambiguous references may refer to
one or more packages. Most commands generate an error if more than one package
could be referred to with the same specification.
