diff --git a/src/cargo/core/resolver/encode.rs b/src/cargo/core/resolver/encode.rs index 8771a95328b..ca4cdec2e5b 100644 --- a/src/cargo/core/resolver/encode.rs +++ b/src/cargo/core/resolver/encode.rs @@ -20,7 +20,7 @@ pub struct EncodableResolve { pub type Metadata = BTreeMap; impl EncodableResolve { - pub fn to_resolve(self, ws: &Workspace) -> CargoResult { + pub fn into_resolve(self, ws: &Workspace) -> CargoResult { let path_deps = build_path_deps(ws); let default = try!(ws.current()).package_id().source_id(); @@ -48,14 +48,17 @@ impl EncodableResolve { let mut register_pkg = |pkgid: &PackageId| { let precise = pkgid.source_id().precise() .map(|s| s.to_string()); - assert!(tmp.insert(pkgid.clone(), precise).is_none(), - "a package was referenced twice in the lockfile"); + if tmp.insert(pkgid.clone(), precise).is_some() { + return Err(internal(format!("package `{}` is specified twice in the lockfile", + pkgid.name()))); + } g.add(pkgid.clone(), &[]); + Ok(()) }; - register_pkg(&root); + try!(register_pkg(&root)); for id in ids.iter() { - register_pkg(id); + try!(register_pkg(id)); } } diff --git a/src/cargo/core/source.rs b/src/cargo/core/source.rs index ed684e95468..4a46c19294d 100644 --- a/src/cargo/core/source.rs +++ b/src/cargo/core/source.rs @@ -131,7 +131,7 @@ impl SourceId { pub fn from_url(string: &str) -> CargoResult { let mut parts = string.splitn(2, '+'); let kind = parts.next().unwrap(); - let url = parts.next().unwrap(); + let url = try!(parts.next().ok_or(human(format!("invalid source `{}`", string)))); match kind { "git" => { diff --git a/src/cargo/ops/lockfile.rs b/src/cargo/ops/lockfile.rs index 91a2bf2d7a0..2afb4d534db 100644 --- a/src/cargo/ops/lockfile.rs +++ b/src/cargo/ops/lockfile.rs @@ -26,7 +26,7 @@ pub fn load_pkg_lockfile(ws: &Workspace) -> CargoResult> { let table = toml::Value::Table(table); let mut d = toml::Decoder::new(table); let v: resolver::EncodableResolve = try!(Decodable::decode(&mut d)); - Ok(Some(try!(v.to_resolve(ws)))) + Ok(Some(try!(v.into_resolve(ws)))) }).chain_error(|| { human(format!("failed to parse lock file at: {}", f.path().display())) }) diff --git a/tests/bad-config.rs b/tests/bad-config.rs index 15324711fbb..9e6aad274cc 100644 --- a/tests/bad-config.rs +++ b/tests/bad-config.rs @@ -236,6 +236,89 @@ Caused by: ")); } +#[test] +fn duplicate_packages_in_cargo_lock() { + Package::new("foo", "0.1.0").publish(); + + let p = project("bar") + .file("Cargo.toml", r#" + [project] + name = "bar" + version = "0.0.1" + authors = [] + + [dependencies] + foo = "0.1.0" + "#) + .file("src/lib.rs", "") + .file("Cargo.lock", r#" + [root] + name = "bar" + version = "0.0.1" + dependencies = [ + "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + ] + + [[package]] + name = "foo" + version = "0.1.0" + source = "registry+https://github.com/rust-lang/crates.io-index" + + [[package]] + name = "foo" + version = "0.1.0" + source = "registry+https://github.com/rust-lang/crates.io-index" + "#); + p.build(); + + assert_that(p.cargo("build").arg("--verbose"), + execs().with_status(101).with_stderr("\ +[ERROR] failed to parse lock file at: [..] + +Caused by: + package `foo` is specified twice in the lockfile +")); +} + +#[test] +fn bad_source_in_cargo_lock() { + Package::new("foo", "0.1.0").publish(); + + let p = project("bar") + .file("Cargo.toml", r#" + [project] + name = "bar" + version = "0.0.1" + authors = [] + + [dependencies] + foo = "0.1.0" + "#) + .file("src/lib.rs", "") + .file("Cargo.lock", r#" + [root] + name = "bar" + version = "0.0.1" + dependencies = [ + "foo 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + ] + + [[package]] + name = "foo" + version = "0.1.0" + source = "You shall not parse" + "#); + p.build(); + + assert_that(p.cargo("build").arg("--verbose"), + execs().with_status(101).with_stderr("\ +[ERROR] failed to parse lock file at: [..] + +Caused by: + invalid source `You shall not parse` for the key `package.source` +")); +} + #[test] fn bad_git_dependency() { let foo = project("foo")