Skip to content

cargo update -p bar where bar is patched can partially unpatch bar #8355

Open

Description

Problem
If there is a [patch] for something at version 0.1.0, and you need to update the [patch] to version 0.1.1, but there is also a 0.1.2 available in the registry, cargo update is too aggressive and will pick 0.1.2. This can lead to a somewhat corrupt state where there are two different semver compatible versions in the lockfile.

See rust-lang/rust#73238 (comment) for a real-life example.

Note: This isn't specific to cargo update. Implicit updates from cargo build also cause this.

Steps
Repro as a cargo test:

#[cargo_test]
fn update_patch_when_newer_available() {
    // `cargo update` when there is a patch, and there is a *newer*
    // version available on crates.io.
    Package::new("bar", "0.1.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [workspace]
                members = ["foo", "bar"]

                [patch.crates-io]
                bar = { path = "bar" }
            "#,
        )
        .file(
            "foo/Cargo.toml",
            r#"
                [package]
                name = "foo"
                version = "0.1.0"

                [dependencies]
                bar = "0.1"
            "#,
        )
        .file("foo/src/lib.rs", "")
        .file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
        .file("bar/src/lib.rs", "")
        .build();

    // Establish an initial Cargo.lock.
    p.cargo("tree")
        .with_stdout(
            "\
bar v0.1.0 ([ROOT]/foo/bar)

foo v0.1.0 ([ROOT]/foo/foo)
└── bar v0.1.0 ([ROOT]/foo/bar)
",
        )
        .run();

    Package::new("bar", "0.1.1").publish();
    Package::new("bar", "0.1.2").publish();

    p.change_file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"));

    // Ideally this would just work, and pick 0.1.1 from the workspace.
    // Unfortunately it picks 0.1.2.
    // p.cargo("update -p bar").run();
    // This doesn't work either (it picks 0.1.2).
    // p.cargo("update -p bar --precise 0.1.1").run();

    // Currently, the only solution is to do:
    //  cargo update -p bar
    //  cargo update -p bar:0.1.2 --precise 0.1.1
    // 
    // where the second command downgrades and reverses the damage from the first command.
}

Notes

cargo 1.45.0-nightly (40ebd52 2020-06-01)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions