mod date; mod filetype; mod indicator; mod name; mod owner; mod permissions; mod size; mod symlink; pub use self::date::Date; pub use self::filetype::FileType; pub use self::indicator::Indicator; pub use self::name::Name; pub use self::owner::Owner; pub use self::permissions::Permissions; pub use self::size::Size; pub use self::symlink::SymLink; pub use crate::icon::Icons; use std::fs::read_link; use std::io::{Error, ErrorKind}; use std::path::PathBuf; #[derive(Debug)] pub struct Meta { pub name: Name, pub path: PathBuf, pub permissions: Permissions, pub date: Date, pub owner: Owner, pub file_type: FileType, pub size: Size, pub symlink: SymLink, pub indicator: Indicator, pub content: Option>, } impl Meta { pub fn from_path_recursive( path: &PathBuf, depth: usize, list_hidden_files: bool, ) -> Result { let mut meta = Self::from_path(path)?; if depth == 0 { return Ok(meta); } match meta.file_type { FileType::Directory { .. } => (), _ => return Ok(meta), } if let Err(err) = meta.path.read_dir() { println!("cannot access '{}': {}", path.display(), err); return Ok(meta); } let mut content = Vec::new(); for entry in meta.path.read_dir()? { let path = entry?.path(); if !list_hidden_files && path .file_name() .ok_or_else(|| Error::new(ErrorKind::InvalidInput, "invalid file name"))? .to_string_lossy() .starts_with('.') { continue; } let entry_meta = match Self::from_path_recursive( &path.to_path_buf(), depth - 1, list_hidden_files, ) { Ok(res) => res, Err(err) => { println!("cannot access '{}': {}", path.display(), err); continue; } }; content.push(entry_meta); } if !content.is_empty() { meta.content = Some(content); } Ok(meta) } pub fn from_path(path: &PathBuf) -> Result { let metadata = if read_link(path).is_ok() { // If the file is a link, retrieve the metadata without following // the link. path.symlink_metadata()? } else { path.metadata()? }; let permissions = Permissions::from(&metadata); let file_type = FileType::new(&metadata, &permissions); let name = Name::new(&path, file_type); Ok(Self { path: path.to_path_buf(), symlink: SymLink::from(path.as_path()), size: Size::from(&metadata), date: Date::from(&metadata), indicator: Indicator::from(file_type), owner: Owner::from(&metadata), permissions, name, file_type, content: None, }) } }