Skip to content

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

Open
@ehuss

Description

@ehuss

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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-dependency-resolutionArea: dependency resolution and the resolverA-patchArea: [patch] table overrideC-bugCategory: bugCommand-updateS-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