Skip to content

Commit 4e01a4f

Browse files
committed
Add RFC source_replacement_ambiguity
1 parent e9e8ac8 commit 4e01a4f

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
- Feature Name: source_replacement_ambiguity
2+
- Start Date: 2022-07-05
3+
- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000)
4+
- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000)
5+
6+
# Summary
7+
[summary]: #summary
8+
9+
When Cargo is performing an API operation (`yank`/`login`/`publish`/etc.) to a source-replaced `crates-io`, require the user to pass `--registry <NAME>` to specify exactly which registry to use. Additionally, ensure that the token for `crates-io` is never sent to a replacement registry.
10+
11+
# Motivation
12+
[motivation]: #motivation
13+
14+
There are multiple issues that this RFC attempts to resolve around source-replacement.
15+
16+
* When Cargo is performing an API operation, source replacement is only respected for `crates-io`, not alternative registries. This is inconsistent.
17+
* The [error message](https://github.com/rust-lang/cargo/issues/6722) for attempting to publish to a replaced crates-io is confusing, and there is no workaround other than temporarily removing the source replacement configuration.
18+
* When performing an API operation other than `publish` with a replaced `crates-io` source, the `crates-io` credentials are sent to the replacement registry's API. This is a security risk.
19+
* It's unclear which credentials should be used when fetching a source-replaced authenticated alternate registry (RFC 3139).
20+
21+
# Guide-level explanation
22+
[guide-level-explanation]: #guide-level-explanation
23+
24+
When the `crates-io` source is replaced, the user needs to specify `--registry <NAME>` when running an API operation to disambiguate which registry to use. Otherwise, `cargo` will issue an error.
25+
26+
`cargo` only sends the token associated with a given registry to that registry and no other (even if source replacement is configured).
27+
28+
When replacing a source with a registry, the `replace-with` key can reference the name of a registry in the `[registries]` table.
29+
30+
## Example scenarios
31+
32+
### Local source replacement (vendoring)
33+
A repository has a local `.cargo/config` that vendors all dependencies from crates.io. Fetching and building within the repository would work as expected with the vendored sources.
34+
35+
If the user decides to publish the crate, `cargo publish --registry crates-io` will ignore the source-replacement and publish to crates.io.
36+
37+
38+
### `crates-io` mirror registry
39+
A server has been set up that provides a complete mirror of crates.io. The user has configured a `~/.cargo/config` that points to the mirror registry in the `[registries]` table. The mirror requires authentication to access (based on RFC 3139).
40+
41+
The user can log in to the mirror using `cargo login --registry mirror`. Fetching and building use the mirror.
42+
43+
The user decides to publish the crate to crates.io, and does `cargo login --registry crates-io` to log in to crates.io. Source replacement is ignored, and the token is saved.
44+
45+
Next, the user runs `cargo publish --registry crates-io` to publish to crates.io. Cargo ignores source replacement when building and publishing the crate to crates.io.
46+
47+
# Reference-level explanation
48+
[reference-level-explanation]: #reference-level-explanation
49+
50+
### Change 1: respect `--registry`
51+
When running an API operation (`login`, `logout`, `owner`, `publish`, `search`, `yank`), Cargo always uses the registry specified by `--registry <NAME>`, and never a source-replacement.
52+
53+
### Change 2: error for replaced crates-io
54+
When running an API operation (as defined above) and ALL of the following are true:
55+
* `crates-io` has been replaced by a remote-registry source.
56+
* command line argument `--registry <NAME>` is not present.
57+
* command line argument `--index <URL>` is not present.
58+
* `Cargo.toml` manifest key `publish = <NAME>` is not set (only applies for publishing).
59+
60+
`cargo` issues an error:
61+
```
62+
error: crates-io is replaced: use `--registry replacement` or `--registry crates-io`
63+
```
64+
65+
### Change 3: credentials are only sent to the same registry
66+
If the `crates-io` source is replaced with another remote registry, the credentials for
67+
`crates-io` are never sent to the replacement registry.
68+
69+
### Change 4: `[source]` table can reference `[registries]` table
70+
The `replace-with` key in the `[source]` table can reference a registry defined in the `[registries]` table.
71+
72+
For example, the following configuration would be valid:
73+
74+
```
75+
[source.crates-io]
76+
replace-with = "my-registry"
77+
78+
[registry.my-registry]
79+
index = "https://my-registry-index/"
80+
```
81+
82+
This is necessary to allow the `--registry <NAME>` command-line argument to work with source-replaced registries. It also allows additional configuration (such as a token) to be specified for a source-replacement registry without duplicating configuration between `[registry]` and `[source]` tables.
83+
84+
# Drawbacks
85+
[drawbacks]: #drawbacks
86+
87+
Some behavior is changed, especially around when credentials are sent, which could break some workflows.
88+
89+
# Rationale and alternatives
90+
[rationale-and-alternatives]: #rationale-and-alternatives
91+
92+
93+
## Alternative: don't use source replacement for API operations
94+
When doing an API operation with a replaced `crates-io`, `cargo` would ignore source replacement without additional arguments. This is how alternative registries currently work.
95+
96+
If the user wants to use the replacement, they could pass `--registry <NAME>`, but would not be required to do so.
97+
98+
A new option `--respect-source-config` could be added to make cargo follow the source replacement for API operations (similar to what we already have for `cargo vendor`).
99+
100+
This may be too confusing for users since it silently changes behavior. The RFC proposes a solution that requires the user to be explicit about which registry to use in the ambiguous situation (crates-io replacement).
101+
102+
103+
# Prior art
104+
[prior-art]: #prior-art
105+
106+
Other package managers don't seem to have a source replacement feature.
107+
108+
# Unresolved questions
109+
[unresolved-questions]: #unresolved-questions
110+
111+
Should the `--registry <NAME>` command line argument be allowed to reference the name of a `source` from the `[source]` table as well? This makes it more flexible, but adds potentially unnecessary complexity.
112+
113+
Cargo's tests rely on the ability to replace the crates.io source and have the crates.io credentials go to the replaced source. We need a way for these tests to continue working.
114+
115+
# Future possibilities
116+
[future-possibilities]: #future-possibilities
117+
118+
Can't think of anything.

0 commit comments

Comments
 (0)