]> git.proxmox.com Git - cargo.git/commitdiff
Fix recursion in build_path_deps
authorAlex Crichton <alex@alexcrichton.com>
Mon, 28 Nov 2016 19:10:31 +0000 (11:10 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Fri, 16 Dec 2016 17:47:05 +0000 (09:47 -0800)
We were slightly too eager to follow pointers!

Closes #3330

src/cargo/core/resolver/encode.rs
tests/path.rs

index b0c6e280a37088ac843a4e3de90d6bc3c86ac154..0b35ed5c3ac3db2a2e94404fa644a4f07e1029a6 100644 (file)
@@ -172,26 +172,28 @@ fn build_path_deps(ws: &Workspace) -> HashMap<String, SourceId> {
     }).collect::<Vec<_>>();
 
     let mut ret = HashMap::new();
+    let mut visited = HashSet::new();
     for member in members.iter() {
         ret.insert(member.package_id().name().to_string(),
                    member.package_id().source_id().clone());
+        visited.insert(member.package_id().source_id().clone());
     }
     for member in members.iter() {
-        build(member, ws.config(), &mut ret);
+        build(member, ws.config(), &mut ret, &mut visited);
     }
 
     return ret;
 
     fn build(pkg: &Package,
              config: &Config,
-             ret: &mut HashMap<String, SourceId>) {
+             ret: &mut HashMap<String, SourceId>,
+             visited: &mut HashSet<SourceId>) {
         let replace = pkg.manifest().replace();
         let deps = pkg.dependencies()
                       .iter()
                       .chain(replace.iter().map(|p| &p.1))
-                      .filter(|d| !ret.contains_key(d.name()))
                       .map(|d| d.source_id())
-                      .filter(|id| id.is_path())
+                      .filter(|id| !visited.contains(id) && id.is_path())
                       .filter_map(|id| id.url().to_file_path().ok())
                       .map(|path| path.join("Cargo.toml"))
                       .filter_map(|path| Package::for_path(&path, config).ok())
@@ -199,7 +201,8 @@ fn build_path_deps(ws: &Workspace) -> HashMap<String, SourceId> {
         for pkg in deps {
             ret.insert(pkg.name().to_string(),
                        pkg.package_id().source_id().clone());
-            build(&pkg, config, ret);
+            visited.insert(pkg.package_id().source_id().clone());
+            build(&pkg, config, ret, visited);
         }
     }
 }
index 7d057ae75b62022e726e27cf996909efeb14a9ba..f13cd9d3c6b16dfc137dd608bb98b8c44ba4a2f0 100644 (file)
@@ -9,6 +9,7 @@ use cargo::util::process;
 use cargotest::sleep_ms;
 use cargotest::support::paths::{self, CargoPathExt};
 use cargotest::support::{project, execs, main_file};
+use cargotest::support::registry::Package;
 use hamcrest::{assert_that, existing_file};
 
 #[test]
@@ -924,3 +925,57 @@ Caused by:
   [..] (os error [..])
 "));
 }
+
+#[test]
+fn invalid_path_dep_in_workspace_with_lockfile() {
+    Package::new("bar", "1.0.0").publish();
+
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [project]
+            name = "top"
+            version = "0.5.0"
+            authors = []
+
+            [workspace]
+
+            [dependencies]
+            foo = { path = "foo" }
+        "#)
+        .file("src/lib.rs", "")
+        .file("foo/Cargo.toml", r#"
+            [project]
+            name = "foo"
+            version = "0.5.0"
+            authors = []
+
+            [dependencies]
+            bar = "*"
+        "#)
+        .file("foo/src/lib.rs", "");
+    p.build();
+
+    // Generate a lock file
+    assert_that(p.cargo("build"), execs().with_status(0));
+
+    // Change the dependency on `bar` to an invalid path
+    File::create(&p.root().join("foo/Cargo.toml")).unwrap().write_all(br#"
+        [project]
+        name = "foo"
+        version = "0.5.0"
+        authors = []
+
+        [dependencies]
+        bar = { path = "" }
+    "#).unwrap();
+
+    // Make sure we get a nice error. In the past this actually stack
+    // overflowed!
+    assert_that(p.cargo("build"),
+                execs().with_status(101)
+                       .with_stderr("\
+error: no matching package named `bar` found (required by `foo`)
+location searched: [..]
+version required: *
+"));
+}