Skip to content

Commit 29a2165

Browse files
committed
Gracefully handle duplicate package in a lockfile
1 parent e958281 commit 29a2165

File tree

3 files changed

+53
-6
lines changed

3 files changed

+53
-6
lines changed

src/cargo/core/resolver/encode.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub struct EncodableResolve {
2020
pub type Metadata = BTreeMap<String, String>;
2121

2222
impl EncodableResolve {
23-
pub fn to_resolve(self, ws: &Workspace) -> CargoResult<Resolve> {
23+
pub fn into_resolve(self, ws: &Workspace) -> CargoResult<Resolve> {
2424
let path_deps = build_path_deps(ws);
2525
let default = try!(ws.current()).package_id().source_id();
2626

@@ -48,14 +48,17 @@ impl EncodableResolve {
4848
let mut register_pkg = |pkgid: &PackageId| {
4949
let precise = pkgid.source_id().precise()
5050
.map(|s| s.to_string());
51-
assert!(tmp.insert(pkgid.clone(), precise).is_none(),
52-
"a package was referenced twice in the lockfile");
51+
if tmp.insert(pkgid.clone(), precise).is_some() {
52+
return Err(internal(format!("package `{}` is specified twice in the lockfile",
53+
pkgid.name())));
54+
}
5355
g.add(pkgid.clone(), &[]);
56+
Ok(())
5457
};
5558

56-
register_pkg(&root);
59+
try!(register_pkg(&root));
5760
for id in ids.iter() {
58-
register_pkg(id);
61+
try!(register_pkg(id));
5962
}
6063
}
6164

src/cargo/ops/lockfile.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub fn load_pkg_lockfile(ws: &Workspace) -> CargoResult<Option<Resolve>> {
2626
let table = toml::Value::Table(table);
2727
let mut d = toml::Decoder::new(table);
2828
let v: resolver::EncodableResolve = try!(Decodable::decode(&mut d));
29-
Ok(Some(try!(v.to_resolve(ws))))
29+
Ok(Some(try!(v.into_resolve(ws))))
3030
}).chain_error(|| {
3131
human(format!("failed to parse lock file at: {}", f.path().display()))
3232
})

tests/bad-config.rs

+44
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,50 @@ Caused by:
236236
"));
237237
}
238238

239+
#[test]
240+
fn duplicate_packages_in_cargo_lock() {
241+
Package::new("foo", "0.1.0").publish();
242+
243+
let p = project("bar")
244+
.file("Cargo.toml", r#"
245+
[project]
246+
name = "bar"
247+
version = "0.0.1"
248+
authors = []
249+
250+
[dependencies]
251+
foo = "0.1.0"
252+
"#)
253+
.file("src/lib.rs", "")
254+
.file("Cargo.lock", r#"
255+
[root]
256+
name = "bar"
257+
version = "0.0.1"
258+
dependencies = [
259+
"foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
260+
]
261+
262+
[[package]]
263+
name = "foo"
264+
version = "0.1.0"
265+
source = "registry+https://github.com/rust-lang/crates.io-index"
266+
267+
[[package]]
268+
name = "foo"
269+
version = "0.1.0"
270+
source = "registry+https://github.com/rust-lang/crates.io-index"
271+
"#);
272+
p.build();
273+
274+
assert_that(p.cargo("build").arg("--verbose"),
275+
execs().with_status(101).with_stderr("\
276+
[ERROR] failed to parse lock file at: [..]
277+
278+
Caused by:
279+
package `foo` is specified twice in the lockfile
280+
"));
281+
}
282+
239283
#[test]
240284
fn bad_git_dependency() {
241285
let foo = project("foo")

0 commit comments

Comments
 (0)