Skip to content

Git merge can produce inconsistent Cargo.lock files #2302

@SimonSapin

Description

@SimonSapin

This is a reduction of what happened in servo/servo#9380.

  • Consider a Cargo project in a git repository including Cargo.lock.
  • One of the crates has a dependency, say on matches version 0.1.1.
  • In a git branch A, another crate gets a dependency on matches added. The version stays 0.1.1.
  • In another branch B, matches is updated to 0.1.2
  • The two branches are merged.
  • Cargo.lock now lists a "matches 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)"dependency from branch A, but has no [[package]] section for that version. (The one section for matches was updated to 0.1.2. in branch B.)
  • Cargo fails to deal with this inconsistency, everything is stuck until Cargo.lock is fixed up manually.

Maybe Cargo could detect this kind of situation and repair it automatically?

This test script can be run in an empty directory:

#!/bin/sh
set -x

cargo new a --bin
cd a
echo 'b = {path = "./b"}' >> Cargo.toml
cargo new b
echo 'matches = "0.1"' >> b/Cargo.toml
cargo build
cargo update -p matches --precise 0.1.1
git add .
git commit -a -m "Initial"
git checkout -b update
cargo update -p matches --precise 0.1.2
git commit -a -m "Update"
git checkout master
echo 'matches = "0.1"' >> Cargo.toml
cargo build
git commit -a -m "Add dep"
git merge update --no-edit
cat Cargo.lock
cargo build

cd ..
rm -rf a

Here is the output:

+ cargo new a --bin
+ cd a
+ echo 'b = {path = "./b"}'
+ cargo new b
+ echo 'matches = "0.1"'
+ cargo build
    Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling matches v0.1.2
   Compiling b v0.1.0 (file:///tmp/z/a)
   Compiling a v0.1.0 (file:///tmp/z/a)
+ cargo update -p matches --precise 0.1.1
    Updating registry `https://github.com/rust-lang/crates.io-index`
    Updating matches v0.1.2 -> v0.1.1
+ git add .
+ git commit -a -m Initial
[master (root-commit) 468750c] Initial
 6 files changed, 43 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 Cargo.lock
 create mode 100644 Cargo.toml
 create mode 100644 b/Cargo.toml
 create mode 100644 b/src/lib.rs
 create mode 100644 src/main.rs
+ git checkout -b update
Switched to a new branch 'update'
+ cargo update -p matches --precise 0.1.2
    Updating registry `https://github.com/rust-lang/crates.io-index`
    Updating matches v0.1.1 -> v0.1.2
+ git commit -a -m Update
[update 45230ad] Update
 1 file changed, 2 insertions(+), 2 deletions(-)
+ git checkout master
Switched to branch 'master'
+ echo 'matches = "0.1"'
+ cargo build
    Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling matches v0.1.1
   Compiling b v0.1.0 (file:///tmp/z/a)
   Compiling a v0.1.0 (file:///tmp/z/a)
+ git commit -a -m 'Add dep'
[master d2ece92] Add dep
 2 files changed, 2 insertions(+)
+ git merge update --no-edit
Auto-merging Cargo.lock
Merge made by the 'recursive' strategy.
 Cargo.lock | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
+ cat Cargo.lock
[root]
name = "a"
version = "0.1.0"
dependencies = [
 "b 0.1.0",
 "matches 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "b"
version = "0.1.0"
dependencies = [
 "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "matches"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"

+ cargo build
failed to select a version for `matches` (required by `a`):
all possible versions conflict with previously selected versions of `matches`
  version 0.1.2 in use by matches v0.1.2
  possible versions to select: 0.1.1
+ cd ..
+ rm -rf a

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Error and warning messages generated by Cargo itself.C-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions