Skip to content

Multiple git dependencies with different refs confuses cargo #10256

@ehuss

Description

@ehuss

Problem

If there are multiple git dependencies on the same repository with different refs, but those refs contain the same package version, then cargo gets confused. There is no package spec that can be passed to -p to unambiguously refer to them. Thus commands like cargo update -p my-git-dep can't work.

Steps

Example using cargo's testsuite:

#[cargo_test]
fn multiple_git_same_version() {
    // Test what happens if different packages refer to the same git repo with
    // different refs, and the package version is the same.
    let (xyz_project, xyz_repo) = git::new_repo("xyz", |project| {
        project
            .file("Cargo.toml", &basic_lib_manifest("xyz"))
            .file("src/lib.rs", "fn example() {}")
    });
    let rev1 = xyz_repo.revparse_single("HEAD").unwrap().id();
    xyz_project.change_file("src/lib.rs", "pub fn example() {}");
    git::add(&xyz_repo);
    let rev2 = git::commit(&xyz_repo);
    // Both rev1 and rev2 point to version 0.1.0.

    let p = project()
        .file(
            "Cargo.toml",
            &format!(
                r#"
                    [package]
                    name = "foo"
                    version = "0.1.0"

                    [dependencies]
                    bar = {{ path = "bar" }}
                    xyz = {{ git = "{}", rev = "{}" }}

                "#,
                xyz_project.url(),
                rev1
            ),
        )
        .file("src/lib.rs", "")
        .file(
            "bar/Cargo.toml",
            &format!(
                r#"
                    [package]
                    name = "bar"
                    version = "0.1.0"

                    [dependencies]
                    xyz = {{ git = "{}", rev = "{}" }}
                "#,
                xyz_project.url(),
                rev2
            ),
        )
        .file("bar/src/lib.rs", "")
        .build();

    p.cargo("check").run();
    p.cargo("tree")
        .with_stdout(&format!(
            "\
foo v0.1.0 ([..]/foo)
├── bar v0.1.0 ([..]/foo/bar)
│   └── xyz v0.5.0 (file://[..]/xyz?rev={}#{})
└── xyz v0.5.0 (file://[..]/xyz?rev={}#{})
",
            rev2,
            &rev2.to_string()[..8],
            rev1,
            &rev1.to_string()[..8]
        ))
        .run();
    // FIXME: This fails since xyz is ambiguous, but the
    // possible pkgids are also ambiguous.
    p.cargo("pkgid xyz")
        .with_status(101)
        .with_stderr(
            "\
error: There are multiple `xyz` packages in your project, and the specification `xyz` is ambiguous.
Please re-run this command with `-p <spec>` where `<spec>` is one of the following:
  file://[..]/xyz#0.5.0
  file://[..]/xyz#0.5.0
",
        )
        .run();
    // TODO, what should the `-p` value be here?
    //p.cargo("update -p")
}

Possible Solution(s)

I'm not sure if this should be an allowed configuration, since @alexcrichton has mentioned a few times like here that is an invalid Cargo.lock configuration. However, I think it probably should be supported, since otherwise it can make it hard to get all Cargo.toml files in sync.

I could image cargo could allow pkgid specs of the form https://.../foo.git?rev=499e8c4bb3b75ae6c4dcc91a8bdd81947c577147 or something like that.

Notes

There are some related issues like #8101 and #8293, though I'm not sure if those are duplicates.

Version

cargo 1.59.0-nightly (fcef61230 2021-12-17)
release: 1.59.0-nightly
commit-hash: fcef61230c3b6213b6b0d233a36ba4ebd1649ec3
commit-date: 2021-12-17
host: x86_64-apple-darwin
libgit2: 1.3.0 (sys:0.13.23 vendored)
libcurl: 7.77.0 (sys:0.4.51+curl-7.80.0 system ssl:(SecureTransport) LibreSSL/2.8.3)
os: Mac OS 12.0.1 [64-bit]

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-gitArea: anything dealing with gitC-bugCategory: bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions