Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Git merge can produce inconsistent Cargo.lock files #2302

Closed
SimonSapin opened this issue Jan 21, 2016 · 5 comments
Closed

Git merge can produce inconsistent Cargo.lock files #2302

SimonSapin opened this issue Jan 21, 2016 · 5 comments
Labels
A-diagnostics Area: Error and warning messages generated by Cargo itself. C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`

Comments

@SimonSapin
Copy link
Contributor

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
@SimonSapin
Copy link
Contributor Author

Note that once in that situation, even cargo update fails with the same error message.

@alexcrichton
Copy link
Member

Thanks so much for the detailed writeup @SimonSapin! (especially the script to reproduce)

This should indeed be relatively easy enough to detect and provide a nicer error message.

@carols10cents carols10cents added A-diagnostics Area: Error and warning messages generated by Cargo itself. C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` labels Sep 25, 2017
@dwijnand
Copy link
Member

See also #1818 which, if resolved, might provide a resolution for this.

@Eh2406
Copy link
Contributor

Eh2406 commented Nov 30, 2018

Can someone test if this still happens after #5831 ?

@dwijnand
Copy link
Member

dwijnand commented Feb 6, 2019

Seems to be fixed with #5831:

+ cat Cargo.lock
[[package]]
name = "a"
version = "0.1.0"
dependencies = [
 "b 0.1.0",
 "matches 0.1.8 (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"

[metadata]
"checksum matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "15305656809ce5a4805b1ff2946892810992197ce1270ff79baded852187942e"
+ cargo build
   Compiling matches v0.1.2
   Compiling a v0.1.0 (/s/a)
    Finished dev [unoptimized + debuginfo] target(s) in 0.75s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Error and warning messages generated by Cargo itself. C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`
Projects
None yet
Development

No branches or pull requests

5 participants