feat: async micro task initialization error handling (#1710)

This commit is contained in:
三咲雅 · Misaki Masa 2024-10-01 18:38:37 +08:00 committed by GitHub
parent 40211df219
commit e1773b11f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 244 additions and 234 deletions

119
Cargo.lock generated
View file

@ -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]]

View file

@ -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"

View file

@ -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:

View file

@ -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

View file

@ -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<PathBuf>,
new: Vec<PathBuf>,
) -> Result<()> {
async fn bulk_rename_do(root: PathBuf, old: Vec<PathBuf>, new: Vec<PathBuf>) -> 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);

View file

@ -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();

View file

@ -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);

View file

@ -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 {

View file

@ -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();

View file

@ -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);
}

View file

@ -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);

View file

@ -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() {

View file

@ -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

View file

@ -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),
}
})?,
),
])?,

View file

@ -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))?;
}

View file

@ -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<Data>) {
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<F>(&self, id: usize, priority: u8, f: F)
where
F: Future<Output = Result<()>> + 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()))?;

View file

@ -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 {

View file

@ -47,6 +47,30 @@ impl FilesOp {
ticket
}
pub fn rename(map: HashMap<Url, File>) {
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<Url>, Vec<Url>) {
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(),

View file

@ -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<PathBuf> {
@ -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<Url> {
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

View file

@ -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() }

View file

@ -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<T: AsRef<Path> + ?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<Path> 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<OsStr> for Urn {
fn eq(&self, other: &OsStr) -> bool { self.0 == other }
}
impl PartialEq<Cow<'_, OsStr>> for &Urn {
fn eq(&self, other: &Cow<OsStr>) -> bool { self.0 == other.as_ref() }
}
// --- UrnBuf
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct UrnBuf(PathBuf);
@ -37,14 +52,19 @@ impl Borrow<Urn> for UrnBuf {
fn borrow(&self) -> &Urn { Urn::new(&self.0) }
}
impl AsRef<Path> for UrnBuf {
fn as_ref(&self) -> &Path { &self.0 }
}
impl PartialEq<Urn> 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<PathBuf>) -> Self { Self(p.into()) }
impl<T: Into<PathBuf>> From<T> for UrnBuf {
fn from(p: T) -> Self { Self(p.into()) }
}
impl UrnBuf {
#[inline]
pub fn as_urn(&self) -> &Urn { self.borrow() }
}