There's a [patch] section in Cargo.toml which lets you temporarily override a crates.io dependency with a local version. Check out the docs for details on how you use it.
I have not tried it, but I believe that, as Michael says, [patch] is the way to go. It is my understanding, though, that you would still have to manually add-remove (or comment-uncomment) the patch section if you want to switch between the patched and repository version of the crate. I would suggest to use a cargo workspace. In that case you would have a folder with your crate inside of another folder with the workspace, which contains the virtual manifest. The [patch] section is recognized only in the virtual manifest, and it overrides dependency resolution for all crates within the workspace. The crate itself would declare its dependencies as normal. Once you want to publish it, you would do it using the --package option of cargo publish (I don't know whether one could publish the entire workspace at once, probably not).
For example, the hello library is from crates.io, I use it in my main package. I want to make some changes to hello, so I git clone it locally, and use the local copy. After the online version updated, I need to change ./main/Cargo.toml to use the online version again.
How can I do it in the ./Cargo.toml in top directory of the workspace, without changing ./main/Cargo.toml repeatedly.
# 1. use the online version
# ./main/Cargo.toml
[dependencies]
hello = "0.1.0"
# 2. use local copy
# ./main/Cargo.toml
[dependencies]
hello = { path = "../hello" }
# 3. use online version again
# ./main/Cargo.toml
[dependencies]
hello = "0.1.0"
$ pwd
/Users/rust/rust_work
$
$ find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
.
|____Cargo.toml
|____hello
| |____Cargo.toml
| |____src
| | |____lib.rs
|____main
| |____Cargo.toml
| |____src
| | |____main.rs
$
$
$ for f in `find . -name "*.*" -type f`; do echo "## $f"; echo; cat $f; done
## ./Cargo.toml
[workspace]
members = [
"main",
"hello",
]
## ./hello/Cargo.toml
[package]
name = "hello"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
//## ./hello/src/lib.rs
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
}
}
pub fn hello(){
println!("hello")
}
## ./main/Cargo.toml
[package]
name = "main"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
hello = { path = "../hello" }
//## ./main/src/main.rs
use hello;
fn main() {
println!("main");
hello::hello();
}
$
You can specify both version and path for the same dependency. When building locally cargo will use path, when uploading to crates.io, path will be stripped and version is left.
[dependencies]
# Uses `my-bitflags` when used locally, and uses
# version 1.0 from crates.io when published.
bitflags = { path = "my-bitflags", version = "1.0" }
I'm not sure, but I think the path will still be contained in the Cargo.toml.orig file, permanently published. It might not be a problem in the vast majority of cases, but may be worth mentioning as some private data (e.g. on other projects) might leak.