diff --git a/gix-fs/src/symlink.rs b/gix-fs/src/symlink.rs index d37980f4674..8dd64406cbb 100644 --- a/gix-fs/src/symlink.rs +++ b/gix-fs/src/symlink.rs @@ -59,7 +59,7 @@ pub fn create(original: &Path, link: &Path) -> io::Result<()> { pub fn is_collision_error(err: &std::io::Error) -> bool { // TODO: use ::IsDirectory as well when stabilized instead of raw_os_error(), and ::FileSystemLoop respectively err.kind() == AlreadyExists - || err.raw_os_error() == Some(21) + || err.raw_os_error() == Some(if cfg!(windows) { 5 } else { 21 }) || err.raw_os_error() == Some(62) // no-follow on symlnk on mac-os || err.raw_os_error() == Some(40) // no-follow on symlnk on ubuntu } diff --git a/gix-glob/src/search/pattern.rs b/gix-glob/src/search/pattern.rs index 828e59df3f7..54981651ecb 100644 --- a/gix-glob/src/search/pattern.rs +++ b/gix-glob/src/search/pattern.rs @@ -48,16 +48,29 @@ fn read_in_full_ignore_missing(path: &Path, follow_symlinks: bool, buf: &mut Vec }; Ok(match file { Ok(mut file) => { - file.read_to_end(buf)?; - true + if let Err(err) = file.read_to_end(buf) { + if io_err_is_dir(&err) { + false + } else { + return Err(err); + } + } else { + true + } } - Err(err) if err.kind() == std::io::ErrorKind::NotFound || - // TODO: use the enum variant NotADirectory for this once stabilized - err.raw_os_error() == Some(20) /* Not a directory */ => false, + Err(err) if err.kind() == std::io::ErrorKind::NotFound || io_err_is_dir(&err) => false, Err(err) => return Err(err), }) } +fn io_err_is_dir(err: &std::io::Error) -> bool { + // TODO: use the enum variant NotADirectory for this once stabilized + let raw = err.raw_os_error(); + raw == Some(if cfg!(windows) { 5 } else { 21 }) /* Not a directory */ + /* Also that, but under different circumstances */ + || raw == Some(20) +} + /// Instantiation impl List where diff --git a/gix-glob/tests/search/pattern.rs b/gix-glob/tests/search/pattern.rs index 6b62ee3d286..cfdb410a67f 100644 --- a/gix-glob/tests/search/pattern.rs +++ b/gix-glob/tests/search/pattern.rs @@ -85,7 +85,7 @@ mod list { } #[test] - fn from_file() { + fn from_file_that_does_not_exist() { let mut buf = Vec::new(); for path in [ Path::new(".").join("non-existing-dir").join("pattern-file"), @@ -95,4 +95,16 @@ mod list { assert!(list.is_none(), "the file does not exist"); } } + + #[test] + fn from_file_that_is_a_directory() -> gix_testtools::Result<()> { + let tmp = gix_testtools::tempfile::TempDir::new()?; + let dir_path = tmp.path().join(".gitignore"); + std::fs::create_dir(&dir_path)?; + let mut buf = Vec::new(); + let list = List::::from_file(dir_path, None, false, &mut buf).expect("no io error"); + assert!(list.is_none(), "directories are ignored just like Git does it"); + + Ok(()) + } } diff --git a/gix-worktree/src/stack/delegate.rs b/gix-worktree/src/stack/delegate.rs index d2b3a011b0b..14a48be4e80 100644 --- a/gix-worktree/src/stack/delegate.rs +++ b/gix-worktree/src/stack/delegate.rs @@ -1,4 +1,3 @@ -use crate::stack::mode_is_dir; use crate::{stack::State, PathIdMapping}; /// Various aggregate numbers related to the stack delegate itself. @@ -167,7 +166,7 @@ fn create_leading_directory( mkdir_calls: &mut usize, unlink_on_collision: bool, ) -> std::io::Result<()> { - if is_last_component && !mode_is_dir(mode).unwrap_or(false) { + if is_last_component && !crate::stack::mode_is_dir(mode).unwrap_or(false) { return Ok(()); } *mkdir_calls += 1;