Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: Edits for git/path dependency sections #13341

Merged
merged 2 commits into from
Mar 5, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 121 additions & 54 deletions src/doc/src/reference/specifying-dependencies.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ versions before 1.0.0. While SemVer says there is no compatibility before
and `x > 0`.

It is possible to further tweak the logic for selecting compatible versions
using special operators, though it shouldn't be necessary most of the time.
using special operators as described in the [Version requirement syntax](#version-requirement-syntax) section.

Use the default version requirement strategy, e.g. `log = "1.2.3"` where possible to maximize compatibility.
rimutaka marked this conversation as resolved.
Show resolved Hide resolved

## Version requirement syntax

Expand Down Expand Up @@ -158,16 +160,17 @@ separated with a comma, e.g., `>= 1.2, < 1.5`.

## Specifying dependencies from other registries

To specify a dependency from a registry other than [crates.io], first the
registry must be configured in a `.cargo/config.toml` file. See the [registries
documentation] for more information. In the dependency, set the `registry` key
to the name of the registry to use.
To specify a dependency from a registry other than [crates.io] set the `registry` key
to the name of the registry to use:

```toml
[dependencies]
some-crate = { version = "1.0", registry = "my-registry" }
```

where `my-registry` is the registry name configured in `.cargo/config.toml` file.
See the [registries documentation] for more information.

> **Note**: [crates.io] does not allow packages to be published with
> dependencies on code published outside of [crates.io].

Expand All @@ -183,69 +186,113 @@ you need to specify is the location of the repository with the `git` key:
regex = { git = "https://github.com/rust-lang/regex.git" }
```

Cargo will fetch the `git` repository at this location then look for a
`Cargo.toml` for the requested crate anywhere inside the `git` repository
(not necessarily at the root --- for example, specifying a member crate name
of a workspace and setting `git` to the repository containing the workspace).
Cargo fetches the `git` repository at that location and traverses the file tree to find
`Cargo.toml` file for the requested crate anywhere inside the `git` repository.
For example, `regex-lite` and `regex-syntax` are members of `rust-lang/regex` repo
and can be referred to by the repo's root URL (`https://github.com/rust-lang/regex.git`)
regardless of where in the file tree they reside.
rimutaka marked this conversation as resolved.
Show resolved Hide resolved

```toml
regex-lite = { git = "https://github.com/rust-lang/regex.git" }
weihanglo marked this conversation as resolved.
Show resolved Hide resolved
regex-syntax = { git = "https://github.com/rust-lang/regex.git" }
```

The above rule does not apply to [`path` dependencies](#specifying-path-dependencies).

Since we haven’t specified any other information, Cargo assumes that
we intend to use the latest commit on the default branch to build
our package, which may not necessarily be the main branch.
You can combine the `git` key with the `rev`, `tag`, or `branch` keys to
specify something else. Here's an example of specifying that you want to use
the latest commit on a branch named `next`:
### Choice of commit

Cargo assumes that we intend to use the latest commit on the default branch to build
our package if we only specify the repo URL, as in the examples above.

You can combine the `git` key with the `rev`, `tag`, or `branch` keys to be more specific about
rimutaka marked this conversation as resolved.
Show resolved Hide resolved
which commit to use. Here's an example of using the latest commit on a branch named `next`:

```toml
[dependencies]
regex = { git = "https://github.com/rust-lang/regex.git", branch = "next" }
```

Anything that is not a branch or tag falls under `rev`. This can be a commit
Anything that is not a branch or a tag falls under `rev` key. This can be a commit
hash like `rev = "4c59b707"`, or a named reference exposed by the remote
repository such as `rev = "refs/pull/493/head"`. What references are available
varies by where the repo is hosted; GitHub in particular exposes a reference to
the most recent commit of every pull request as shown, but other git hosts often
provide something equivalent, possibly under a different naming scheme.

Once a `git` dependency has been added, Cargo will lock that dependency to the
latest commit at the time. New commits will not be pulled down automatically
once the lock is in place. However, they can be pulled down manually with
`cargo update`.

See [Git Authentication] for help with git authentication for private repos.

> **Note**: Neither the `git` key nor the `path` key changes the meaning of the
> `version` key: the `version` key always implies that the package is available
> in a registry. `version`, `git`, and `path` keys are considered [separate
> locations](#multiple-locations) for resolving the dependency.
>
> When the dependency is retrieved from `git`, the `version` key will _not_
> affect which commit is used, but the version information in the dependency's
> `Cargo.toml` file will still be validated against the `version` requirement.
repository such as `rev = "refs/pull/493/head"`.

What references are available for the `rev` key varies by where the repo is hosted.
GitHub exposes a reference to the most recent commit of every pull request as in the example above.
Other git hosts may provide something equivalent under a different naming scheme.

**More `git` dependency examples:**

```toml
# .git suffix can be omitted if the host accepts such URLs - both examples work the same
regex = { git = "https://github.com/rust-lang/regex" }
regex = { git = "https://github.com/rust-lang/regex.git" }

# a commit with a particular tag
regex = { git = "https://github.com/rust-lang/regex.git", tag = "1.10.3" }

# a commit by its SHA1 hash
regex = { git = "https://github.com/rust-lang/regex.git", rev = "0c0990399270277832fbb5b91a1fa118e6f63dba" }

# HEAD commit of PR 493
regex = { git = "https://github.com/rust-lang/regex.git", rev = "refs/pull/493/head" }

# INVALID EXAMPLES

# specifying the commit after # ignores the commit ID and generates a warning
regex = { git = "https://github.com/rust-lang/regex.git#4c59b70" }

# git and path cannot be used at the same time
regex = { git = "https://github.com/rust-lang/regex.git#4c59b70", path = "../regex" }
```

Cargo locks the commits of `git` dependencies in `Cargo.lock` file at the time of their addition
and checks for updates only when you run `cargo update` command.

### The role of the `version` key

The `version` key always implies that the package is available in a registry,
regardless of the presence of `git` or `path` keys.

The `version` key does _not_ affect which commit is used when Cargo retrieves the `git` dependency,
but Cargo checks the version information in the dependency's `Cargo.toml` file
against the `version` key and raises an error if the check fails.

In this example, Cargo retrieves the HEAD commit of the branch called `next` from Git and checks if the crate's version
is compatible with `version = "1.10.3"`:

```toml
[dependencies]
regex = { version = "1.10.3", git = "https://github.com/rust-lang/regex.git", branch = "next" }
```

`version`, `git`, and `path` keys are considered separate locations for resolving the dependency.
See [Multiple locations](#multiple-locations) section below for detailed explanations.

> **Note**: [crates.io] does not allow packages to be published with
> dependencies on code published outside of [crates.io] itself
> ([dev-dependencies] are ignored). See the [Multiple
> locations](#multiple-locations) section for a fallback alternative for `git`
> and `path` dependencies.

[Git Authentication]: ../appendix/git-authentication.md
### Accessing private Git repositories

See [Git Authentication](../appendix/git-authentication.md) for help with Git authentication for private repos.

## Specifying path dependencies

Over time, our `hello_world` package from [the guide](../guide/index.md) has
grown significantly in size! It’s gotten to the point that we probably want to
split out a separate crate for others to use. To do this Cargo supports **path
dependencies** which are typically sub-crates that live within one repository.
Let’s start off by making a new crate inside of our `hello_world` package:
Let’s start by making a new crate inside of our `hello_world` package:

```console
# inside of hello_world/
$ cargo new hello_utils
```

This will create a new folder `hello_utils` inside of which a `Cargo.toml` and
`src` folder are ready to be configured. In order to tell Cargo about this, open
`src` folder are ready to be configured. To tell Cargo about this, open
up `hello_world/Cargo.toml` and add `hello_utils` to your dependencies:

```toml
Expand All @@ -254,30 +301,50 @@ hello_utils = { path = "hello_utils" }
```

This tells Cargo that we depend on a crate called `hello_utils` which is found
in the `hello_utils` folder (relative to the `Cargo.toml` it’s written in).
in the `hello_utils` folder, relative to the `Cargo.toml` file it’s written in.

The next `cargo build` will automatically build `hello_utils` and
all of its dependencies.

And that’s it! The next `cargo build` will automatically build `hello_utils` and
all of its own dependencies, and others can also start using the crate as well.
However, crates that use dependencies specified with only a path are not
permitted on [crates.io]. If we wanted to publish our `hello_world` crate, we
would need to publish a version of `hello_utils` to [crates.io]
and specify its version in the dependencies line as well:
### No local path traversal

The local paths must point to the exact folder with the dependency's `Cargo.toml`.
Unlike with `git` dependencies, Cargo does not traverse local paths.
For example, if `regex-lite` and `regex-syntax` are members of a
locally cloned `rust-lang/regex` repo, they have to be referred to by the full path:

```toml
# git key accepts the repo root URL and Cargo traverses the tree to find the crate
[dependencies]
regex-lite = { git = "https://github.com/rust-lang/regex.git" }
regex-syntax = { git = "https://github.com/rust-lang/regex.git" }

# path key requires the member name to be included in the local path
[dependencies]
regex-lite = { path = "../regex/regex-lite" }
regex-syntax = { path = "../regex/regex-syntax" }
```

### Local paths in published crates

Crates that use dependencies specified with only a path are not
permitted on [crates.io].

If we wanted to publish our `hello_world` crate,
we would need to publish a version of `hello_utils` to [crates.io] as a separate crate
and specify its version in the dependencies line of `hello_world`:

```toml
[dependencies]
hello_utils = { path = "hello_utils", version = "0.1.0" }
```

> **Note**: Neither the `git` key nor the `path` key changes the meaning of the
> `version` key: the `version` key always implies that the package is available
> in a registry. `version`, `git`, and `path` keys are considered [separate
> locations](#multiple-locations) for resolving the dependency.
The use of `path` and `version` keys together is explained in the [Multiple locations](#multiple-locations) section.

> **Note**: [crates.io] does not allow packages to be published with
> dependencies on code published outside of [crates.io] itself
> ([dev-dependencies] are ignored). See the [Multiple
> locations](#multiple-locations) section for a fallback alternative for `git`
> and `path` dependencies.
> dependencies on code outside of [crates.io], except for [dev-dependencies].
> See the [Multiple locations](#multiple-locations) section
> for a fallback alternative for `git` and `path` dependencies.

## Multiple locations

Expand Down