Skip to content

Properly support unnamed crate sourcesΒ #8901

@Diggsey

Description

@Diggsey

Describe the problem you are trying to solve
There are a couple of places in TOML where we need to identify a crate source:

  • [patch] in Cargo.toml
  • [source] in cargo config

The problem is that some crates come from sources that do not have a name:

  • Local crates
  • Git repos

For the latter case, cargo has introduced a special syntax in order to allow patching:

[patch."<url>"]

However, this syntax does not contain all the information necessary to identify the source: it will just match all sources that use the same URL, and this results in bugs like #7670 and #5478. It is also just confusing for users because it doesn't appear as though cargo has all the information needed to figure out which crate to patch.

Describe the solution you'd like
I would like to introduce a standard way to identify unnamed sources that can be applied consistently to both [patch] and [source] keys, and is obvious how to extend to cope with new ways of specifying dependencies in the future (for example if support for other VCSs is added).

The existing [patch."<url>"] syntax would be soft-deprecated in the same way as [replace]. The [patch.<name>] syntax would still be the correct way to patch named sources.

Unnamed dependencies are identified using an array of tables:

[[patch."*"]]
_source = { git = "<url>", branch = "master" }
foo = { path = "../foo" }
bar = { path = "../bar" }

[[patch."*"]]
_source = { path = "../baz" }
baz = { git = "<url>" }

The same pattern could be used for source replacement using [[source."*"]].

The following two examples are logically equivalent:

[[patch."*"]]
_source = { registry = "example" }
foo = { path = "../foo" }
[patch.example]
foo = { path = "../foo" }

Notes

I think we could also improve the way this is documented: I always end up having to look up the syntax for patching git dependencies, because there's no way to extrapolate from a set of rules you can easily remember.

We would define a crate source identifier to be an object with some subset of the following keys:

source_id = {
    # Keys for anonymous sources
    git = "...",
    branch = "...",
    rev = "...",
    path = "...",
    # Key for a named source
    registry = "..."
}

We define a dependency specification to essentially extend a source_id object with some additional keys:

  • version
  • optional
  • features
  • etc.

This way it's easy to figure out how to patch a dependency: you just need to take the dependency object, remove all the keys that are not part of a source_id, and you have the syntax for patching that dependency.

Bikeshedding

The _source key could potentially conflict with a crate name. Either that name or some other name (tbd) would need to be reserved or we could a name that cannot conflict like "@source" with the caveat that you'd then need to quote it.

The "*" could also be substituted for some other key like "unnamed" or something.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-patchArea: [patch] table overrideC-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`S-triageStatus: This issue is waiting on initial triage.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions