# \[Pre-RFC\] \[Cargo\] Support vendored/local-directory alternate registries

**URL:** <https://internals.rust-lang.org/t/pre-rfc-cargo-support-vendored-local-directory-alternate-registries/10641>\
**Category:** internals\
**Created:** [July 30, 2019, 6:04pm UTC](https://internals.rust-lang.org/t/pre-rfc-cargo-support-vendored-local-directory-alternate-registries/10641 "2019-07-30T18:04:05Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![bdonlan](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@bdonlan](https://internals.rust-lang.org/u/bdonlan)\
**Post date:** [July 30, 2019, 6:04pm UTC](https://internals.rust-lang.org/t/pre-rfc-cargo-support-vendored-local-directory-alternate-registries/10641/1 "2019-07-30T18:04:05Z")

</div>

[requested to file a RFC in [https://github.com/rust-lang/cargo/pull/7188](https://github.com/rust-lang/cargo/pull/7188), so opening a pre-RFC thread here first]

Cargo supports alternate registries, which allow for packages from multiple sources (under independent namespaces) to be included in the same project. Currently, these work by specifying the URL of a git repository, which includes a configuration file naming a download server. This works well on many desktop use cases, but when integrating with existing build systems things can get more complex - in particular, they may have their own ideas about build reproducibility which do not allow access to external servers, which control which source or crate versions are visible to a build, and have their own version management rules which do not play well with Cargo.lock files.

With [crates.io](http://crates.io), these problems can be dealt with by using source replacement; a pre-build script can examine the Cargo.toml and/or Cargo.lock files, resolve them based on a frozen snapshot of [crates.io](http://crates.io), and download them via the external build orchestration framework. However, it does not appear possible to do this with alternate registries - as far as I can tell, they require a HTTP server for the actual download of the crates, at a minimum, and do not support source replacement entries.

While it would be possible to implement source replacement rules for alternate registries, this is a bit strange - we'd have to specify a bogus URL in the [registries] section, only to replace it with a local-directory source replacement rule. Therefore, I propose simply allowing the alternate registry to be directly specified using a local-directory statement in the relevant [registries] section.

---

<div class="post-metadata">

**Author:** ![ehuss](https://avatars.discourse-cdn.com/v4/letter/e/9de0a6/32.png) [@ehuss](https://internals.rust-lang.org/u/ehuss)\
**Post date:** [July 30, 2019, 6:42pm UTC](https://internals.rust-lang.org/t/pre-rfc-cargo-support-vendored-local-directory-alternate-registries/10641/2 "2019-07-30T18:42:46Z")

</div>

I'm having a little trouble understanding your use case. A concrete example would be helpful.

> [@bdonlan](#):
>
> as far as I can tell, they require a HTTP server for the actual download of the crates

They support `file://` urls to download locally.

> [@bdonlan](#):
>
> Therefore, I propose simply allowing the alternate registry to be directly specified using a local-directory statement in the relevant [registries] section.

A path can be specified like this:

```rust
[registries]
my-registry = { index = "file:///path/to/index" }

```

There are also other methods, like [local registry sources](https://doc.rust-lang.org/nightly/cargo/reference/source-replacement.html#local-registry-sources) that may be applicable.

---

<div class="post-metadata">

**Author:** ![bdonlan](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@bdonlan](https://internals.rust-lang.org/u/bdonlan)\
**Post date:** [July 30, 2019, 6:53pm UTC](https://internals.rust-lang.org/t/pre-rfc-cargo-support-vendored-local-directory-alternate-registries/10641/3 "2019-07-30T18:53:07Z")

</div>

Aha! I didn't realize `file://` URLs were supported (I might send a doc PR in that case instead). The tree layout is a bit strange for a filesystem tree, and it's inconvenient to have to construct a git repository here, but it'll work to unblock us.

It's hard to provide a concrete example, since this is all about integration with an internal build system, but essentially we want to build an alt-registry of our first-party crates, and we can't reach out to an external server. Today, we merge these into a vendored snapshot of the [crates.io](http://crates.io) tree, but this has a number of unfortunate side effects (e.g. cargo outdated doesn't work properly as our tooling subsets the [crates.io](http://crates.io) tree to just the versions we're using).

As for local registry sources, it seems that they currently only work for crates-io - the source replacement infrastructure is [hardcoded to only be queried for crates.io](https://github.com/rust-lang/cargo/blob/master/src/cargo/ops/registry.rs#L700) (with the exception of some handling on `cargo install`), and the alt-registry config parsing logic today doesn't understand the local-directory key in a `registries` entry (this is what this pre-RFC proposes to add support for).

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [July 30, 2019, 9:09pm UTC](https://internals.rust-lang.org/t/pre-rfc-cargo-support-vendored-local-directory-alternate-registries/10641/4 "2019-07-30T21:09:11Z")

</div>

The directory registry mechanism _should_ work as a replacement for any registry. If it doesn't, that's a bug and should be fixed.

---

<div class="post-metadata">

**Author:** ![bdonlan](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@bdonlan](https://internals.rust-lang.org/u/bdonlan)\
**Post date:** [July 30, 2019, 9:41pm UTC](https://internals.rust-lang.org/t/pre-rfc-cargo-support-vendored-local-directory-alternate-registries/10641/5 "2019-07-30T21:41:36Z")

</div>

If we treat this as a bug, do we expect that the registry name should be used to locate the relevant entry in the sources map, or should the registry index URL be used? And if these are inconsistent, what happens?

e.g.

```rust
[registries]
[registries.foo]
index = "http://this.is.a.bogus.url"

[sources]
[sources.foo]
registry = "http://some.other.url"
replace-with = "foo-replacement"

[sources.foo-replacement]
local-registry = "/foo"

[sources.bar]
registry = "http://this.is.a.bogus.url"
replace-with = "bar-replacement"

[sources.bar-replacement]
local-registry = "/bar"

```

Do we expect the alternate registry `foo` to be mapped to the local-directory `/foo` or `/bar`?

Edit: I'll also point out it's a bit awkward to explicitly write an external URL in the same configuration file where you override that external URL to point somewhere else.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [October 28, 2019, 9:49pm UTC](https://internals.rust-lang.org/t/pre-rfc-cargo-support-vendored-local-directory-alternate-registries/10641/6 "2019-10-28T21:49:52Z")

</div>

Closed on October 28, 2019, 9:49pm UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
