How to avoid changing Cargo.toml repeatedly

Hi forum,

Suppose I want to use a crate named "hello" on crates.io. My Cargo.toml is like this:

[dependencies]
hello = "0.1.0"

I want to contribute to this crate, so I clone its repo to my computer and change my toml file to this:

[dependencies]
hello = { path = "../hello" }

When I push my changes to the repo, I need to undo changes to my toml file, right?

[dependencies]
hello = "0.1.0"

I think Go lang has the new feature go.work to avoid repeated changes like this.

Thanks

3 Likes

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.

4 Likes

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).

1 Like

Suppose my code is in a crate which will be published online too.

1 Like

Thanks,

I followed this Cargo Workspaces - The Rust Programming Language

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.

4 Likes

Thanks,

found it here Specifying Dependencies - The Cargo Book

[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.

If that ends up being true, a git clean filter might do the trick.