diff --git a/yazi-dds/src/state.rs b/yazi-dds/src/state.rs index ffb6baed..d7a80c92 100644 --- a/yazi-dds/src/state.rs +++ b/yazi-dds/src/state.rs @@ -1,6 +1,6 @@ use std::{mem, ops::Deref, sync::atomic::{AtomicU64, Ordering}, time::UNIX_EPOCH}; -use anyhow::Result; +use anyhow::{Result, anyhow}; use hashbrown::HashMap; use parking_lot::RwLock; use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader, BufWriter}; @@ -103,8 +103,9 @@ impl State { } async fn skip(&self) -> Result { - let meta = Local::symlink_metadata(BOOT.state_dir.join(".dds")).await?; - let modified = meta.modified()?.duration_since(UNIX_EPOCH)?.as_micros(); + let cha = Local::symlink_metadata(BOOT.state_dir.join(".dds")).await?; + let modified = + cha.mtime.ok_or_else(|| anyhow!("invalid mtime"))?.duration_since(UNIX_EPOCH)?.as_micros(); Ok(modified >= self.last.load(Ordering::Relaxed) as u128) } } diff --git a/yazi-fs/src/cha/cha.rs b/yazi-fs/src/cha/cha.rs index de76b3a6..57dd9b8b 100644 --- a/yazi-fs/src/cha/cha.rs +++ b/yazi-fs/src/cha/cha.rs @@ -1,4 +1,4 @@ -use std::{fs::{FileType, Metadata}, ops::Deref, time::SystemTime}; +use std::{ffi::OsStr, fs::{FileType, Metadata}, ops::Deref, time::SystemTime}; use yazi_macro::{unix_either, win_either}; use yazi_shared::url::Url; @@ -47,11 +47,8 @@ impl Default for Cha { impl Cha { #[inline] - pub fn new<'a, U>(url: U, meta: Metadata) -> Self - where - U: Into>, - { - Self::from_bare(&meta).attach(ChaKind::hidden(url, &meta)) + pub fn new(name: &OsStr, meta: Metadata) -> Self { + Self::from_bare(&meta).attach(ChaKind::hidden(name, &meta)) } #[inline] @@ -60,22 +57,21 @@ impl Cha { Ok(Self::from_follow(url, provider::symlink_metadata(url).await?).await) } - pub async fn from_follow<'a, U>(url: U, mut meta: Metadata) -> Self + pub async fn from_follow<'a, U>(url: U, mut cha: Self) -> Self where U: Into>, { - let url = url.into(); - let mut attached = ChaKind::hidden(url, &meta); + let url: Url = url.into(); + let mut attached = cha.kind & (ChaKind::HIDDEN | ChaKind::SYSTEM | ChaKind::LINK); - if meta.is_symlink() { - attached |= ChaKind::LINK; - meta = provider::metadata(url).await.unwrap_or(meta); + if cha.is_link() { + cha = provider::metadata(url).await.unwrap_or(cha); } - if meta.is_symlink() { + if cha.is_link() { attached |= ChaKind::ORPHAN; } - Self::from_bare(&meta).attach(attached) + cha.attach(attached) } pub fn from_dummy<'a, U>(_url: U, ft: Option) -> Self diff --git a/yazi-fs/src/cha/kind.rs b/yazi-fs/src/cha/kind.rs index 291933e1..df16385a 100644 --- a/yazi-fs/src/cha/kind.rs +++ b/yazi-fs/src/cha/kind.rs @@ -1,7 +1,6 @@ -use std::fs::Metadata; +use std::{ffi::OsStr, fs::Metadata}; use bitflags::bitflags; -use yazi_shared::url::Url; bitflags! { #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] @@ -18,15 +17,15 @@ bitflags! { impl ChaKind { #[inline] - pub(super) fn hidden<'a, U>(_url: U, _meta: &Metadata) -> Self - where - U: Into>, - { + pub(super) fn hidden(_name: &OsStr, _meta: &Metadata) -> Self { let mut me = Self::empty(); #[cfg(unix)] - if _url.into().urn().is_hidden() { - me |= Self::HIDDEN; + { + use std::os::unix::ffi::OsStrExt; + if _name.as_bytes().starts_with(b".") { + me |= Self::HIDDEN; + } } #[cfg(windows)] { diff --git a/yazi-fs/src/file.rs b/yazi-fs/src/file.rs index 4f5a6a96..2576d613 100644 --- a/yazi-fs/src/file.rs +++ b/yazi-fs/src/file.rs @@ -1,4 +1,4 @@ -use std::{ffi::OsStr, fs::{FileType, Metadata}, hash::{BuildHasher, Hash, Hasher}, ops::Deref, path::{Path, PathBuf}}; +use std::{ffi::OsStr, fs::FileType, hash::{BuildHasher, Hash, Hasher}, ops::Deref, path::{Path, PathBuf}}; use anyhow::Result; use yazi_shared::url::{Uri, UrlBuf, UrlCow, Urn}; @@ -22,15 +22,15 @@ impl File { #[inline] pub async fn new(url: impl Into>) -> Result { let url = url.into(); - let meta = provider::symlink_metadata(&url).await?; - Ok(Self::from_follow(url.into_owned(), meta).await) + let cha = provider::symlink_metadata(&url).await?; + Ok(Self::from_follow(url.into_owned(), cha).await) } #[inline] - pub async fn from_follow(url: UrlBuf, meta: Metadata) -> Self { - let link_to = if meta.is_symlink() { provider::read_link(&url).await.ok() } else { None }; + pub async fn from_follow(url: UrlBuf, cha: Cha) -> Self { + let link_to = if cha.is_link() { provider::read_link(&url).await.ok() } else { None }; - let cha = Cha::from_follow(&url, meta).await; + let cha = Cha::from_follow(&url, cha).await; Self { url, cha, link_to } } diff --git a/yazi-fs/src/files.rs b/yazi-fs/src/files.rs index 4082bad0..09de81c0 100644 --- a/yazi-fs/src/files.rs +++ b/yazi-fs/src/files.rs @@ -46,7 +46,7 @@ impl Files { result = item.metadata() => { let url = item.url(); _ = tx.send(match result { - Ok(meta) => File::from_follow(url, meta).await, + Ok(cha) => File::from_follow(url, cha).await, Err(_) => File::from_dummy(url, item.file_type().await.ok()) }); } @@ -70,7 +70,7 @@ impl Files { for entry in entries { let url = entry.url(); files.push(match entry.metadata().await { - Ok(meta) => File::from_follow(url, meta).await, + Ok(cha) => File::from_follow(url, cha).await, Err(_) => File::from_dummy(url, entry.file_type().await.ok()), }); } diff --git a/yazi-fs/src/fns.rs b/yazi-fs/src/fns.rs index 843b5bba..7c1f6c87 100644 --- a/yazi-fs/src/fns.rs +++ b/yazi-fs/src/fns.rs @@ -68,7 +68,7 @@ pub fn copy_with_progress( None => {} } - let len = provider::symlink_metadata(&to).await.map(|m| m.len()).unwrap_or(0); + let len = provider::symlink_metadata(&to).await.map(|m| m.len).unwrap_or(0); if len > last { prog_tx.send(Ok(len - last)).await.ok(); last = len; diff --git a/yazi-fs/src/provider/calculator.rs b/yazi-fs/src/provider/calculator.rs index aa409e0f..85920f7a 100644 --- a/yazi-fs/src/provider/calculator.rs +++ b/yazi-fs/src/provider/calculator.rs @@ -15,11 +15,11 @@ impl SizeCalculator { U: Into>, { let url: Url = url.into(); - let meta = provider::symlink_metadata(url).await?; - Ok(if meta.is_dir() { + let cha = provider::symlink_metadata(url).await?; + Ok(if cha.is_dir() { Self::Dir(VecDeque::from([Either::Left(url.to_owned())])) } else { - Self::File(Some(meta.len())) + Self::File(Some(cha.len)) }) } @@ -72,8 +72,8 @@ impl SizeCalculator { let Ok(ft) = ent.file_type().await else { continue }; if ft.is_dir() { buf.push_back(Either::Left(ent.url())); - } else if let Ok(meta) = ent.metadata().await { - size += meta.len(); + } else if let Ok(cha) = ent.metadata().await { + size += cha.len; } } Some(size) diff --git a/yazi-fs/src/provider/dir_entry.rs b/yazi-fs/src/provider/dir_entry.rs index df24a090..c5eabe75 100644 --- a/yazi-fs/src/provider/dir_entry.rs +++ b/yazi-fs/src/provider/dir_entry.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, ffi::OsStr, io}; use yazi_shared::url::UrlBuf; -use crate::provider::FileHolder; +use crate::{cha::Cha, provider::FileHolder}; pub enum DirEntry { Local(super::local::DirEntry), @@ -27,7 +27,7 @@ impl DirEntry { } } - pub async fn metadata(&self) -> io::Result { + pub async fn metadata(&self) -> io::Result { match self { Self::Local(local) => local.metadata().await, } diff --git a/yazi-fs/src/provider/local/dir_entry.rs b/yazi-fs/src/provider/local/dir_entry.rs index 706a5675..8f9ecffd 100644 --- a/yazi-fs/src/provider/local/dir_entry.rs +++ b/yazi-fs/src/provider/local/dir_entry.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, ffi::OsStr, io, path::PathBuf}; -use crate::provider::FileHolder; +use crate::{cha::Cha, provider::FileHolder}; pub struct DirEntry(pub(super) tokio::fs::DirEntry); @@ -9,7 +9,10 @@ impl FileHolder for DirEntry { fn name(&self) -> Cow<'_, OsStr> { self.0.file_name().into() } - async fn metadata(&self) -> io::Result { self.0.metadata().await } + async fn metadata(&self) -> io::Result { + let name = self.name(); // TODO: use `file_name_os_str` when stabilized + Ok(Cha::new(&name, self.0.metadata().await?)) + } async fn file_type(&self) -> io::Result { self.0.file_type().await } } diff --git a/yazi-fs/src/provider/local/local.rs b/yazi-fs/src/provider/local/local.rs index fe078fcf..1547db53 100644 --- a/yazi-fs/src/provider/local/local.rs +++ b/yazi-fs/src/provider/local/local.rs @@ -62,11 +62,12 @@ impl Provider for Local { } #[inline] - async fn metadata

(path: P) -> io::Result + async fn metadata

(path: P) -> io::Result where P: AsRef, { - tokio::fs::metadata(path).await + let path = path.as_ref(); + Ok(Cha::new(path.file_name().unwrap_or_default(), tokio::fs::metadata(path).await?)) } #[inline] @@ -170,11 +171,12 @@ impl Provider for Local { } #[inline] - async fn symlink_metadata

(path: P) -> io::Result + async fn symlink_metadata

(path: P) -> io::Result where P: AsRef, { - tokio::fs::symlink_metadata(path).await + let path = path.as_ref(); + Ok(Cha::new(path.file_name().unwrap_or_default(), tokio::fs::symlink_metadata(path).await?)) } async fn trash

(path: P) -> io::Result<()> diff --git a/yazi-fs/src/provider/provider.rs b/yazi-fs/src/provider/provider.rs index 197123ac..17a4ed86 100644 --- a/yazi-fs/src/provider/provider.rs +++ b/yazi-fs/src/provider/provider.rs @@ -125,7 +125,7 @@ where } #[inline] -pub async fn metadata<'a, U>(url: U) -> io::Result +pub async fn metadata<'a, U>(url: U) -> io::Result where U: Into>, { @@ -256,7 +256,7 @@ where } #[inline] -pub async fn symlink_metadata<'a, U>(url: U) -> io::Result +pub async fn symlink_metadata<'a, U>(url: U) -> io::Result where U: Into>, { diff --git a/yazi-fs/src/provider/sftp/read_dir.rs b/yazi-fs/src/provider/sftp/read_dir.rs index be753008..b55d5d39 100644 --- a/yazi-fs/src/provider/sftp/read_dir.rs +++ b/yazi-fs/src/provider/sftp/read_dir.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, ffi::OsStr, io, path::PathBuf}; -use crate::provider::{DirReader, FileHolder}; +use crate::{cha::Cha, provider::{DirReader, FileHolder}}; pub struct ReadDir(pub(super) yazi_sftp::fs::ReadDir); @@ -20,7 +20,7 @@ impl FileHolder for DirEntry<'_> { fn name(&self) -> Cow<'_, OsStr> { self.0.name() } - async fn metadata(&self) -> io::Result { todo!() } + async fn metadata(&self) -> io::Result { todo!() } async fn file_type(&self) -> io::Result { todo!() } } diff --git a/yazi-fs/src/provider/sftp/sftp.rs b/yazi-fs/src/provider/sftp/sftp.rs index c77b4875..ed5b916f 100644 --- a/yazi-fs/src/provider/sftp/sftp.rs +++ b/yazi-fs/src/provider/sftp/sftp.rs @@ -70,7 +70,7 @@ impl Provider for Sftp { Ok(Self::op().await?.hardlink(&original, &link).await?) } - async fn metadata

(path: P) -> io::Result + async fn metadata

(path: P) -> io::Result where P: AsRef, { @@ -122,7 +122,7 @@ impl Provider for Sftp { Ok(Self::op().await?.symlink(&original, &link).await?) } - async fn symlink_metadata

(path: P) -> io::Result + async fn symlink_metadata

(path: P) -> io::Result where P: AsRef, { diff --git a/yazi-fs/src/provider/traits.rs b/yazi-fs/src/provider/traits.rs index c8816edf..72a89518 100644 --- a/yazi-fs/src/provider/traits.rs +++ b/yazi-fs/src/provider/traits.rs @@ -67,7 +67,7 @@ pub trait Provider { P: AsRef, Q: AsRef; - fn metadata

(path: P) -> impl Future> + fn metadata

(path: P) -> impl Future> where P: AsRef; @@ -115,8 +115,8 @@ pub trait Provider { async move { let path = path.as_ref(); - let ft = ok_or_not_found!(Self::symlink_metadata(path).await, return Ok(())); - if ft.is_symlink() { + let cha = ok_or_not_found!(Self::symlink_metadata(path).await, return Ok(())); + if cha.is_link() { Self::remove_file(path).await } else { remove_dir_all_impl::(path).await @@ -155,7 +155,7 @@ pub trait Provider { Self::symlink(original, link, async || Ok(false)) } - fn symlink_metadata

(path: P) -> impl Future> + fn symlink_metadata

(path: P) -> impl Future> where P: AsRef; @@ -187,7 +187,7 @@ pub trait FileHolder { fn name(&self) -> Cow<'_, OsStr>; - fn metadata(&self) -> impl Future>; + fn metadata(&self) -> impl Future>; fn file_type(&self) -> impl Future>; } diff --git a/yazi-plugin/src/fs/fs.rs b/yazi-plugin/src/fs/fs.rs index 10661ad0..bffa46bb 100644 --- a/yazi-plugin/src/fs/fs.rs +++ b/yazi-plugin/src/fs/fs.rs @@ -50,14 +50,14 @@ fn cwd(lua: &Lua) -> mlua::Result { fn cha(lua: &Lua) -> mlua::Result { lua.create_async_function(|lua, (url, follow): (UrlRef, Option)| async move { - let meta = if follow.unwrap_or(false) { + let cha = if follow.unwrap_or(false) { provider::metadata(&*url).await } else { provider::symlink_metadata(&*url).await }; - match meta { - Ok(m) => Cha(yazi_fs::cha::Cha::new(&*url, m)).into_lua_multi(&lua), + match cha { + Ok(c) => Cha(c).into_lua_multi(&lua), Err(e) => (Value::Nil, Error::Io(e)).into_lua_multi(&lua), } }) @@ -129,8 +129,8 @@ fn read_dir(lua: &Lua) -> mlua::Result { let file = if !resolve { yazi_fs::File::from_dummy(url, next.file_type().await.ok()) - } else if let Ok(meta) = next.metadata().await { - yazi_fs::File::from_follow(url, meta).await + } else if let Ok(cha) = next.metadata().await { + yazi_fs::File::from_follow(url, cha).await } else { yazi_fs::File::from_dummy(url, next.file_type().await.ok()) }; diff --git a/yazi-scheduler/src/file/file.rs b/yazi-scheduler/src/file/file.rs index 6da31f3b..d60e8f41 100644 --- a/yazi-scheduler/src/file/file.rs +++ b/yazi-scheduler/src/file/file.rs @@ -71,7 +71,7 @@ impl File { let mut it = continue_unless_ok!(provider::read_dir(&src).await); while let Ok(Some(entry)) = it.next_entry().await { let from = entry.url(); - let cha = continue_unless_ok!(Self::cha_from(entry, &from, task.follow).await); + let cha = continue_unless_ok!(Self::entry_cha(entry, &from, task.follow).await); if cha.is_dir() { dirs.push_back(from); @@ -205,7 +205,7 @@ impl File { let mut it = continue_unless_ok!(provider::read_dir(&src).await); while let Ok(Some(entry)) = it.next_entry().await { let from = entry.url(); - let cha = continue_unless_ok!(Self::cha_from(entry, &from, task.follow).await); + let cha = continue_unless_ok!(Self::entry_cha(entry, &from, task.follow).await); if cha.is_dir() { dirs.push_back(from); @@ -237,11 +237,11 @@ impl File { } pub(crate) async fn delete(&self, mut task: FileInDelete) -> Result<(), FileOutDelete> { - let meta = provider::symlink_metadata(&task.target).await?; - if !meta.is_dir() { + let cha = provider::symlink_metadata(&task.target).await?; + if !cha.is_dir() { let id = task.id; - task.length = meta.len(); - self.ops.out(id, FileOutDelete::New(meta.len())); + task.length = cha.len; + self.ops.out(id, FileOutDelete::New(cha.len)); self.queue(task, NORMAL); self.ops.out(id, FileOutDelete::Init); return Ok(()); @@ -252,16 +252,16 @@ impl File { let Ok(mut it) = provider::read_dir(&target).await else { continue }; while let Ok(Some(entry)) = it.next_entry().await { - let Ok(meta) = entry.metadata().await else { continue }; + let Ok(cha) = entry.metadata().await else { continue }; - if meta.is_dir() { + if cha.is_dir() { dirs.push_front(entry.url()); continue; } task.target = entry.url(); - task.length = meta.len(); - self.ops.out(task.id, FileOutDelete::New(meta.len())); + task.length = cha.len; + self.ops.out(task.id, FileOutDelete::New(cha.len)); self.queue(task.clone(), NORMAL); } } @@ -291,16 +291,16 @@ impl File { #[inline] async fn cha<'a>(url: impl Into>, follow: bool) -> io::Result { let url = url.into(); - let meta = provider::symlink_metadata(url).await?; - Ok(if follow { Cha::from_follow(url, meta).await } else { Cha::new(url, meta) }) + let cha = provider::symlink_metadata(url).await?; + Ok(if follow { Cha::from_follow(url, cha).await } else { cha }) } #[inline] - async fn cha_from(entry: DirEntry, url: &UrlBuf, follow: bool) -> io::Result { + async fn entry_cha(entry: DirEntry, url: &UrlBuf, follow: bool) -> io::Result { Ok(if follow { Cha::from_follow(url, entry.metadata().await?).await } else { - Cha::new(url, entry.metadata().await?) + entry.metadata().await? }) } }