Skip to content

Commit 6c4baa2

Browse files
fix: fix copying .git folders by using overrides (#1838)
Co-authored-by: remimimimimi <[email protected]>
1 parent 15163d9 commit 6c4baa2

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

src/source/copy_dir.rs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{
88
use fs_err::create_dir_all;
99

1010
use globset::Glob;
11-
use ignore::WalkBuilder;
11+
use ignore::{WalkBuilder, overrides::OverrideBuilder};
1212
use rayon::iter::{ParallelBridge, ParallelIterator};
1313

1414
use crate::recipe::parser::{GlobVec, GlobWithSource};
@@ -142,6 +142,7 @@ pub(crate) struct CopyDir<'a> {
142142
use_git_global: bool,
143143
use_condapackageignore: bool,
144144
hidden: bool,
145+
exclude_git_dirs: bool,
145146
copy_options: CopyOptions,
146147
}
147148

@@ -159,6 +160,8 @@ impl<'a> CopyDir<'a> {
159160
use_condapackageignore: true,
160161
// include hidden files by default
161162
hidden: false,
163+
// exclude .git directories by default for path sources
164+
exclude_git_dirs: false,
162165
copy_options: CopyOptions::default(),
163166
}
164167
}
@@ -205,6 +208,11 @@ impl<'a> CopyDir<'a> {
205208
self
206209
}
207210

211+
pub fn exclude_git_dirs(mut self, b: bool) -> Self {
212+
self.exclude_git_dirs = b;
213+
self
214+
}
215+
208216
pub fn run(self) -> Result<CopyDirResult, SourceError> {
209217
// Create the to path because we're going to copy the contents only
210218
create_dir_all(self.to_path)?;
@@ -225,6 +233,14 @@ impl<'a> CopyDir<'a> {
225233
// Always disable .ignore files - they should not affect source copying
226234
.ignore(false)
227235
.hidden(self.hidden);
236+
237+
// Conditionally exclude .git directories for path sources only
238+
if self.exclude_git_dirs {
239+
let mut override_builder = OverrideBuilder::new(self.from_path);
240+
override_builder.add("!.git/").unwrap();
241+
let overrides = override_builder.build().unwrap();
242+
walk_builder.overrides(overrides);
243+
}
228244
if self.use_condapackageignore {
229245
walk_builder.add_custom_ignore_filename(".condapackageignore");
230246
}
@@ -738,4 +754,38 @@ mod test {
738754
.exists()
739755
);
740756
}
757+
758+
#[test]
759+
fn test_git_directory_exclusion() {
760+
let tmp_dir = tempfile::TempDir::new().unwrap();
761+
let src = tmp_dir.path().join("src");
762+
fs_err::create_dir_all(&src).unwrap();
763+
764+
// Create regular files and .git structure
765+
fs::write(src.join("main.rs"), "fn main() {}").unwrap();
766+
let git_obj = src.join(".git/objects/ab/1234567890abcdef");
767+
fs_err::create_dir_all(git_obj.parent().unwrap()).unwrap();
768+
fs::write(&git_obj, "fake git object").unwrap();
769+
770+
#[cfg(unix)]
771+
if git_obj.metadata().is_ok() {
772+
use std::os::unix::fs::PermissionsExt;
773+
let _ = fs_err::set_permissions(&git_obj, std::fs::Permissions::from_mode(0o444));
774+
}
775+
776+
let dest = tmp_dir.path().join("dest");
777+
let result = super::CopyDir::new(&src, &dest)
778+
.use_gitignore(false)
779+
.exclude_git_dirs(true)
780+
.run()
781+
.unwrap();
782+
783+
assert!(dest.join("main.rs").exists() && !dest.join(".git").exists());
784+
assert!(
785+
!result
786+
.copied_paths()
787+
.iter()
788+
.any(|p| p.components().any(|c| c.as_os_str() == ".git"))
789+
);
790+
}
741791
}

src/source/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ pub(crate) async fn fetch_source(
236236
copy_dir::CopyDir::new(&src_path, &dest_dir)
237237
.use_gitignore(src.use_gitignore())
238238
.with_globvec(&src.filter)
239+
.exclude_git_dirs(true)
239240
.run()
240241
},
241242
)?;

0 commit comments

Comments
 (0)