use std::fs::{DirEntry, FileType, Metadata};
use std::io;
pub(crate) fn entry_is_dir(entry: &DirEntry) -> io::Result<bool> {
entry.file_type().map(|ft| ft.is_dir())
}
pub(crate) fn entry_is_git_ignored_special(entry: &DirEntry) -> io::Result<bool> {
entry
.file_type()
.map(|ft| file_type_is_git_ignored_special(&ft))
}
pub(crate) fn metadata_is_git_ignored_special(meta: &Metadata) -> bool {
file_type_is_git_ignored_special(&meta.file_type())
}
fn file_type_is_git_ignored_special(ft: &FileType) -> bool {
if ft.is_dir() || ft.is_file() || ft.is_symlink() {
return false;
}
#[cfg(unix)]
{
use std::os::unix::fs::FileTypeExt;
if ft.is_fifo() || ft.is_socket() || ft.is_block_device() || ft.is_char_device() {
return true;
}
}
true
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
#[test]
fn regular_file_is_not_special() {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("f.txt");
fs::write(&path, b"x").expect("write");
let entry = fs::read_dir(dir.path())
.expect("read_dir")
.find(|e| e.as_ref().ok().is_some_and(|e| e.file_name() == "f.txt"))
.expect("entry")
.expect("entry ok");
assert!(!entry_is_git_ignored_special(&entry).expect("type"));
}
#[cfg(unix)]
#[test]
fn fifo_is_special() {
use std::process::Command;
let dir = tempfile::tempdir().expect("tempdir");
let fifo = dir.path().join("pipe");
let status = Command::new("mkfifo").arg(&fifo).status().expect("mkfifo");
assert!(status.success(), "mkfifo failed");
let entry = fs::read_dir(dir.path())
.expect("read_dir")
.find(|e| e.as_ref().ok().is_some_and(|e| e.file_name() == "pipe"))
.expect("entry")
.expect("entry ok");
assert!(entry_is_git_ignored_special(&entry).expect("type"));
let meta = fs::symlink_metadata(&fifo).expect("stat");
assert!(metadata_is_git_ignored_special(&meta));
}
}