diff --git a/src/cargo/util/vcs.rs b/src/cargo/util/vcs.rs index 095164e23df..22c14a59082 100644 --- a/src/cargo/util/vcs.rs +++ b/src/cargo/util/vcs.rs @@ -10,7 +10,17 @@ use std::path::Path; // 2. We are in an HG repo. pub fn existing_vcs_repo(path: &Path, cwd: &Path) -> bool { fn in_git_repo(path: &Path, cwd: &Path) -> bool { - if let Ok(repo) = GitRepo::discover(path, cwd) { + // Try to find the first existing parent of the path. + // Otherwise, we can't find the git repo when the path has non-existing parent directories. + let mut first_exist_base_path = Some(path); + while let Some(p) = first_exist_base_path { + if p.exists() { + break; + } + first_exist_base_path = p.parent(); + } + + if let Ok(repo) = GitRepo::discover(first_exist_base_path.unwrap_or(path), cwd) { // Don't check if the working directory itself is ignored. if repo.workdir().map_or(false, |workdir| workdir == path) { true diff --git a/tests/testsuite/new.rs b/tests/testsuite/new.rs index 92a5ed46555..277154f5776 100644 --- a/tests/testsuite/new.rs +++ b/tests/testsuite/new.rs @@ -301,6 +301,43 @@ fn subpackage_git_with_gitignore() { .is_file()); } +#[cargo_test] +fn subpackage_no_git_with_git_in_ancestor() { + cargo_process("new foo").run(); + + assert!(paths::root().join("foo/.git").is_dir()); + assert!(paths::root().join("foo/.gitignore").is_file()); + + cargo_process("new foo/non-existent/subcomponent").run(); + + assert!(!paths::root() + .join("foo/non-existent/subcomponent/.git") + .is_dir()); + assert!(!paths::root() + .join("foo/non-existent/subcomponent/.gitignore") + .is_file()); +} + +#[cargo_test] +fn subpackage_git_with_gitignore_in_ancestor() { + cargo_process("new foo").run(); + + assert!(paths::root().join("foo/.git").is_dir()); + assert!(paths::root().join("foo/.gitignore").is_file()); + + let gitignore = paths::root().join("foo/.gitignore"); + fs::write(gitignore, b"non-existent").unwrap(); + + cargo_process("new foo/non-existent/subcomponent").run(); + + assert!(paths::root() + .join("foo/non-existent/subcomponent/.git") + .is_dir()); + assert!(paths::root() + .join("foo/non-existent/subcomponent/.gitignore") + .is_file()); +} + #[cargo_test] fn subpackage_git_with_vcs_arg() { cargo_process("new foo").run();