diff --git a/src/cargo/sources/directory.rs b/src/cargo/sources/directory.rs index 1cf8b27550b..ee27a13cec3 100644 --- a/src/cargo/sources/directory.rs +++ b/src/cargo/sources/directory.rs @@ -81,6 +81,32 @@ impl<'cfg> Source for DirectorySource<'cfg> { } } + // Vendor directories are often checked into a VCS, but throughout + // the lifetime of a vendor dir crates are often added and deleted. + // Some VCS implementations don't always fully delete the directory + // when a dir is removed from a different checkout. Sometimes a + // mostly-empty dir is left behind. + // + // To help work Cargo work by default in more cases we try to + // handle this case by default. If the directory looks like it only + // has dotfiles in it (or no files at all) then we skip it. + // + // In general we don't want to skip completely malformed directories + // to help with debugging, so we don't just ignore errors in + // `update` below. + let mut only_dotfile = true; + for entry in path.read_dir()?.filter_map(|e| e.ok()) { + if let Some(s) = entry.file_name().to_str() { + if s.starts_with(".") { + continue + } + } + only_dotfile = false; + } + if only_dotfile { + continue + } + let mut src = PathSource::new(&path, &self.source_id, self.config); src.update()?; let pkg = src.root_package()?; diff --git a/tests/directory.rs b/tests/directory.rs index 33fd9a039e5..8ff54c1476e 100644 --- a/tests/directory.rs +++ b/tests/directory.rs @@ -471,3 +471,36 @@ required then it is recommended that [replace] is used with a forked copy of \ the source ")); } + +#[test] +fn only_dot_files_ok() { + setup(); + + VendorPackage::new("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + "#) + .file("src/lib.rs", "") + .build(); + VendorPackage::new("bar") + .file(".foo", "") + .build(); + + let p = project("bar") + .file("Cargo.toml", r#" + [package] + name = "bar" + version = "0.1.0" + authors = [] + + [dependencies] + foo = "0.1.0" + "#) + .file("src/lib.rs", ""); + p.build(); + + assert_that(p.cargo("build"), execs().with_status(0)); +}