Skip to content

Commit d406d25

Browse files
committed
Auto merge of #1709 - alexcrichton:fix-some-overrides, r=brson
The fix in #1697 was to alter the `Hash` implementation of `Package` to take into account the source root instead of just the package id (so packages at the same source would have the same hash). There's a spot, however, where we normalize some paths and not others, causing two paths which logically point the same location end up having different hashes, so the same package ended up being stored multiple times, later leading to an assertion that there was only one stored. This commit alters the behavior of read_packages to keep a hash map of ID => Package instead of just a hash set of Package as the deduplication/equality needs to be based on the ID, not the literal path to the source root. This specific bug shows up when you have an override and a normal dependency pointing at the same location (and the override has some inter-dependencies). Not exactly a normal use case, but it showed up in Servo's build!
2 parents f98100f + 06a0605 commit d406d25

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

src/cargo/ops/cargo_read_manifest.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use std::collections::HashSet;
1+
use std::collections::{HashMap, HashSet};
22
use std::fs::{self, File};
33
use std::io::prelude::*;
44
use std::io;
55
use std::path::{Path, PathBuf};
66

7-
use core::{Package,Manifest,SourceId};
7+
use core::{Package, Manifest, SourceId, PackageId};
88
use util::{self, CargoResult, human, Config, ChainError};
99
use util::important_paths::find_project_manifest_exact;
1010
use util::toml::{Layout, project_layout};
@@ -35,7 +35,7 @@ pub fn read_package(path: &Path, source_id: &SourceId, config: &Config)
3535

3636
pub fn read_packages(path: &Path, source_id: &SourceId, config: &Config)
3737
-> CargoResult<Vec<Package>> {
38-
let mut all_packages = HashSet::new();
38+
let mut all_packages = HashMap::new();
3939
let mut visited = HashSet::<PathBuf>::new();
4040

4141
trace!("looking for root package: {}, source_id={}", path.display(), source_id);
@@ -69,7 +69,7 @@ pub fn read_packages(path: &Path, source_id: &SourceId, config: &Config)
6969
if all_packages.is_empty() {
7070
Err(human(format!("Could not find Cargo.toml in `{}`", path.display())))
7171
} else {
72-
Ok(all_packages.into_iter().collect())
72+
Ok(all_packages.into_iter().map(|(_, v)| v).collect())
7373
}
7474
}
7575

@@ -103,7 +103,7 @@ fn has_manifest(path: &Path) -> bool {
103103
}
104104

105105
fn read_nested_packages(path: &Path,
106-
all_packages: &mut HashSet<Package>,
106+
all_packages: &mut HashMap<PackageId, Package>,
107107
source_id: &SourceId,
108108
config: &Config,
109109
visited: &mut HashSet<PathBuf>) -> CargoResult<()> {
@@ -112,7 +112,7 @@ fn read_nested_packages(path: &Path,
112112
let manifest = try!(find_project_manifest_exact(path, "Cargo.toml"));
113113

114114
let (pkg, nested) = try!(read_package(&manifest, source_id, config));
115-
all_packages.insert(pkg);
115+
all_packages.insert(pkg.package_id().clone(), pkg);
116116

117117
// Registry sources are not allowed to have `path=` dependencies because
118118
// they're all translated to actual registry dependencies.

tests/test_cargo_compile_path_deps.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,3 +793,44 @@ test!(custom_target_no_rebuild {
793793
{compiling} b v0.5.0 ([..])
794794
", compiling = COMPILING)));
795795
});
796+
797+
test!(override_and_depend {
798+
let p = project("foo")
799+
.file("a/a1/Cargo.toml", r#"
800+
[project]
801+
name = "a1"
802+
version = "0.5.0"
803+
authors = []
804+
[dependencies]
805+
a2 = { path = "../a2" }
806+
"#)
807+
.file("a/a1/src/lib.rs", "")
808+
.file("a/a2/Cargo.toml", r#"
809+
[project]
810+
name = "a2"
811+
version = "0.5.0"
812+
authors = []
813+
"#)
814+
.file("a/a2/src/lib.rs", "")
815+
.file("b/Cargo.toml", r#"
816+
[project]
817+
name = "b"
818+
version = "0.5.0"
819+
authors = []
820+
[dependencies]
821+
a1 = { path = "../a/a1" }
822+
a2 = { path = "../a/a2" }
823+
"#)
824+
.file("b/src/lib.rs", "")
825+
.file("b/.cargo/config", r#"
826+
paths = ["../a"]
827+
"#);
828+
p.build();
829+
assert_that(p.cargo("build").cwd(p.root().join("b")),
830+
execs().with_status(0)
831+
.with_stdout(&format!("\
832+
{compiling} a2 v0.5.0 ([..])
833+
{compiling} a1 v0.5.0 ([..])
834+
{compiling} b v0.5.0 ([..])
835+
", compiling = COMPILING)));
836+
});

0 commit comments

Comments
 (0)