diff --git a/src/cargo/ops/vendor.rs b/src/cargo/ops/vendor.rs index 39ee0044545..a58d8f346c5 100644 --- a/src/cargo/ops/vendor.rs +++ b/src/cargo/ops/vendor.rs @@ -80,7 +80,13 @@ fn sync( if !opts.no_delete { for entry in canonical_destination.read_dir()? { let entry = entry?; - to_remove.insert(entry.path()); + if !entry + .file_name() + .to_str() + .map_or(false, |s| s.starts_with('.')) + { + to_remove.insert(entry.path()); + } } } diff --git a/tests/testsuite/vendor.rs b/tests/testsuite/vendor.rs index 7eccc0526b3..42dbcca2345 100644 --- a/tests/testsuite/vendor.rs +++ b/tests/testsuite/vendor.rs @@ -501,3 +501,39 @@ fn depend_on_vendor_dir_not_deleted() { p.cargo("vendor --respect-source-config").run(); assert!(p.root().join("vendor/libc").is_dir()); } + +#[cargo_test] +fn ignore_hidden() { + // Don't delete files starting with `.` + Package::new("bar", "0.1.0").publish(); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "1.0.0" + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + p.cargo("vendor --respect-source-config").run(); + // Add a `.git` directory. + let repo = git::init(&p.root().join("vendor")); + git::add(&repo); + git::commit(&repo); + assert!(p.root().join("vendor/.git").exists()); + // Vendor again, shouldn't change anything. + p.cargo("vendor --respect-source-config").run(); + // .git should not be removed. + assert!(p.root().join("vendor/.git").exists()); + // And just for good measure, make sure no files changed. + let mut opts = git2::StatusOptions::new(); + assert!(repo + .statuses(Some(&mut opts)) + .unwrap() + .iter() + .all(|status| status.status() == git2::Status::CURRENT)); +}