diff --git a/Cargo.lock b/Cargo.lock index 6cb4202a..e947fed8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -159,7 +159,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -179,9 +179,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "av1-grain" @@ -351,9 +351,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.21" +version = "1.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +checksum = "3bbb537bb4a30b90362caddba8f360c0a56bc13d3a5570028e7197204cb54a17" dependencies = [ "jobserver", "libc", @@ -448,7 +448,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -627,7 +627,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -638,7 +638,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -668,7 +668,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -678,7 +678,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4abae7035bf79b9877b779505d8cf3749285b80c43941eda66604841889451dc" dependencies = [ "derive_builder_core", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -785,9 +785,9 @@ dependencies = [ [[package]] name = "fdeflate" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "d8090f921a24b04994d9929e204f50b498a33ea6ba559ffaa05e04f7ee7fb5ab" dependencies = [ "simd-adler32", ] @@ -827,9 +827,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -924,7 +924,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1170,7 +1170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" dependencies = [ "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1190,7 +1190,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1290,9 +1290,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libfuzzer-sys" @@ -1413,7 +1413,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", - "simd-adler32", ] [[package]] @@ -1423,6 +1422,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ "adler2", + "simd-adler32", ] [[package]] @@ -1493,7 +1493,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1586,7 +1586,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1672,9 +1672,12 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] [[package]] name = "onig" @@ -1793,17 +1796,23 @@ dependencies = [ [[package]] name = "png" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" dependencies = [ "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.7.4", + "miniz_oxide 0.8.0", ] +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + [[package]] name = "powerfmt" version = "0.2.0" @@ -1868,7 +1877,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" dependencies = [ "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2026,9 +2035,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] @@ -2046,9 +2055,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", @@ -2058,9 +2067,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -2069,9 +2078,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rgb" @@ -2161,7 +2170,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2178,9 +2187,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -2334,7 +2343,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2349,9 +2358,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -2415,7 +2424,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2533,7 +2542,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2584,9 +2593,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.21" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "serde", @@ -2626,7 +2635,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2808,7 +2817,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2905,7 +2914,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-shared", ] @@ -2927,7 +2936,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3026,7 +3035,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3037,7 +3046,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -3199,9 +3208,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -3493,7 +3502,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 64668a31..f5047133 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,12 +20,12 @@ crossterm = { version = "0.28.1", features = [ "event-stream" ] } dirs = "5.0.1" futures = "0.3.30" globset = "0.4.15" -libc = "0.2.158" +libc = "0.2.159" md-5 = "0.10.6" mlua = { version = "0.9.9", features = [ "lua54", "serialize", "macros", "async" ] } parking_lot = "0.12.3" ratatui = { version = "0.28.1", features = [ "unstable-rendered-line-info" ] } -regex = "1.10.6" +regex = "1.11.0" scopeguard = "1.2.0" serde = { version = "1.0.210", features = [ "derive" ] } serde_json = "1.0.128" diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 28a77c1f..a8ea3d12 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -7,7 +7,7 @@ description: | It aims to provide an efficient, user-friendly, and customizable file management experience. license: MIT grade: stable -confinement: strict +confinement: classic platforms: amd64: diff --git a/yazi-cli/Cargo.toml b/yazi-cli/Cargo.toml index 0b87229f..cc068dd9 100644 --- a/yazi-cli/Cargo.toml +++ b/yazi-cli/Cargo.toml @@ -20,7 +20,7 @@ crossterm = { workspace = true } md-5 = { workspace = true } serde_json = { workspace = true } tokio = { workspace = true } -toml_edit = "0.22.21" +toml_edit = "0.22.22" [build-dependencies] # External build dependencies diff --git a/yazi-core/src/manager/commands/bulk_rename.rs b/yazi-core/src/manager/commands/bulk_rename.rs index 0f4d7d1d..16595336 100644 --- a/yazi-core/src/manager/commands/bulk_rename.rs +++ b/yazi-core/src/manager/commands/bulk_rename.rs @@ -6,7 +6,7 @@ use tokio::{fs::{self, OpenOptions}, io::{AsyncReadExt, AsyncWriteExt, stdin}}; use yazi_config::{OPEN, PREVIEW}; use yazi_dds::Pubsub; use yazi_proxy::{AppProxy, HIDER, TasksProxy, WATCHER}; -use yazi_shared::{fs::{File, Url, max_common_root, maybe_exists, paths_to_same_file}, terminal_clear}; +use yazi_shared::{fs::{File, FilesOp, Url, max_common_root, maybe_exists, paths_to_same_file}, terminal_clear}; use crate::manager::Manager; @@ -16,7 +16,6 @@ impl Manager { return AppProxy::notify_warn("Bulk rename", "No text opener found"); }; - let cwd = self.cwd().to_owned(); let old: Vec<_> = self.selected_or_hovered(true).collect(); let root = max_common_root(&old); @@ -42,16 +41,11 @@ impl Manager { AppProxy::stop().await; let new: Vec<_> = fs::read_to_string(&tmp).await?.lines().map(PathBuf::from).collect(); - Self::bulk_rename_do(cwd, root, old, new).await + Self::bulk_rename_do(root, old, new).await }); } - async fn bulk_rename_do( - cwd: Url, - root: PathBuf, - old: Vec, - new: Vec, - ) -> Result<()> { + async fn bulk_rename_do(root: PathBuf, old: Vec, new: Vec) -> Result<()> { terminal_clear(&mut stderr())?; if old.len() != new.len() { eprintln!("Number of old and new differ, press ENTER to exit"); @@ -95,11 +89,9 @@ impl Manager { } } - // FIXME: consider old and new in the different directories if !succeeded.is_empty() { - Pubsub::pub_from_bulk(succeeded.iter().map(|(u, f)| (u, &f.url)).collect()); - // FIXME 0 - // FilesOp::Upserting(cwd, succeeded).emit(); + Pubsub::pub_from_bulk(succeeded.iter().map(|(o, n)| (o, &n.url)).collect()); + FilesOp::rename(succeeded); } drop(permit); diff --git a/yazi-core/src/manager/commands/create.rs b/yazi-core/src/manager/commands/create.rs index 1ea36b0e..60f2cc8d 100644 --- a/yazi-core/src/manager/commands/create.rs +++ b/yazi-core/src/manager/commands/create.rs @@ -50,7 +50,7 @@ impl Manager { fs::create_dir_all(&new).await?; } else if let Some(real) = realname(&new).await { ok_or_not_found(fs::remove_file(&new).await)?; - FilesOp::Deleting(parent.clone(), HashSet::from_iter([UrnBuf::_from(real)])).emit(); + FilesOp::Deleting(parent.clone(), HashSet::from_iter([UrnBuf::from(real)])).emit(); fs::File::create(&new).await?; } else { fs::create_dir_all(&parent).await.ok(); diff --git a/yazi-core/src/manager/commands/rename.rs b/yazi-core/src/manager/commands/rename.rs index feaa06ac..06412ba7 100644 --- a/yazi-core/src/manager/commands/rename.rs +++ b/yazi-core/src/manager/commands/rename.rs @@ -83,7 +83,7 @@ impl Manager { if let Some(o) = overwritten { ok_or_not_found(fs::rename(p_new.join(&o), &new).await)?; - FilesOp::Deleting(p_new.clone(), HashSet::from_iter([UrnBuf::_from(o)])).emit(); + FilesOp::Deleting(p_new.clone(), HashSet::from_iter([UrnBuf::from(o)])).emit(); } Pubsub::pub_from_rename(tab, &old, &new); diff --git a/yazi-core/src/manager/commands/update_files.rs b/yazi-core/src/manager/commands/update_files.rs index 909b803e..75b4c088 100644 --- a/yazi-core/src/manager/commands/update_files.rs +++ b/yazi-core/src/manager/commands/update_files.rs @@ -64,7 +64,7 @@ impl Manager { if let Some(f) = tab.parent.as_mut() { render!(f.update(op.into_owned())); - render!(f.hover(urn._deref())); + render!(f.hover(urn.as_urn())); } if leave { @@ -81,7 +81,7 @@ impl Manager { return; } - tab.current.repos(hovered.as_ref().map(|u| u._deref())); + tab.current.repos(hovered.as_ref().map(|u| u.as_urn())); if foreign { return; } @@ -115,7 +115,7 @@ impl Manager { let folder = tab.history.entry(op.cwd().clone()).or_insert_with(|| Folder::from(op.cwd())); let hovered = folder.hovered().filter(|_| folder.tracing).map(|h| h.urn_owned()); if folder.update(op.into_owned()) { - folder.repos(hovered.as_ref().map(|u| u._deref())); + folder.repos(hovered.as_ref().map(|u| u.as_urn())); } if leave { diff --git a/yazi-core/src/manager/watcher.rs b/yazi-core/src/manager/watcher.rs index 88d06924..26e5f26c 100644 --- a/yazi-core/src/manager/watcher.rs +++ b/yazi-core/src/manager/watcher.rs @@ -133,7 +133,7 @@ impl Watcher { let u = &file.url; let eq = (!file.is_link() && fs::canonicalize(u).await.is_ok_and(|p| p == ***u)) - || realname_unchecked(u, &mut cached).await.is_ok_and(|s| s == urn._deref()._as_path()); + || realname_unchecked(u, &mut cached).await.is_ok_and(|s| urn.as_urn() == s); if !eq { FilesOp::Deleting(parent, HashSet::from_iter([urn])).emit(); diff --git a/yazi-core/src/tab/commands/filter.rs b/yazi-core/src/tab/commands/filter.rs index 0302c864..5be874bd 100644 --- a/yazi-core/src/tab/commands/filter.rs +++ b/yazi-core/src/tab/commands/filter.rs @@ -70,8 +70,8 @@ impl Tab { return; } - self.current.repos(hovered.as_ref().map(|u| u._deref())); - if self.current.hovered().map(|f| f.urn()) != hovered.as_ref().map(|u| u._deref()) { + self.current.repos(hovered.as_ref().map(|u| u.as_urn())); + if self.current.hovered().map(|f| f.urn()) != hovered.as_ref().map(|u| u.as_urn()) { ManagerProxy::hover(None, self.idx); } diff --git a/yazi-core/src/tab/tab.rs b/yazi-core/src/tab/tab.rs index 6cac3e96..83f39f1a 100644 --- a/yazi-core/src/tab/tab.rs +++ b/yazi-core/src/tab/tab.rs @@ -102,7 +102,7 @@ impl Tab { f.files.set_sorter(self.conf.sorter()); render!(f.files.catchup_revision()); - render!(f.repos(hovered.as_ref().map(|u| u._deref()))); + render!(f.repos(hovered.as_ref().map(|u| u.as_urn()))); }; apply(&mut self.current); diff --git a/yazi-fs/src/files.rs b/yazi-fs/src/files.rs index 5143bd8e..944b8c51 100644 --- a/yazi-fs/src/files.rs +++ b/yazi-fs/src/files.rs @@ -214,13 +214,13 @@ impl Files { let (mut hidden, mut items) = if let Some(filter) = &self.filter { urns.into_iter().partition(|u| { - (!self.show_hidden && u._deref().is_hidden()) - || !u._deref().name().is_some_and(|s| filter.matches(s)) + (!self.show_hidden && u.as_urn().is_hidden()) + || !u.as_urn().name().is_some_and(|s| filter.matches(s)) }) } else if self.show_hidden { (HashSet::new(), urns) } else { - urns.into_iter().partition(|u| u._deref().is_hidden()) + urns.into_iter().partition(|u| u.as_urn().is_hidden()) }; if !items.is_empty() { diff --git a/yazi-plugin/preset/plugins/mime.lua b/yazi-plugin/preset/plugins/mime.lua index c74be89d..4403d663 100644 --- a/yazi-plugin/preset/plugins/mime.lua +++ b/yazi-plugin/preset/plugins/mime.lua @@ -59,28 +59,4 @@ function M:fetch() return j == #urls and 3 or 2 end --- TODO: remove this after v0.3 release -local notified = ya.sync(function (state) - if state.notified then - return true - else - state.notified = true - return false - end -end) -function M:preload() - if notified() then - return 1 - end - ya.notify { - title = "Error", - content = [[In Yazi v0.3, the `mime` plugin has been re-classified as a fetcher. Please remove it from the `preloaders` of your yazi.toml - -See https://github.com/sxyazi/yazi/issues/1046 for details.]], - timeout = 20, - level = "error", - } - return 1 -end - return M diff --git a/yazi-plugin/src/fs/fs.rs b/yazi-plugin/src/fs/fs.rs index 07d9136c..ca6544ca 100644 --- a/yazi-plugin/src/fs/fs.rs +++ b/yazi-plugin/src/fs/fs.rs @@ -111,9 +111,10 @@ pub fn install(lua: &Lua) -> mlua::Result<()> { ( "unique_name", lua.create_async_function(|lua, url: UrlRef| async move { - // FIXME: should return a `std::io::Result` to handle errors such as - // permission denied - Url::cast(lua, yazi_shared::fs::unique_name(url.clone()).await) + match yazi_shared::fs::unique_name(url.clone()).await { + Ok(u) => (Url::cast(lua, u)?, Value::Nil).into_lua_multi(lua), + Err(e) => (Value::Nil, e.raw_os_error()).into_lua_multi(lua), + } })?, ), ])?, diff --git a/yazi-scheduler/src/prework/prework.rs b/yazi-scheduler/src/prework/prework.rs index a936d208..2d93b9cc 100644 --- a/yazi-scheduler/src/prework/prework.rs +++ b/yazi-scheduler/src/prework/prework.rs @@ -92,8 +92,11 @@ impl Prework { } let parent = buf[0].0.parent_url().unwrap(); - // FIXME 0 - // FilesOp::Size(parent, HashMap::from_iter(buf)).emit(); + FilesOp::Size( + parent, + HashMap::from_iter(buf.into_iter().map(|(u, s)| (u.urn_owned(), s))), + ) + .emit(); }); self.prog.send(TaskProg::Adv(task.id, 1, 0))?; } diff --git a/yazi-scheduler/src/scheduler.rs b/yazi-scheduler/src/scheduler.rs index 644918e4..60ab3194 100644 --- a/yazi-scheduler/src/scheduler.rs +++ b/yazi-scheduler/src/scheduler.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, ffi::OsString, sync::Arc, time::Duration}; +use std::{borrow::Cow, ffi::OsString, future::Future, sync::Arc, time::Duration}; use anyhow::Result; use futures::{FutureExt, future::BoxFuture}; @@ -95,19 +95,12 @@ impl Scheduler { }); let file = self.file.clone(); - _ = self.micro.try_send( - async move { - if !force { - to = unique_name(to).await; - } - file - .paste(FileOpPaste { id, from, to, meta: None, cut: true, follow: false, retry: 0 }) - .await - .ok(); + self.send_micro(id, LOW, async move { + if !force { + to = unique_name(to).await?; } - .boxed(), - LOW, - ); + file.paste(FileOpPaste { id, from, to, meta: None, cut: true, follow: false, retry: 0 }).await + }); } pub fn file_copy(&self, from: Url, mut to: Url, force: bool, follow: bool) { @@ -120,19 +113,12 @@ impl Scheduler { } let file = self.file.clone(); - _ = self.micro.try_send( - async move { - if !force { - to = unique_name(to).await; - } - file - .paste(FileOpPaste { id, from, to, meta: None, cut: false, follow, retry: 0 }) - .await - .ok(); + self.send_micro(id, LOW, async move { + if !force { + to = unique_name(to).await?; } - .boxed(), - LOW, - ); + file.paste(FileOpPaste { id, from, to, meta: None, cut: false, follow, retry: 0 }).await + }); } pub fn file_link(&self, from: Url, mut to: Url, relative: bool, force: bool) { @@ -140,19 +126,14 @@ impl Scheduler { let id = self.ongoing.lock().add(TaskKind::User, name); let file = self.file.clone(); - _ = self.micro.try_send( - async move { - if !force { - to = unique_name(to).await; - } - file - .link(FileOpLink { id, from, to, meta: None, resolve: false, relative, delete: false }) - .await - .ok(); + self.send_micro(id, LOW, async move { + if !force { + to = unique_name(to).await?; } - .boxed(), - LOW, - ); + file + .link(FileOpLink { id, from, to, meta: None, resolve: false, relative, delete: false }) + .await + }); } pub fn file_hardlink(&self, from: Url, mut to: Url, force: bool, follow: bool) { @@ -165,16 +146,12 @@ impl Scheduler { } let file = self.file.clone(); - _ = self.micro.try_send( - async move { - if !force { - to = unique_name(to).await; - } - file.hardlink(FileOpHardlink { id, from, to, meta: None, follow }).await.ok(); + self.send_micro(id, LOW, async move { + if !force { + to = unique_name(to).await?; } - .boxed(), - LOW, - ); + file.hardlink(FileOpHardlink { id, from, to, meta: None, follow }).await + }); } pub fn file_delete(&self, target: Url) { @@ -199,12 +176,10 @@ impl Scheduler { }); let file = self.file.clone(); - _ = self.micro.try_send( - async move { - file.delete(FileOpDelete { id, target, length: 0 }).await.ok(); - } - .boxed(), + self.send_micro( + id, LOW, + async move { file.delete(FileOpDelete { id, target, length: 0 }).await }, ); } @@ -229,25 +204,19 @@ impl Scheduler { }); let file = self.file.clone(); - _ = self.micro.try_send( - async move { - file.trash(FileOpTrash { id, target: target.clone(), length: 0 }).await.ok(); - } - .boxed(), - LOW, - ); + self.send_micro(id, LOW, async move { + file.trash(FileOpTrash { id, target: target.clone(), length: 0 }).await + }) } pub fn plugin_micro(&self, name: String, args: Vec) { let id = self.ongoing.lock().add(TaskKind::User, format!("Run micro plugin `{name}`")); let plugin = self.plugin.clone(); - _ = self.micro.try_send( - async move { - plugin.micro(PluginOpEntry { id, name, args }).await.ok(); - } - .boxed(), + self.send_micro( + id, NORMAL, + async move { plugin.micro(PluginOpEntry { id, name, args }).await }, ); } @@ -265,13 +234,9 @@ impl Scheduler { let plugin = fetcher.into(); let prework = self.prework.clone(); - _ = self.micro.try_send( - async move { - prework.fetch(PreworkOpFetch { id, plugin, targets }).await.ok(); - } - .boxed(), - NORMAL, - ); + self.send_micro(id, NORMAL, async move { + prework.fetch(PreworkOpFetch { id, plugin, targets }).await + }); } pub fn preload_paged(&self, preloader: &Preloader, target: &yazi_shared::fs::File) { @@ -281,12 +246,10 @@ impl Scheduler { let plugin = preloader.into(); let target = target.clone(); let prework = self.prework.clone(); - _ = self.micro.try_send( - async move { - prework.load(PreworkOpLoad { id, plugin, target }).await.ok(); - } - .boxed(), + self.send_micro( + id, NORMAL, + async move { prework.load(PreworkOpLoad { id, plugin, target }).await }, ); } @@ -300,13 +263,9 @@ impl Scheduler { let throttle = throttle.clone(); let prework = self.prework.clone(); - _ = self.micro.try_send( - async move { - prework.size(PreworkOpSize { id, target, throttle }).await.ok(); - } - .boxed(), - NORMAL, - ); + self.send_micro(id, NORMAL, async move { + prework.size(PreworkOpSize { id, target, throttle }).await + }); } } @@ -348,19 +307,15 @@ impl Scheduler { let cmd = OsString::from(&opener.run); let process = self.process.clone(); - _ = self.micro.try_send( - async move { - if opener.block { - process.block(ProcessOpBlock { id, cmd, args }).await.ok(); - } else if opener.orphan { - process.orphan(ProcessOpOrphan { id, cmd, args }).await.ok(); - } else { - process.bg(ProcessOpBg { id, cmd, args, cancel: cancel_rx }).await.ok(); - } + self.send_micro(id, NORMAL, async move { + if opener.block { + process.block(ProcessOpBlock { id, cmd, args }).await + } else if opener.orphan { + process.orphan(ProcessOpOrphan { id, cmd, args }).await + } else { + process.bg(ProcessOpBg { id, cmd, args, cancel: cancel_rx }).await } - .boxed(), - NORMAL, - ); + }); } fn schedule_micro( @@ -471,6 +426,23 @@ impl Scheduler { }) } + fn send_micro(&self, id: usize, priority: u8, f: F) + where + F: Future> + Send + 'static, + { + let prog = self.prog.clone(); + _ = self.micro.try_send( + async move { + if let Err(e) = f.await { + prog.send(TaskProg::New(id, 0)).ok(); + prog.send(TaskProg::Fail(id, format!("Task initialization failed:\n{e}"))).ok(); + } + } + .boxed(), + priority, + ); + } + fn new_and_fail(&self, id: usize, reason: &str) -> Result<()> { self.prog.send(TaskProg::New(id, 0))?; self.prog.send(TaskProg::Fail(id, reason.to_owned()))?; diff --git a/yazi-shared/src/fs/loc.rs b/yazi-shared/src/fs/loc.rs index 8bdea196..190e6be7 100644 --- a/yazi-shared/src/fs/loc.rs +++ b/yazi-shared/src/fs/loc.rs @@ -22,7 +22,7 @@ impl Clone for Loc { fn clone(&self) -> Self { let path = self.path.clone(); let name = path.file_name().unwrap_or(OsStr::new("")) as *const OsStr; - let urn = if self.urn()._as_path() == self.name() { name } else { self.twin_urn(&path) }; + let urn = if self.urn() == self.name() { name } else { self.twin_urn(&path) }; Self { path, urn, name } } } @@ -75,14 +75,14 @@ impl Loc { pub fn base(&self) -> &Path { let mut it = self.path.components(); - for _ in 0..self.urn()._as_path().components().count() { + for _ in 0..self.urn().components().count() { it.next_back().unwrap(); } it.as_path() } pub fn rebase(&self, parent: &Path) -> Self { - debug_assert!(self.urn()._as_path() == self.name()); + debug_assert!(self.urn() == self.name()); let path = parent.join(self.name()); let name = path.file_name().unwrap_or(OsStr::new("")) as *const OsStr; @@ -92,7 +92,7 @@ impl Loc { #[inline] fn twin_urn<'a>(&self, new: &'a Path) -> &'a OsStr { let total = new.components().count(); - let take = self.urn()._as_path().components().count(); + let take = self.urn().components().count(); let mut it = new.components(); for _ in 0..total - take { diff --git a/yazi-shared/src/fs/op.rs b/yazi-shared/src/fs/op.rs index b51e86dd..98a2b54e 100644 --- a/yazi-shared/src/fs/op.rs +++ b/yazi-shared/src/fs/op.rs @@ -47,6 +47,30 @@ impl FilesOp { ticket } + pub fn rename(map: HashMap) { + let mut parents = HashMap::new(); + for (o, n) in map { + let Some(o_p) = o.parent_url() else { continue }; + if o == n.url { + parents.entry(o_p).or_insert((HashSet::new(), HashMap::new())).1.insert(o.urn_owned(), n); + } else if let Some(n_p) = n.url.parent_url() { + parents.entry(o_p).or_insert((HashSet::new(), HashMap::new())).0.insert(o.urn_owned()); + parents.entry(n_p).or_insert((HashSet::new(), HashMap::new())).1.insert(n.urn_owned(), n); + } + } + for (p, (o, n)) in parents { + match (o.is_empty(), n.is_empty()) { + (true, true) => unreachable!(), + (true, false) => Self::Upserting(p, n).emit(), + (false, true) => Self::Deleting(p, o).emit(), + (false, false) => { + Self::Deleting(p.clone(), o).emit(); + Self::Upserting(p, n).emit(); + } + } + } + } + pub fn rebase(&self, new: &Url) -> Self { macro_rules! files { ($files:expr) => {{ $files.iter().map(|f| f.rebase(new)).collect() }}; @@ -72,13 +96,11 @@ impl FilesOp { pub fn diff_recoverable(&self, contains: impl Fn(&Url) -> bool) -> (Vec, Vec) { match self { - Self::Deleting(cwd, urns) => { - (urns.iter().map(|u| cwd.join(u._deref()._as_path())).collect(), vec![]) - } + Self::Deleting(cwd, urns) => (urns.iter().map(|u| cwd.join(u)).collect(), vec![]), Self::Updating(cwd, urns) | Self::Upserting(cwd, urns) => urns .iter() .filter(|&(u, f)| u != f.urn()) - .map(|(u, f)| (cwd.join(u._deref()._as_path()), f)) + .map(|(u, f)| (cwd.join(u), f)) .filter(|(u, _)| contains(u)) .map(|(u, f)| (u, f.url_owned())) .unzip(), diff --git a/yazi-shared/src/fs/path.rs b/yazi-shared/src/fs/path.rs index f6fedaad..592e4f17 100644 --- a/yazi-shared/src/fs/path.rs +++ b/yazi-shared/src/fs/path.rs @@ -1,6 +1,8 @@ -use std::{borrow::Cow, env, ffi::OsString, path::{Component, Path, PathBuf}}; +use std::{borrow::Cow, env, ffi::OsString, io, path::{Component, Path, PathBuf}}; -use super::maybe_exists; +use tokio::fs; + +use super::Loc; use crate::fs::Url; pub fn current_cwd() -> Option { @@ -72,9 +74,9 @@ fn _expand_path(p: &Path) -> PathBuf { } } -pub async fn unique_name(mut u: Url) -> Url { +pub async fn unique_name(mut u: Url) -> io::Result { let Some(stem) = u.file_stem().map(|s| s.to_owned()) else { - return u; + return Err(io::Error::new(io::ErrorKind::InvalidInput, "empty file stem")); }; let ext = u @@ -88,8 +90,14 @@ pub async fn unique_name(mut u: Url) -> Url { .unwrap_or_default(); let mut i = 1u64; - let mut p = u.into_path(); - while maybe_exists(&p).await { + let mut p = u.to_path(); + loop { + match fs::symlink_metadata(&p).await { + Ok(_) => {} + Err(e) if e.kind() == io::ErrorKind::NotFound => break, + Err(e) => return Err(e), + } + let mut name = OsString::with_capacity(stem.len() + ext.len() + 5); name.push(&stem); name.push("_"); @@ -99,8 +107,9 @@ pub async fn unique_name(mut u: Url) -> Url { p.set_file_name(name); i += 1; } - // FIXME 3: handle base path - Url::from(p) + + u.set_loc(Loc::from(u.base(), p)); + Ok(u) } // Parameters diff --git a/yazi-shared/src/fs/url.rs b/yazi-shared/src/fs/url.rs index bebe9288..6d8264ca 100644 --- a/yazi-shared/src/fs/url.rs +++ b/yazi-shared/src/fs/url.rs @@ -239,7 +239,13 @@ impl Url { self } - // --- Path + // --- Loc + #[inline] + pub fn set_loc(&mut self, loc: Loc) { self.loc = loc; } + + #[inline] + pub fn to_path(&self) -> PathBuf { self.loc.to_path_buf() } + #[inline] pub fn into_path(self) -> PathBuf { self.loc.into_path() } diff --git a/yazi-shared/src/fs/urn.rs b/yazi-shared/src/fs/urn.rs index c4b6d66f..29fba9e1 100644 --- a/yazi-shared/src/fs/urn.rs +++ b/yazi-shared/src/fs/urn.rs @@ -1,11 +1,11 @@ -use std::{borrow::Borrow, ffi::OsStr, path::{Path, PathBuf}}; +use std::{borrow::{Borrow, Cow}, ffi::OsStr, ops::Deref, path::{Path, PathBuf}}; #[derive(Debug, Eq, PartialEq, Hash)] #[repr(transparent)] pub struct Urn(Path); impl Urn { - // TODO: clean this up + #[inline] pub fn new + ?Sized>(p: &T) -> &Self { unsafe { &*(p.as_ref() as *const Path as *const Self) } } @@ -18,9 +18,16 @@ impl Urn { pub fn is_hidden(&self) -> bool { self.name().map_or(false, |s| s.as_encoded_bytes().starts_with(b".")) } +} - // FIXME 1: remove this - pub fn _as_path(&self) -> &Path { &self.0 } +impl Deref for Urn { + type Target = Path; + + fn deref(&self) -> &Self::Target { &self.0 } +} + +impl AsRef for Urn { + fn as_ref(&self) -> &Path { &self.0 } } impl ToOwned for Urn { @@ -29,6 +36,14 @@ impl ToOwned for Urn { fn to_owned(&self) -> Self::Owned { UrnBuf(self.0.to_owned()) } } +impl PartialEq for Urn { + fn eq(&self, other: &OsStr) -> bool { self.0 == other } +} + +impl PartialEq> for &Urn { + fn eq(&self, other: &Cow) -> bool { self.0 == other.as_ref() } +} + // --- UrnBuf #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct UrnBuf(PathBuf); @@ -37,14 +52,19 @@ impl Borrow for UrnBuf { fn borrow(&self) -> &Urn { Urn::new(&self.0) } } +impl AsRef for UrnBuf { + fn as_ref(&self) -> &Path { &self.0 } +} + impl PartialEq for UrnBuf { fn eq(&self, other: &Urn) -> bool { self.0 == other.0 } } -impl UrnBuf { - // FIXME 1: remove this - pub fn _deref(&self) -> &Urn { Urn::new(&self.0) } - - // FIXME 1: remove this - pub fn _from(p: impl Into) -> Self { Self(p.into()) } +impl> From for UrnBuf { + fn from(p: T) -> Self { Self(p.into()) } +} + +impl UrnBuf { + #[inline] + pub fn as_urn(&self) -> &Urn { self.borrow() } }