mirror of
https://github.com/lsd-rs/lsd
synced 2024-12-17 07:13:13 +00:00
122 lines
3.1 KiB
Rust
122 lines
3.1 KiB
Rust
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<Vec<Meta>>,
|
|
}
|
|
|
|
impl Meta {
|
|
pub fn from_path_recursive(
|
|
path: &PathBuf,
|
|
depth: usize,
|
|
list_hidden_files: bool,
|
|
) -> Result<Self, std::io::Error> {
|
|
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<Self, std::io::Error> {
|
|
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,
|
|
})
|
|
}
|
|
}
|