currently there is no way in replace or patch to specify a _different_ version than the original dependency.
with replace:
[replace]
"openssl:0.9.24" = {git = "https://github.com/sfackler/rust-openssl.git"
``
error: no matching package for overridehttps://github.com/rust-lang/crates.io-index#openssl:0.9.24` found
location searched: https://github.com/sfackler/rust-openssl.git
version required: = 0.9.24
with patch:
```toml
[patch.crates-io]
openssl = {git = "https://github.com/sfackler/rust-openssl.git"}
is simply ignored.
error: failed to run custom build command for `openssl v0.9.24`
With the complexity of packages growing, it is sometimes nessesary to override versions in Cargo.toml since upstream cant update the version yet if another dependency hasnt updated.
You probably need to update your lockfile file for patch to work:
https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#testing-a-bugfix
Next up we need to ensure that our lock file is updated to use this new version of uuid so our project uses the locally checked out copy instead of one from crates.io. The way [patch] works is that it'll load the dependency at ../path/to/uuid and then whenever crates.io is queried for versions of uuid it'll also return the local version.
This means that the version number of the local checkout is significant and will affect whether the patch is used. Our manifest declared uuid = "1.0" which means we'll only resolve to >= 1.0.0, < 2.0.0, and Cargo's greedy resolution algorithm also means that we'll resolve to the maximum version within that range. Typically this doesn't matter as the version of the git repository will already be greater or match the maximum version published on crates.io, but it's important to keep this in mind!
Note thar git repository contains openssl 0.10, while you seem to replace 0.9. That means that you probably need to update Cargo.toml as well, because 0.10 and 0.9 are not semver compatible.
thanks, i'm aware of this. the lockfile is deleted on every try.
that is correct, i was asking for a feature that allows overriding 0.9 with 0.10 in Cargo.toml of my project rather than in the actual project that depends on 0.9. intentionally ignoring semver compatibility
i was asking for a feature that allows overriding 0.9 with 0.10 in Cargo.toml of my project rather than in the actual project that depends on 0.9
Oh, sorry, I've misunderstood your intentions! Yes, I think currently it is impossible to replace dependency specifications: that is, if a crate depends on foo 1.0.0, you can't make it to depend on foo 2.0.0 instead (this is a non-trivial task, because 1.0 and 2.0 are semver-incompatible).
However, it is possible to override the dependency itself. My understanding is that your project depends on library foo, which depends on openssl 0.9, and you want foo to use openssl 0.10. Would it be possible to fork foo, modify it's Cargo.toml to say openssl 0.10, and then patch foo instead of openssl?
yep, doing that now, this helps me :)
but i was thinking there should be a more generic solution for this in cargo
Yeah, such extension is possible in theory!
However, the current "fork upstream and edit Cargo.toml" has two benefits:
i'd really like to see this too, imo it is a _huge_ usability issue for both patch and replace, and it seems to me that without the ability to override version specs neither of them actually work for all but the simplest scenario (as is described in the docs) :-/
The fork-and-update approach is nice for the case when you're just a version behind, but, practically there are a bunch of situations that are _not_ that and in my experience you often end up having to fork a pile of transitive dependencies to edit their dependency versions to test a patch, at which point patch and replace don't actually offer any utility and you may as well just change the dependency key directly.
As a simple example, for packages A, B, C and D, where:
To test an unpublished local change to D (or if D publishes a 0.3.0 release), there's no way to patch up to that from A without forking and altering both B and C.
This problem is in no way limited to only two intermediate dependencies, and as one of the maintainers of a reasonably widely used D-like package, this makes testing patches and changes a huge effort.
The documentation 1 2 3 also only mentions versions are important in one of the three places, and does not cover transitive dependencies at all, so it'd be neat to clear that up with whatever the outcome of this is.
Any chance of getting this implemented? Overriding dependencies manually, even if there is a potential semver violation, is an important task in many complex projects. Unfortunately, the real world is not ideal, and it is possible to have situations where dependency versions in upstream projects just don't match, and there is a need to set things manually.
Right now, I can't do anything to fix a dependency issue in my project without manually forking some repositories and doing fixes there, and then using the [patch] section in my manifest.
It does not seem at the first glance to be a hard thing to do from the technical standpoint: just allow specifying dependency version overrides in the manifest, e.g. like this:
[[version-overrides.some-crate]]
version = "1.2.3" # override dependencies only for some-crate=1.2.3 but not e.g. some-crate=2.3.1
[version-overrides.some-crate.dependencies]
dependency = "3.2.1" # overridden version
This configuration would work as a simple replace in the manifest of the overridden crate, and won't do anything else. So in the example above, Cargo would behave as if the manifest of some-crate=1.2.3 contained dependency = "3.2.1" instead of whatever dependency is defined there by default.
This does go against the idea of semantic versions, but as I said, sometimes there are things which have to be done, and it is great if tools give the developer a power to do them.
Also, it's not currently possible to patch multiple versions of the same dependency in your project. Example dependency tree from the project-level Cargo.toml:
A = 2.0
B = 1.0
A = 2.0
C = 1.0
A = 1.0
A has a bug that you need to patch. You can only specify a single version because the patch is unversioned:
[patch.crates-io]
A = { git = "https://github.com/my/repo.git", branch = "fix-2.0" }
As long as C is the only user of [email protected] you can just patch it (or as previously requested, override the constraint) to use the same version, but this doesn't scale if the dependency is widely used (which is somewhat likely due to rust's small stdlib).
Isn't this exactly this case from the doc?
https://doc.rust-lang.org/cargo/reference/manifest.html#using-patch-with-multiple-versions
On Fri, 21 Feb 2020 at 23:54, Cam Cope notifications@github.com wrote:
Also, it's not currently possible to patch multiple versions of the same
dependency in your project. Example dependency tree from the project-level
Cargo.toml:A = 2.0
B = 1.0
A = 2.0
C = 1.0
A = 1.0A has a bug that you need to patch. You can only specify a single version
because the patch is unversioned:[patch.crates-io]
A = { git = "https://github.com/my/repo.git", branch = "fix-0.2" }As long as C is the only user of [email protected] you can just patch it (or as
previously requested, override the constraint) to use the same version, but
this doesn't scale if the dependency is widely used (which is somewhat
likely due to rust's small stdlib).—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/rust-lang/cargo/issues/5640?email_source=notifications&email_token=AANB3M6OS4TLXQVUS3WDYETREBLRFA5CNFSM4FFVLY5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEMULOZA#issuecomment-589870948,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AANB3M22JZBMWTNCDLIZDFLREBLRFANCNFSM4FFVLY5A
.
Ah yes, I missed the note underneath about the name being ignored. That format is kind of confusing though, I was thinking about adding a config variant like:
package_name = [
{ version = "1.0", git = "..." },
{ version = "2.0", git = "..." },
]
Is there a reason it wasn't done that way originally?
Here's a real world example where this feature would be useful: sccache depends on rouille, which hasn't been updated since 2019. rouille depends on tiny_http 0.6. This setup has a bug that surfaces in sccache, and that was fixed in tiny_http 0.7. Considering the lack of activity on the rouille repo, I don't see a bump of its Cargo.toml to use tiny_http 0.7 happening. It seems the only workable solution today is to either move away from rouille (lot of work), or publish a rouille fork to crates.io. (I tried publishing a fork of tiny_http and to use a patch with a package pointing to the fork, but that doesn't seem to work)
If you are a maintained project and your dependency has not been updated, then a fork of the dependency seams like the honest way to do things.
Most helpful comment
Any chance of getting this implemented? Overriding dependencies manually, even if there is a potential semver violation, is an important task in many complex projects. Unfortunately, the real world is not ideal, and it is possible to have situations where dependency versions in upstream projects just don't match, and there is a need to set things manually.
Right now, I can't do anything to fix a dependency issue in my project without manually forking some repositories and doing fixes there, and then using the
[patch]section in my manifest.It does not seem at the first glance to be a hard thing to do from the technical standpoint: just allow specifying dependency version overrides in the manifest, e.g. like this:
This configuration would work as a simple replace in the manifest of the overridden crate, and won't do anything else. So in the example above, Cargo would behave as if the manifest of
some-crate=1.2.3containeddependency = "3.2.1"instead of whatever dependency is defined there by default.This does go against the idea of semantic versions, but as I said, sometimes there are things which have to be done, and it is great if tools give the developer a power to do them.