Skip to content

Commit

Permalink
fix: set the current working directory in a thread-safe way (#2043)
Browse files Browse the repository at this point in the history
  • Loading branch information
sxyazi authored Dec 14, 2024
1 parent c1048de commit 6e1948e
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 34 deletions.
20 changes: 10 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions yazi-core/src/manager/commands/refresh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down
42 changes: 32 additions & 10 deletions yazi-fs/src/cwd.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,57 @@
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<Cwd> = RoCell::new();

pub struct Cwd {
inner: ArcSwap<Url>,
}
pub struct Cwd(ArcSwap<Url>);

impl Deref for Cwd {
type Target = ArcSwap<Url>;

fn deref(&self) -> &Self::Target { &self.inner }
fn deref(&self) -> &Self::Target { &self.0 }
}

impl Default for Cwd {
fn default() -> Self {
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();
}
});
}
}
11 changes: 1 addition & 10 deletions yazi-plugin/src/utils/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ use mlua::{Function, Lua};

use super::Utils;

#[cfg(unix)]
static HOSTNAME_CACHE: std::sync::OnceLock<Option<String>> = std::sync::OnceLock::new();

impl Utils {
#[cfg(unix)]
pub(super) fn uid(lua: &Lua) -> mlua::Result<Function> {
Expand Down Expand Up @@ -46,12 +43,6 @@ impl Utils {

#[cfg(unix)]
pub(super) fn host_name(lua: &Lua) -> mlua::Result<Function> {
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())
}
}
9 changes: 8 additions & 1 deletion yazi-shared/src/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
pub static USERS_CACHE: crate::RoCell<uzers::UsersCache> = crate::RoCell::new();

#[cfg(unix)]
pub fn hostname() -> Result<String, std::io::Error> {
pub fn hostname() -> Option<&'static str> {
static CACHE: std::sync::OnceLock<Option<String>> = std::sync::OnceLock::new();

CACHE.get_or_init(|| hostname_impl().ok()).as_deref()
}

#[cfg(unix)]
fn hostname_impl() -> Result<String, std::io::Error> {
use std::io::{Error, ErrorKind};

use libc::{gethostname, strlen};
Expand Down

0 comments on commit 6e1948e

Please sign in to comment.