From 31fcba372fa9d769e49a6c58078db89fc4f13fd9 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 18 Feb 2021 20:47:18 +0800 Subject: [PATCH 1/2] fix: add `.*` pattern in the same gitignore instance --- src/cargo/sources/path.rs | 49 ++++++++++++--------------------------- 1 file changed, 15 insertions(+), 34 deletions(-) diff --git a/src/cargo/sources/path.rs b/src/cargo/sources/path.rs index 64b0f77ed..a379cbfaf 100644 --- a/src/cargo/sources/path.rs +++ b/src/cargo/sources/path.rs @@ -107,8 +107,17 @@ impl<'cfg> PathSource<'cfg> { fn _list_files(&self, pkg: &Package) -> CargoResult> { let root = pkg.root(); let no_include_option = pkg.manifest().include().is_empty(); + let git_repo = if no_include_option { + self.discover_git_repo(root)? + } else { + None + }; let mut exclude_builder = GitignoreBuilder::new(root); + if no_include_option && git_repo.is_none() { + // no include option and not git repo discovered (see rust-lang/cargo#7183). + exclude_builder.add_line(None, ".*")?; + } for rule in pkg.manifest().exclude() { exclude_builder.add_line(None, rule)?; } @@ -160,23 +169,16 @@ impl<'cfg> PathSource<'cfg> { // Attempt Git-prepopulate only if no `include` (see rust-lang/cargo#4135). if no_include_option { - if let Some(result) = self.discover_git_and_list_files(pkg, root, &mut filter)? { - return Ok(result); + if let Some(repo) = git_repo { + return self.list_files_git(pkg, &repo, &mut filter); } - // no include option and not git repo discovered (see rust-lang/cargo#7183). - return self.list_files_walk_except_dot_files_and_dirs(pkg, &mut filter); } self.list_files_walk(pkg, &mut filter) } - // Returns `Some(_)` if found sibling `Cargo.toml` and `.git` directory; - // otherwise, caller should fall back on full file list. - fn discover_git_and_list_files( - &self, - pkg: &Package, - root: &Path, - filter: &mut dyn FnMut(&Path, bool) -> CargoResult, - ) -> CargoResult>> { + /// Returns `Some(git2::Repository)` if found sibling `Cargo.toml` and `.git` + /// directory; otherwise, caller should fall back on full file list. + fn discover_git_repo(&self, root: &Path) -> CargoResult> { let repo = match git2::Repository::discover(root) { Ok(repo) => repo, Err(e) => { @@ -211,7 +213,7 @@ impl<'cfg> PathSource<'cfg> { }; let manifest_path = repo_relative_path.join("Cargo.toml"); if index.get_path(&manifest_path, 0).is_some() { - return Ok(Some(self.list_files_git(pkg, &repo, filter)?)); + return Ok(Some(repo)); } // Package Cargo.toml is not in git, don't use git to guide our selection. Ok(None) @@ -355,27 +357,6 @@ impl<'cfg> PathSource<'cfg> { } } - fn list_files_walk_except_dot_files_and_dirs( - &self, - pkg: &Package, - filter: &mut dyn FnMut(&Path, bool) -> CargoResult, - ) -> CargoResult> { - let root = pkg.root(); - let mut exclude_dot_files_dir_builder = GitignoreBuilder::new(root); - exclude_dot_files_dir_builder.add_line(None, ".*")?; - let ignore_dot_files_and_dirs = exclude_dot_files_dir_builder.build()?; - - let mut filter_ignore_dot_files_and_dirs = - |path: &Path, is_dir: bool| -> CargoResult { - let relative_path = path.strip_prefix(root)?; - match ignore_dot_files_and_dirs.matched_path_or_any_parents(relative_path, is_dir) { - Match::Ignore(_) => Ok(false), - _ => filter(path, is_dir), - } - }; - self.list_files_walk(pkg, &mut filter_ignore_dot_files_and_dirs) - } - fn list_files_walk( &self, pkg: &Package, From 153146ecc5264f3066caf314b37c8091c0eb7595 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 18 Feb 2021 20:48:17 +0800 Subject: [PATCH 2/2] test(vendor): respect to Cargo.toml [package.exclude] --- tests/testsuite/vendor.rs | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/testsuite/vendor.rs b/tests/testsuite/vendor.rs index 63872392e..09968aa94 100644 --- a/tests/testsuite/vendor.rs +++ b/tests/testsuite/vendor.rs @@ -50,6 +50,50 @@ fn add_vendor_config(p: &Project) { ); } +#[cargo_test] +fn package_exclude() { + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "0.1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + Package::new("bar", "0.1.0") + .file( + "Cargo.toml", + r#" + [package] + name = "bar" + version = "0.1.0" + exclude = [".*", "!.include", "!.dotdir/include"] + "#, + ) + .file("src/lib.rs", "") + .file(".exclude", "") + .file(".include", "") + .file(".dotdir/exclude", "") + .file(".dotdir/include", "") + .publish(); + + p.cargo("vendor --respect-source-config").run(); + let csum = dbg!(p.read_file("vendor/bar/.cargo-checksum.json")); + assert!(csum.contains(".include")); + assert!(!csum.contains(".exclude")); + assert!(!csum.contains(".dotdir/exclude")); + // Gitignore doesn't re-include a file in an excluded parent directory, + // even if negating it explicitly. + assert!(!csum.contains(".dotdir/include")); +} + #[cargo_test] fn two_versions() { let p = project()