fix: put package cache in cache dir instead of state dir (#3930)

This commit is contained in:
三咲雅 misaki masa 2026-05-02 22:15:25 +08:00 committed by GitHub
parent 740d891989
commit 62dd22b8da
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 131 additions and 77 deletions

View file

@ -5,7 +5,7 @@ use super::Actions;
impl Actions {
pub(super) fn clear_cache() {
if YAZI.preview.cache_dir == *Xdg::cache_dir() {
if YAZI.preview.cache_dir == *Xdg::temp_dir() {
println!("Clearing cache directory: \n{:?}", YAZI.preview.cache_dir);
std::fs::remove_dir_all(&YAZI.preview.cache_dir).unwrap();
} else {

View file

@ -165,7 +165,7 @@ impl Actions {
fn file1_output() -> String {
use std::io::Write;
let p = env::temp_dir().join(format!(".yazi-debug-{}.tmp", timestamp_us()));
let p = Xdg::temp_dir().join(format!(".debug-{}.tmp", timestamp_us()));
std::fs::File::create_new(&p).map(|mut f| f.write_all(b"Hello, World!")).ok();
let program = env::var_os("YAZI_FILE_ONE").unwrap_or("file".into());

View file

@ -1,8 +1,6 @@
use std::path::PathBuf;
use futures::executor::block_on;
use hashbrown::HashSet;
use yazi_fs::{CWD, Xdg, path::clean_url};
use yazi_fs::{CWD, path::clean_url};
use yazi_shared::{strand::StrandBuf, url::{UrlBuf, UrlLike}};
use yazi_vfs::provider;
@ -13,11 +11,6 @@ pub struct Boot {
pub local_events: HashSet<String>,
pub remote_events: HashSet<String>,
pub config_dir: PathBuf,
pub flavor_dir: PathBuf,
pub plugin_dir: PathBuf,
pub state_dir: PathBuf,
}
impl Boot {
@ -52,7 +45,6 @@ impl Boot {
impl From<&crate::Args> for Boot {
fn from(args: &crate::Args) -> Self {
let config_dir = Xdg::config_dir();
let (cwds, files) = block_on(Self::parse_entries(&args.entries));
let local_events = args
@ -66,17 +58,6 @@ impl From<&crate::Args> for Boot {
.map(|s| s.split(',').map(|s| s.to_owned()).collect())
.unwrap_or_default();
Self {
cwds,
files,
local_events,
remote_events,
flavor_dir: config_dir.join("flavors"),
plugin_dir: config_dir.join("plugins"),
config_dir,
state_dir: Xdg::state_dir(),
}
Self { cwds, files, local_events, remote_events }
}
}

View file

@ -23,7 +23,7 @@ pub(crate) struct Dependency {
impl Dependency {
pub(super) fn local(&self) -> PathBuf {
Xdg::state_dir()
Xdg::cache_dir()
.join("packages")
.join(format!("{:x}", XxHash3_128::oneshot(self.remote().as_bytes())))
}

View file

@ -4,7 +4,7 @@ use anyhow::Context;
use yazi_fs::Xdg;
pub(super) fn init() -> anyhow::Result<()> {
let packages_dir = Xdg::state_dir().join("packages");
let packages_dir = Xdg::cache_dir().join("packages");
std::fs::create_dir_all(&packages_dir)
.with_context(|| format!("failed to create packages directory: {packages_dir:?}"))?;

View file

@ -63,7 +63,7 @@ where
{
let path = PathBuf::deserialize(deserializer)?;
if path.as_os_str().is_empty() {
Ok(Xdg::cache_dir().to_owned())
Ok(Xdg::temp_dir().to_owned())
} else {
normalize_path(path).ok_or_else(|| {
serde::de::Error::custom("cache_dir must be either empty or an absolute path.")

View file

@ -4,8 +4,7 @@ use anyhow::Result;
use hashbrown::HashMap;
use parking_lot::RwLock;
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader, BufWriter};
use yazi_boot::BOOT;
use yazi_fs::provider::{FileBuilder, Provider, local::{Gate, Local}};
use yazi_fs::{Xdg, provider::{FileBuilder, Provider, local::{Gate, Local}}};
use yazi_shared::timestamp_us;
use yazi_shim::cell::RoCell;
@ -59,14 +58,11 @@ impl State {
return Ok(());
}
Local::regular(&BOOT.state_dir).create_dir_all().await?;
let state_dir = Xdg::state_dir();
Local::regular(&state_dir).create_dir_all().await?;
let mut buf = BufWriter::new(
Gate::default()
.write(true)
.create(true)
.truncate(true)
.open(BOOT.state_dir.join(".dds"))
.await?,
Gate::default().write(true).create(true).truncate(true).open(state_dir.join(".dds")).await?,
);
let mut state = inner.into_iter().collect::<Vec<_>>();
@ -80,7 +76,7 @@ impl State {
}
async fn load(&self) -> Result<()> {
let mut file = BufReader::new(Local::regular(&BOOT.state_dir.join(".dds")).open().await?);
let mut file = BufReader::new(Local::regular(&Xdg::state_dir().join(".dds")).open().await?);
let mut buf = String::new();
let mut inner = HashMap::new();
@ -104,7 +100,7 @@ impl State {
}
async fn skip(&self) -> Result<bool> {
let cha = Local::regular(&BOOT.state_dir.join(".dds")).symlink_metadata().await?;
let cha = Local::regular(&Xdg::state_dir().join(".dds")).symlink_metadata().await?;
let modified = cha.mtime_dur()?.as_micros();
Ok(modified >= self.last.load(Ordering::Relaxed) as u128)
}

View file

@ -1,3 +1,5 @@
use std::io;
use tokio::io::{BufReader, Lines, ReadHalf, WriteHalf};
pub struct Stream;
@ -21,41 +23,51 @@ pub(super) type ServerListener = tokio::net::TcpListener;
impl Stream {
#[cfg(unix)]
pub async fn connect() -> std::io::Result<(ClientReader, ClientWriter)> {
let stream = tokio::net::UnixStream::connect(Self::socket_file()).await?;
pub async fn connect() -> io::Result<(ClientReader, ClientWriter)> {
let stream = tokio::net::UnixStream::connect(Self::socket_file().await?).await?;
let (reader, writer) = tokio::io::split(stream);
Ok((BufReader::new(reader).lines(), writer))
}
#[cfg(not(unix))]
pub async fn connect() -> std::io::Result<(ClientReader, ClientWriter)> {
pub async fn connect() -> io::Result<(ClientReader, ClientWriter)> {
let stream = tokio::net::TcpStream::connect("127.0.0.1:33581").await?;
let (reader, writer) = tokio::io::split(stream);
Ok((BufReader::new(reader).lines(), writer))
}
#[cfg(unix)]
pub(super) async fn bind() -> std::io::Result<ServerListener> {
pub(super) async fn bind() -> io::Result<ServerListener> {
use yazi_fs::provider::Provider;
let p = Self::socket_file();
let p = Self::socket_file().await?;
yazi_fs::provider::local::Local::regular(&p).remove_file().await.ok();
tokio::net::UnixListener::bind(p)
}
#[cfg(not(unix))]
pub(super) async fn bind() -> std::io::Result<ServerListener> {
pub(super) async fn bind() -> io::Result<ServerListener> {
tokio::net::TcpListener::bind("127.0.0.1:33581").await
}
#[cfg(unix)]
fn socket_file() -> std::path::PathBuf {
use std::env::temp_dir;
async fn socket_file() -> io::Result<&'static std::path::PathBuf> {
use tokio::{fs::DirBuilder, sync::OnceCell};
use yazi_fs::Xdg;
use uzers::Users;
use yazi_shared::USERS_CACHE;
static ONCE: tokio::sync::OnceCell<std::path::PathBuf> = OnceCell::const_new();
ONCE
.get_or_try_init(|| async move {
let p = Xdg::runtime_dir();
temp_dir().join(format!(".yazi_dds-{}.sock", USERS_CACHE.get_current_uid()))
#[cfg(unix)]
DirBuilder::new().mode(0o700).recursive(true).create(p).await?;
#[cfg(not(unix))]
DirBuilder::new().recursive(true).create(p).await?;
Ok(p.join(".dds.sock"))
})
.await
}
}

View file

@ -56,7 +56,7 @@ impl Cwd {
return cache.into();
}
let latter = cache.strip_prefix(Xdg::cache_dir()).expect("under cache dir");
let latter = cache.strip_prefix(Xdg::temp_dir()).expect("under temp dir");
let mut it = latter.components().peekable();
while it.peek() == Some(&C::CurDir) {
it.next().unwrap();

View file

@ -6,4 +6,6 @@ pub fn init() {
CWD.init(<_>::default());
mounts::init();
Xdg::load();
}

View file

@ -13,10 +13,10 @@ impl FsScheme for SchemeRef<'_> {
match self {
Self::Regular { .. } | Self::Search { .. } => None,
Self::Archive { domain, .. } => Some(
Xdg::cache_dir().join(format!("archive-{}", yazi_shared::scheme::Encode::domain(domain))),
Xdg::temp_dir().join(format!("archive-{}", yazi_shared::scheme::Encode::domain(domain))),
),
Self::Sftp { domain, .. } => {
Some(Xdg::cache_dir().join(format!("sftp-{}", yazi_shared::scheme::Encode::domain(domain))))
Some(Xdg::temp_dir().join(format!("sftp-{}", yazi_shared::scheme::Encode::domain(domain))))
}
}
}

View file

@ -1,9 +1,24 @@
use std::{env, path::PathBuf, sync::OnceLock};
use yazi_macro::unix_either;
pub struct Xdg;
impl Xdg {
pub fn config_dir() -> PathBuf {
pub(super) fn load() {
Self::config_dir();
Self::cache_dir();
Self::state_dir();
Self::runtime_dir();
Self::temp_dir();
}
pub fn config_dir() -> &'static PathBuf {
static ONCE: OnceLock<PathBuf> = OnceLock::new();
ONCE.get_or_init(Self::load_config_dir)
}
fn load_config_dir() -> PathBuf {
if let Some(p) = env::var_os("YAZI_CONFIG_HOME").map(PathBuf::from)
&& p.is_absolute()
{
@ -12,53 +27,102 @@ impl Xdg {
#[cfg(windows)]
{
dirs::config_dir()
.map(|p| p.join("yazi").join("config"))
.expect("Failed to get config directory")
dirs::config_dir().map(|p| p.join("yazi\\config")).expect("Failed to get config directory")
}
#[cfg(unix)]
{
env::var_os("XDG_CONFIG_HOME")
.map(PathBuf::from)
.filter(|p| p.is_absolute())
.or_else(|| dirs::home_dir().map(|h| h.join(".config")))
.map(|p| p.join("yazi"))
.or_else(|| dirs::home_dir().map(|h| h.join(".config/yazi")))
.expect("Failed to get config directory")
}
}
pub fn state_dir() -> PathBuf {
pub fn cache_dir() -> &'static PathBuf {
static ONCE: OnceLock<PathBuf> = OnceLock::new();
ONCE.get_or_init(Self::load_cache_dir)
}
fn load_cache_dir() -> PathBuf {
#[cfg(windows)]
{
dirs::data_dir().map(|p| p.join("yazi").join("state")).expect("Failed to get state directory")
dirs::cache_dir().map(|p| p.join("yazi")).expect("Failed to get cache directory")
}
#[cfg(unix)]
{
env::var_os("XDG_CACHE_HOME")
.map(PathBuf::from)
.filter(|p| p.is_absolute())
.map(|p| p.join("yazi"))
.or_else(|| dirs::home_dir().map(|h| h.join(".cache/yazi")))
.expect("Failed to get cache directory")
}
}
pub fn state_dir() -> &'static PathBuf {
static ONCE: OnceLock<PathBuf> = OnceLock::new();
ONCE.get_or_init(Self::load_state_dir)
}
fn load_state_dir() -> PathBuf {
#[cfg(windows)]
{
dirs::data_dir().map(|p| p.join("yazi\\state")).expect("Failed to get state directory")
}
#[cfg(unix)]
{
env::var_os("XDG_STATE_HOME")
.map(PathBuf::from)
.filter(|p| p.is_absolute())
.or_else(|| dirs::home_dir().map(|h| h.join(".local/state")))
.map(|p| p.join("yazi"))
.or_else(|| dirs::home_dir().map(|h| h.join(".local/state/yazi")))
.expect("Failed to get state directory")
}
}
pub fn cache_dir() -> &'static PathBuf {
static CACHE: OnceLock<PathBuf> = OnceLock::new();
pub fn runtime_dir() -> &'static PathBuf {
static ONCE: OnceLock<PathBuf> = OnceLock::new();
ONCE.get_or_init(Self::load_runtime_dir)
}
CACHE.get_or_init(|| {
let mut p = env::temp_dir();
assert!(p.is_absolute(), "Temp dir is not absolute");
fn load_runtime_dir() -> PathBuf {
let mut p = env::var_os("XDG_RUNTIME_DIR")
.map(PathBuf::from)
.filter(|p| p.is_absolute())
.unwrap_or_else(|| env::temp_dir());
#[cfg(unix)]
let uid = unix_either!(
{
use uzers::Users;
p.push(format!("yazi-{}", yazi_shared::USERS_CACHE.get_current_uid()))
}
#[cfg(not(unix))]
p.push("yazi");
yazi_shared::USERS_CACHE.get_current_uid()
},
0
);
p
})
p.push(format!("yazi+{uid}"));
p
}
pub fn temp_dir() -> &'static PathBuf {
static ONCE: OnceLock<PathBuf> = OnceLock::new();
ONCE.get_or_init(Self::load_temp_dir)
}
fn load_temp_dir() -> PathBuf {
let mut p = env::temp_dir();
assert!(p.is_absolute(), "Temporary directory path is not absolute");
let uid = unix_either!(
{
use uzers::Users;
yazi_shared::USERS_CACHE.get_current_uid()
},
0
);
p.push(format!("yazi-{uid}"));
p
}
}

View file

@ -2,7 +2,7 @@ use anyhow::{Context, Result};
use futures::executor::block_on;
use mlua::Lua;
use yazi_binding::{Runtime, runtime_scope};
use yazi_boot::BOOT;
use yazi_fs::Xdg;
use yazi_macro::plugin_preset as preset;
use yazi_shim::cell::RoCell;
@ -67,7 +67,7 @@ fn stage_2(lua: &Lua) -> mlua::Result<()> {
lua.load(preset!("setup")).set_name("setup.lua").exec()?;
lua.load(preset!("compat")).set_name("compat.lua").exec()?;
if let Ok(b) = std::fs::read(BOOT.config_dir.join("init.lua")) {
if let Ok(b) = std::fs::read(Xdg::config_dir().join("init.lua")) {
runtime_scope!(lua, "init", block_on(lua.load(b).set_name("init.lua").exec_async()))?;
}

View file

@ -4,8 +4,7 @@ use anyhow::{Context, Result, bail, ensure};
use hashbrown::HashMap;
use mlua::{ChunkMode, ExternalError, Lua, Table};
use parking_lot::RwLock;
use yazi_boot::BOOT;
use yazi_fs::provider::local::Local;
use yazi_fs::{Xdg, provider::local::Local};
use yazi_macro::plugin_preset as preset;
use yazi_shared::{BytesExt, LOG_LEVEL};
use yazi_shim::cell::RoCell;
@ -89,7 +88,7 @@ impl Loader {
return Self::compatible_or_error(id, c).map(|_| f(c));
}
let p = BOOT.plugin_dir.join(format!("{plugin}.yazi/{entry}.lua"));
let p = Xdg::config_dir().join(format!("plugins/{plugin}.yazi/{entry}.lua"));
let chunk = Local::regular(&p)
.read()
.await

View file

@ -40,7 +40,7 @@ impl Watched {
}
pub(super) fn find_by_cache(&self, cache: PathDyn) -> Option<UrlBuf> {
let mut it = cache.try_strip_prefix(Xdg::cache_dir()).ok()?.components();
let mut it = cache.try_strip_prefix(Xdg::temp_dir()).ok()?.components();
// Parse domain
let domain = it.next()?.as_normal()?.to_str().ok()?;