From ece59974fe2bc97bb9a4eeb4057034bea63b126d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20misaki=20masa?= Date: Wed, 17 Sep 2025 23:18:54 +0800 Subject: [PATCH] refactor: use `Cha` for better cross-platform consistency (#3174) --- Cargo.lock | 97 +++++++++++++------------ Cargo.toml | 6 +- yazi-binding/src/cha.rs | 18 ++--- yazi-boot/Cargo.toml | 2 +- yazi-cli/Cargo.toml | 2 +- yazi-cli/src/shared/shared.rs | 2 +- yazi-dds/src/state.rs | 6 +- yazi-fs/src/cha/cha.rs | 61 ++++++++++++---- yazi-fs/src/cha/kind.rs | 15 ++-- yazi-fs/src/file.rs | 12 +-- yazi-fs/src/files.rs | 4 +- yazi-fs/src/fns.rs | 2 +- yazi-fs/src/provider/calculator.rs | 10 +-- yazi-fs/src/provider/dir_entry.rs | 4 +- yazi-fs/src/provider/local/dir_entry.rs | 7 +- yazi-fs/src/provider/local/local.rs | 10 ++- yazi-fs/src/provider/provider.rs | 4 +- yazi-fs/src/provider/sftp/read_dir.rs | 4 +- yazi-fs/src/provider/sftp/sftp.rs | 16 ++-- yazi-fs/src/provider/traits.rs | 10 +-- yazi-plugin/src/fs/fs.rs | 10 +-- yazi-scheduler/src/file/file.rs | 28 +++---- 22 files changed, 175 insertions(+), 155 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 892b87a1..e93c75d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -549,9 +549,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.57" +version = "4.5.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d9501bd3f5f09f7bbee01da9a511073ed30a80cd7a509f1214bb74eadea71ad" +checksum = "75bf0b32ad2e152de789bb635ea4d3078f6b838ad7974143e99b99f45a04af4a" dependencies = [ "clap", ] @@ -1412,7 +1412,7 @@ dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.5+wasi-0.2.4", + "wasi 0.14.7+wasi-0.2.4", ] [[package]] @@ -1619,13 +1619,14 @@ checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" [[package]] name = "indexmap" -version = "2.11.1" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206a8042aec68fa4a62e8d3f7aa4ceb508177d9324faf261e1959e495b7a1921" +checksum = "92119844f513ffa41556430369ab02c295a3578af21cf945caa3e9e0c2481ac3" dependencies = [ "equivalent", "hashbrown 0.15.5", "serde", + "serde_core", ] [[package]] @@ -1778,9 +1779,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.78" +version = "0.3.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738" +checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e" dependencies = [ "once_cell", "wasm-bindgen", @@ -2561,9 +2562,9 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "plist" -version = "1.7.4" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af6b589e163c5a788fab00ce0c0366f6efbb9959c2f9874b224936af7fce7e1" +checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" dependencies = [ "base64", "indexmap", @@ -3202,9 +3203,9 @@ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "serde" -version = "1.0.223" +version = "1.0.225" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a505d71960adde88e293da5cb5eda57093379f64e61cf77bf0e6a63af07a7bac" +checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d" dependencies = [ "serde_core", "serde_derive", @@ -3222,18 +3223,18 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.223" +version = "1.0.225" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20f57cbd357666aa7b3ac84a90b4ea328f1d4ddb6772b430caa5d9e1309bb9e9" +checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.223" +version = "1.0.225" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d428d07faf17e306e699ec1e91996e5a165ba5d6bce5b5155173e91a8a01a56" +checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516" dependencies = [ "proc-macro2", "quote", @@ -3264,11 +3265,11 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +checksum = "2789234a13a53fc4be1b51ea1bab45a3c338bdb884862a257d10e5a74ae009e6" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -3715,14 +3716,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8" +checksum = "ae2a4cf385da23d1d53bc15cdfa5c2109e93d8d362393c801e87da2f72f0e201" dependencies = [ "indexmap", - "serde", - "serde_spanned 1.0.0", - "toml_datetime 0.7.0", + "serde_core", + "serde_spanned 1.0.1", + "toml_datetime 0.7.1", "toml_parser", "toml_writer", "winnow", @@ -3739,11 +3740,11 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +checksum = "a197c0ec7d131bfc6f7e82c8442ba1595aeab35da7adbf05b6b73cd06a16b6be" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -4045,27 +4046,27 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.14.5+wasi-0.2.4" +version = "0.14.7+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4494f6290a82f5fe584817a676a34b9d6763e8d9d18204009fb31dceca98fd4" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" dependencies = [ "wasip2", ] [[package]] name = "wasip2" -version = "1.0.0+wasi-0.2.4" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.101" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b" +checksum = "ab10a69fbd0a177f5f649ad4d8d3305499c42bab9aef2f7ff592d0ec8f833819" dependencies = [ "cfg-if", "once_cell", @@ -4076,9 +4077,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.101" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb" +checksum = "0bb702423545a6007bbc368fde243ba47ca275e549c8a28617f56f6ba53b1d1c" dependencies = [ "bumpalo", "log", @@ -4090,9 +4091,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.51" +version = "0.4.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca85039a9b469b38336411d6d6ced91f3fc87109a2a27b0c197663f5144dffe" +checksum = "a0b221ff421256839509adbb55998214a70d829d3a28c69b4a6672e9d2a42f67" dependencies = [ "cfg-if", "js-sys", @@ -4103,9 +4104,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.101" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d" +checksum = "fc65f4f411d91494355917b605e1480033152658d71f722a90647f56a70c88a0" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4113,9 +4114,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.101" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" +checksum = "ffc003a991398a8ee604a401e194b6b3a39677b3173d6e74495eb51b82e99a32" dependencies = [ "proc-macro2", "quote", @@ -4126,18 +4127,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.101" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1" +checksum = "293c37f4efa430ca14db3721dfbe48d8c33308096bd44d80ebaa775ab71ba1cf" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.78" +version = "0.3.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e4b637749ff0d92b8fad63aa1f7cff3cbe125fd49c175cd6345e7272638b12" +checksum = "fbe734895e869dc429d78c4b433f8d17d95f8d05317440b4fad5ab2d33e596dc" dependencies = [ "js-sys", "wasm-bindgen", @@ -4566,9 +4567,9 @@ checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" [[package]] name = "wit-bindgen" -version = "0.45.1" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "wyz" @@ -4693,7 +4694,7 @@ dependencies = [ "serde", "serde_json", "tokio", - "toml 0.9.5", + "toml 0.9.6", "twox-hash", "vergen-gitcl", "yazi-boot", @@ -4725,7 +4726,7 @@ dependencies = [ "ratatui", "regex", "serde", - "toml 0.9.5", + "toml 0.9.6", "tracing", "yazi-codegen", "yazi-fs", diff --git a/Cargo.toml b/Cargo.toml index 9671f764..0c9f6c48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ foldhash = "0.2.0" futures = "0.3.31" globset = "0.4.16" hashbrown = { version = "0.16.0", features = [ "serde" ] } -indexmap = { version = "2.11.1", features = [ "serde" ] } +indexmap = { version = "2.11.3", features = [ "serde" ] } libc = "0.2.175" lru = "0.16.1" mlua = { version = "0.11.3", features = [ "anyhow", "async", "error-send", "lua54", "macros", "serde" ] } @@ -44,13 +44,13 @@ ratatui = { version = "0.29.0", features = [ "unstable-rendered-line regex = "1.11.2" russh = { version = "0.54.3", default-features = false, features = [ "ring", "rsa" ] } scopeguard = "1.2.0" -serde = { version = "1.0.223", features = [ "derive" ] } +serde = { version = "1.0.225", features = [ "derive" ] } serde_json = "1.0.145" syntect = { version = "5.2.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] } tokio = { version = "1.47.1", features = [ "full" ] } tokio-stream = "0.1.17" tokio-util = "0.7.16" -toml = { version = "0.9.5" } +toml = { version = "0.9.6" } tracing = { version = "0.1.41", features = [ "max_level_debug", "release_max_level_debug" ] } unicode-width = { version = "0.2.0", default-features = false } twox-hash = { version = "2.1.2", default-features = false, features = [ "std", "random", "xxhash3_128" ] } diff --git a/yazi-binding/src/cha.rs b/yazi-binding/src/cha.rs index 8502603f..fe9b5176 100644 --- a/yazi-binding/src/cha.rs +++ b/yazi-binding/src/cha.rs @@ -1,4 +1,4 @@ -use std::{ops::Deref, time::{Duration, SystemTime, UNIX_EPOCH}}; +use std::{ops::Deref, time::{Duration, SystemTime}}; use mlua::{ExternalError, FromLua, IntoLua, Lua, Table, UserData, UserDataFields, UserDataMethods}; use yazi_fs::cha::{ChaKind, ChaMode}; @@ -66,18 +66,10 @@ impl UserData for Cha { fields.add_field_method_get("is_sticky", |_, me| Ok(me.is_sticky())); fields.add_field_method_get("len", |_, me| Ok(me.len)); - fields.add_field_method_get("atime", |_, me| { - Ok(me.atime.and_then(|t| t.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok())) - }); - fields.add_field_method_get("btime", |_, me| { - Ok(me.btime.and_then(|t| t.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok())) - }); - fields.add_field_method_get("ctime", |_, me| { - Ok(me.ctime.and_then(|t| t.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok())) - }); - fields.add_field_method_get("mtime", |_, me| { - Ok(me.mtime.and_then(|t| t.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok())) - }); + fields.add_field_method_get("atime", |_, me| Ok(me.atime_dur().ok().map(|d| d.as_secs_f64()))); + fields.add_field_method_get("btime", |_, me| Ok(me.btime_dur().ok().map(|d| d.as_secs_f64()))); + fields.add_field_method_get("ctime", |_, me| Ok(me.ctime_dur().ok().map(|d| d.as_secs_f64()))); + fields.add_field_method_get("mtime", |_, me| Ok(me.mtime_dur().ok().map(|d| d.as_secs_f64()))); fields.add_field_method_get("dev", |_, me| Ok(me.dev)); fields.add_field_method_get("uid", |_, me| Ok(me.uid)); fields.add_field_method_get("gid", |_, me| Ok(me.gid)); diff --git a/yazi-boot/Cargo.toml b/yazi-boot/Cargo.toml index 16620b54..2dc20fd2 100644 --- a/yazi-boot/Cargo.toml +++ b/yazi-boot/Cargo.toml @@ -27,7 +27,7 @@ yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External dependencies clap = { workspace = true } -clap_complete = "4.5.57" +clap_complete = "4.5.58" clap_complete_fig = "4.5.2" clap_complete_nushell = "4.5.8" vergen-gitcl = { version = "1.0.8", features = [ "build", "rustc" ] } diff --git a/yazi-cli/Cargo.toml b/yazi-cli/Cargo.toml index 8188fdb6..6351bc46 100644 --- a/yazi-cli/Cargo.toml +++ b/yazi-cli/Cargo.toml @@ -41,7 +41,7 @@ yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External build dependencies anyhow = { workspace = true } clap = { workspace = true } -clap_complete = "4.5.57" +clap_complete = "4.5.58" clap_complete_fig = "4.5.2" clap_complete_nushell = "4.5.8" serde_json = { workspace = true } diff --git a/yazi-cli/src/shared/shared.rs b/yazi-cli/src/shared/shared.rs index d12be9b5..76602662 100644 --- a/yazi-cli/src/shared/shared.rs +++ b/yazi-cli/src/shared/shared.rs @@ -34,7 +34,7 @@ pub async fn copy_and_seal(from: &Path, to: &Path) -> io::Result<()> { pub async fn remove_sealed(p: &Path) -> io::Result<()> { #[cfg(windows)] { - let mut perm = Local::metadata(p).await?.permissions(); + let mut perm = tokio::fs::metadata(p).await?.permissions(); perm.set_readonly(false); tokio::fs::set_permissions(p, perm).await?; } diff --git a/yazi-dds/src/state.rs b/yazi-dds/src/state.rs index ffb6baed..c33f0b6b 100644 --- a/yazi-dds/src/state.rs +++ b/yazi-dds/src/state.rs @@ -1,4 +1,4 @@ -use std::{mem, ops::Deref, sync::atomic::{AtomicU64, Ordering}, time::UNIX_EPOCH}; +use std::{mem, ops::Deref, sync::atomic::{AtomicU64, Ordering}}; use anyhow::Result; use hashbrown::HashMap; @@ -103,8 +103,8 @@ 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_dur()?.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..d6ed6b6e 100644 --- a/yazi-fs/src/cha/cha.rs +++ b/yazi-fs/src/cha/cha.rs @@ -1,5 +1,6 @@ -use std::{fs::{FileType, Metadata}, ops::Deref, time::SystemTime}; +use std::{ffi::OsStr, fs::{FileType, Metadata}, ops::Deref, time::{Duration, SystemTime, UNIX_EPOCH}}; +use anyhow::bail; use yazi_macro::{unix_either, win_either}; use yazi_shared::url::Url; @@ -47,11 +48,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 +58,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 retain = 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() { - attached |= ChaKind::ORPHAN; + if cha.is_link() { + retain |= ChaKind::ORPHAN; } - Self::from_bare(&meta).attach(attached) + cha.attach(retain) } pub fn from_dummy<'a, U>(_url: U, ft: Option) -> Self @@ -99,7 +96,7 @@ impl Cha { fn from_bare(m: &Metadata) -> Self { #[cfg(unix)] - use std::{os::unix::fs::MetadataExt, time::{Duration, UNIX_EPOCH}}; + use std::os::unix::fs::MetadataExt; #[cfg(unix)] let mode = { @@ -169,4 +166,36 @@ impl Cha { #[inline] pub const fn is_dummy(&self) -> bool { self.kind.contains(ChaKind::DUMMY) } + + pub fn atime_dur(&self) -> anyhow::Result { + if let Some(atime) = self.atime { + Ok(atime.duration_since(UNIX_EPOCH)?) + } else { + bail!("atime not supported on this platform"); + } + } + + pub fn mtime_dur(&self) -> anyhow::Result { + if let Some(mtime) = self.mtime { + Ok(mtime.duration_since(UNIX_EPOCH)?) + } else { + bail!("mtime not supported on this platform"); + } + } + + pub fn btime_dur(&self) -> anyhow::Result { + if let Some(btime) = self.btime { + Ok(btime.duration_since(UNIX_EPOCH)?) + } else { + bail!("btime not supported on this platform"); + } + } + + pub fn ctime_dur(&self) -> anyhow::Result { + if let Some(ctime) = self.ctime { + Ok(ctime.duration_since(UNIX_EPOCH)?) + } else { + bail!("ctime not supported on this platform"); + } + } } 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..f2924716 100644 --- a/yazi-fs/src/provider/sftp/sftp.rs +++ b/yazi-fs/src/provider/sftp/sftp.rs @@ -1,4 +1,4 @@ -use std::{io, path::{Path, PathBuf}, time::UNIX_EPOCH}; +use std::{io, path::{Path, PathBuf}}; use yazi_sftp::fs::{Attrs, Flags}; @@ -36,14 +36,8 @@ impl Provider for Sftp { uid: Some(cha.uid), gid: Some(cha.gid), perm: Some(cha.mode.bits() as _), - atime: cha - .atime - .and_then(|t| t.duration_since(UNIX_EPOCH).ok()) - .map(|d| d.as_secs() as u32), - mtime: cha - .mtime - .and_then(|t| t.duration_since(UNIX_EPOCH).ok()) - .map(|d| d.as_secs() as u32), + atime: cha.atime_dur().ok().map(|d| d.as_secs() as u32), + mtime: cha.mtime_dur().ok().map(|d| d.as_secs() as u32), extended: Default::default(), }; @@ -70,7 +64,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 +116,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? }) } }