From fa1a5377fdf9923346bb1a8a54ac729d0df1e197 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Sat, 14 Dec 2024 13:17:16 +0800 Subject: [PATCH 1/2] fix: set the current working directory in a thread-safe way --- Cargo.lock | 20 ++++++++--------- README.md | 2 +- yazi-fs/src/cwd.rs | 42 ++++++++++++++++++++++++++--------- yazi-plugin/src/utils/user.rs | 11 +-------- yazi-shared/src/os.rs | 9 +++++++- 5 files changed, 52 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4680377e7..06a3995a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -272,9 +272,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" +checksum = "786a307d683a5bf92e6fd5fd69a7eb613751668d1d8d67d802846dfe367c62c8" dependencies = [ "memchr", "serde", @@ -333,9 +333,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.3" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" +checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" dependencies = [ "jobserver", "libc", @@ -2119,9 +2119,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] @@ -2250,9 +2250,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "serde" @@ -3738,9 +3738,9 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768" +checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" dependencies = [ "zune-core", ] diff --git a/README.md b/README.md index e580b191f..b9869ddfd 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Yazi (means "duck") is a terminal file manager written in Rust, based on non-blo - 💫 Vim-like input/pick/confirm/which/notify component, auto-completion for cd paths - 🏷️ Multi-Tab Support, Cross-directory selection, Scrollable Preview (for videos, PDFs, archives, code, directories, etc.) - 🔄 Bulk Renaming, Visual Mode, File Chooser -- 🎨 Theme System, Mouse Support, Trash Bin, Custom Layouts, CSI u +- 🎨 Theme System, Mouse Support, Trash Bin, Custom Layouts, CSI u, OSC 52 - ... and more! https://github.com/sxyazi/yazi/assets/17523360/92ff23fa-0cd5-4f04-b387-894c12265cc7 diff --git a/yazi-fs/src/cwd.rs b/yazi-fs/src/cwd.rs index 2acb6402e..8b360e417 100644 --- a/yazi-fs/src/cwd.rs +++ b/yazi-fs/src/cwd.rs @@ -1,18 +1,16 @@ -use std::{ops::Deref, path::PathBuf, sync::Arc}; +use std::{env::{current_dir, set_current_dir}, ops::Deref, path::PathBuf, sync::{Arc, atomic::{self, AtomicBool}}}; use arc_swap::ArcSwap; use yazi_shared::{RoCell, url::Url}; pub static CWD: RoCell = RoCell::new(); -pub struct Cwd { - inner: ArcSwap, -} +pub struct Cwd(ArcSwap); impl Deref for Cwd { type Target = ArcSwap; - fn deref(&self) -> &Self::Target { &self.inner } + fn deref(&self) -> &Self::Target { &self.0 } } impl Default for Cwd { @@ -20,16 +18,40 @@ impl Default for Cwd { let p = std::env::var_os("PWD") .map(PathBuf::from) .filter(|p| p.is_absolute()) - .or_else(|| std::env::current_dir().ok()) + .or_else(|| current_dir().ok()) .expect("failed to get current working directory"); - Self { inner: ArcSwap::new(Arc::new(Url::from(p))) } + Self(ArcSwap::new(Arc::new(Url::from(p)))) } } impl Cwd { - pub fn set(&self, url: &Url) { - self.inner.store(Arc::new(url.clone())); - std::env::set_var("PWD", self.inner.load().as_ref()); + pub fn set(&self, url: &Url) -> bool { + if self.load().as_ref() == url { + return false; + } + + self.store(Arc::new(url.clone())); + std::env::set_var("PWD", url); + + Self::sync_cwd(); + true + } + + fn sync_cwd() { + static SYNCING: AtomicBool = AtomicBool::new(false); + if SYNCING.swap(true, atomic::Ordering::Relaxed) { + return; + } + + tokio::task::spawn_blocking(move || { + _ = set_current_dir(CWD.load().as_ref()); + let p = current_dir().unwrap_or_default(); + + SYNCING.store(false, atomic::Ordering::Relaxed); + if p != CWD.load().as_path() { + set_current_dir(CWD.load().as_ref()).ok(); + } + }); } } diff --git a/yazi-plugin/src/utils/user.rs b/yazi-plugin/src/utils/user.rs index c2df7a467..d219ca3ac 100644 --- a/yazi-plugin/src/utils/user.rs +++ b/yazi-plugin/src/utils/user.rs @@ -2,9 +2,6 @@ use mlua::{Function, Lua}; use super::Utils; -#[cfg(unix)] -static HOSTNAME_CACHE: std::sync::OnceLock> = std::sync::OnceLock::new(); - impl Utils { #[cfg(unix)] pub(super) fn uid(lua: &Lua) -> mlua::Result { @@ -46,12 +43,6 @@ impl Utils { #[cfg(unix)] pub(super) fn host_name(lua: &Lua) -> mlua::Result { - lua.create_function(|lua, ()| { - HOSTNAME_CACHE - .get_or_init(|| yazi_shared::hostname().ok()) - .as_ref() - .map(|s| lua.create_string(s)) - .transpose() - }) + lua.create_function(|lua, ()| yazi_shared::hostname().map(|s| lua.create_string(s)).transpose()) } } diff --git a/yazi-shared/src/os.rs b/yazi-shared/src/os.rs index 56bdc4c79..b6c76c4b4 100644 --- a/yazi-shared/src/os.rs +++ b/yazi-shared/src/os.rs @@ -2,7 +2,14 @@ pub static USERS_CACHE: crate::RoCell = crate::RoCell::new(); #[cfg(unix)] -pub fn hostname() -> Result { +pub fn hostname() -> Option<&'static str> { + static CACHE: std::sync::OnceLock> = std::sync::OnceLock::new(); + + CACHE.get_or_init(|| hostname_impl().ok()).as_deref() +} + +#[cfg(unix)] +fn hostname_impl() -> Result { use std::io::{Error, ErrorKind}; use libc::{gethostname, strlen}; From 92ed5c7efcffee660ba7c23a7659c115b3112141 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Sat, 14 Dec 2024 13:20:12 +0800 Subject: [PATCH 2/2] .. --- yazi-core/src/manager/commands/refresh.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/yazi-core/src/manager/commands/refresh.rs b/yazi-core/src/manager/commands/refresh.rs index fe5f58293..1fa6ba487 100644 --- a/yazi-core/src/manager/commands/refresh.rs +++ b/yazi-core/src/manager/commands/refresh.rs @@ -9,8 +9,7 @@ use crate::{manager::Manager, tasks::Tasks}; impl Manager { pub fn refresh(&mut self, _: CmdCow, tasks: &Tasks) { - CWD.set(self.cwd()); - if !MANAGER.title_format.is_empty() { + if CWD.set(self.cwd()) && !MANAGER.title_format.is_empty() { execute!(std::io::stderr(), SetTitle(self.title())).ok(); }