mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: support task initialization failure status (#3227)
This commit is contained in:
parent
149a5feffb
commit
cd6881c9fe
10 changed files with 110 additions and 49 deletions
|
|
@ -32,6 +32,7 @@ impl UserData for TaskSnap {
|
|||
|
||||
fields.add_field_method_get("running", |_, me| Ok(me.prog.running()));
|
||||
fields.add_field_method_get("success", |_, me| Ok(me.prog.success()));
|
||||
fields.add_field_method_get("failed", |_, me| Ok(me.prog.failed()));
|
||||
fields.add_field_method_get("percent", |_, me| Ok(me.prog.percent()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ impl File {
|
|||
|
||||
pub(crate) async fn paste(&self, mut task: FileInPaste) -> Result<(), FileOutPaste> {
|
||||
if task.cut && ok_or_not_found(provider::rename(&task.from, &task.to).await).is_ok() {
|
||||
return Ok(self.ops.out(task.id, FileOutPaste::Init));
|
||||
return Ok(self.ops.out(task.id, FileOutPaste::Succ));
|
||||
}
|
||||
|
||||
if task.cha.is_none() {
|
||||
|
|
@ -44,7 +44,7 @@ impl File {
|
|||
self.ops.out(id, FileOutPaste::New(cha.len));
|
||||
self.queue(task, LOW);
|
||||
}
|
||||
return Ok(self.ops.out(id, FileOutPaste::Init));
|
||||
return Ok(self.ops.out(id, FileOutPaste::Succ));
|
||||
}
|
||||
|
||||
macro_rules! continue_unless_ok {
|
||||
|
|
@ -91,7 +91,7 @@ impl File {
|
|||
}
|
||||
}
|
||||
|
||||
Ok(self.ops.out(task.id, FileOutPaste::Init))
|
||||
Ok(self.ops.out(task.id, FileOutPaste::Succ))
|
||||
}
|
||||
|
||||
pub(crate) async fn paste_do(&self, mut task: FileInPaste) -> Result<(), FileOutPasteDo> {
|
||||
|
|
@ -175,7 +175,7 @@ impl File {
|
|||
let id = task.id;
|
||||
self.ops.out(id, FileOutHardlink::New);
|
||||
self.queue(task, NORMAL);
|
||||
self.ops.out(id, FileOutHardlink::Init);
|
||||
self.ops.out(id, FileOutHardlink::Succ);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ impl File {
|
|||
}
|
||||
}
|
||||
|
||||
Ok(self.ops.out(task.id, FileOutHardlink::Init))
|
||||
Ok(self.ops.out(task.id, FileOutHardlink::Succ))
|
||||
}
|
||||
|
||||
pub(crate) async fn hardlink_do(&self, task: FileInHardlink) -> Result<(), FileOutHardlinkDo> {
|
||||
|
|
@ -243,7 +243,7 @@ impl File {
|
|||
task.length = cha.len;
|
||||
self.ops.out(id, FileOutDelete::New(cha.len));
|
||||
self.queue(task, NORMAL);
|
||||
self.ops.out(id, FileOutDelete::Init);
|
||||
self.ops.out(id, FileOutDelete::Succ);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
|
@ -266,7 +266,7 @@ impl File {
|
|||
}
|
||||
}
|
||||
|
||||
Ok(self.ops.out(task.id, FileOutDelete::Init))
|
||||
Ok(self.ops.out(task.id, FileOutDelete::Succ))
|
||||
}
|
||||
|
||||
pub(crate) async fn delete_do(&self, task: FileInDelete) -> Result<(), FileOutDeleteDo> {
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ use crate::{Task, TaskProg};
|
|||
pub(crate) enum FileOutPaste {
|
||||
New(u64),
|
||||
Deform(String),
|
||||
Init,
|
||||
Succ,
|
||||
Fail(String),
|
||||
Clean,
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for FileOutPaste {
|
||||
fn from(value: std::io::Error) -> Self { Self::Deform(value.to_string()) }
|
||||
fn from(value: std::io::Error) -> Self { Self::Fail(value.to_string()) }
|
||||
}
|
||||
|
||||
impl FileOutPaste {
|
||||
|
|
@ -26,8 +27,12 @@ impl FileOutPaste {
|
|||
prog.failed_files += 1;
|
||||
task.log(reason);
|
||||
}
|
||||
Self::Init => {
|
||||
prog.collected = true;
|
||||
Self::Succ => {
|
||||
prog.collected = Some(true);
|
||||
}
|
||||
Self::Fail(reason) => {
|
||||
prog.collected = Some(false);
|
||||
task.log(reason);
|
||||
}
|
||||
Self::Clean => {
|
||||
prog.cleaned = true;
|
||||
|
|
@ -116,11 +121,12 @@ impl FileOutLink {
|
|||
pub(crate) enum FileOutHardlink {
|
||||
New,
|
||||
Deform(String),
|
||||
Init,
|
||||
Succ,
|
||||
Fail(String),
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for FileOutHardlink {
|
||||
fn from(value: std::io::Error) -> Self { Self::Deform(value.to_string()) }
|
||||
fn from(value: std::io::Error) -> Self { Self::Fail(value.to_string()) }
|
||||
}
|
||||
|
||||
impl FileOutHardlink {
|
||||
|
|
@ -135,8 +141,12 @@ impl FileOutHardlink {
|
|||
prog.failed += 1;
|
||||
task.log(reason);
|
||||
}
|
||||
Self::Init => {
|
||||
prog.collected = true;
|
||||
Self::Succ => {
|
||||
prog.collected = Some(true);
|
||||
}
|
||||
Self::Fail(reason) => {
|
||||
prog.collected = Some(false);
|
||||
task.log(reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -172,13 +182,13 @@ impl FileOutHardlinkDo {
|
|||
#[derive(Debug)]
|
||||
pub(crate) enum FileOutDelete {
|
||||
New(u64),
|
||||
Deform(String),
|
||||
Init,
|
||||
Succ,
|
||||
Fail(String),
|
||||
Clean,
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for FileOutDelete {
|
||||
fn from(value: std::io::Error) -> Self { Self::Deform(value.to_string()) }
|
||||
fn from(value: std::io::Error) -> Self { Self::Fail(value.to_string()) }
|
||||
}
|
||||
|
||||
impl FileOutDelete {
|
||||
|
|
@ -189,13 +199,12 @@ impl FileOutDelete {
|
|||
prog.total_files += 1;
|
||||
prog.total_bytes += size;
|
||||
}
|
||||
Self::Deform(reason) => {
|
||||
prog.total_files += 1;
|
||||
prog.failed_files += 1;
|
||||
task.log(reason);
|
||||
Self::Succ => {
|
||||
prog.collected = Some(true);
|
||||
}
|
||||
Self::Init => {
|
||||
prog.collected = true;
|
||||
Self::Fail(reason) => {
|
||||
prog.collected = Some(false);
|
||||
task.log(reason);
|
||||
}
|
||||
Self::Clean => {
|
||||
prog.cleaned = true;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ pub struct FileProgPaste {
|
|||
pub failed_files: u32,
|
||||
pub total_bytes: u64,
|
||||
pub processed_bytes: u64,
|
||||
pub collected: bool,
|
||||
pub collected: Option<bool>,
|
||||
pub cleaned: bool,
|
||||
}
|
||||
|
||||
|
|
@ -26,20 +26,26 @@ impl From<FileProgPaste> for TaskSummary {
|
|||
|
||||
impl FileProgPaste {
|
||||
pub fn running(self) -> bool {
|
||||
!self.collected || self.success_files + self.failed_files != self.total_files
|
||||
self.collected.is_none() || self.success_files + self.failed_files != self.total_files
|
||||
}
|
||||
|
||||
pub fn success(self) -> bool { self.collected && self.success_files == self.total_files }
|
||||
pub fn success(self) -> bool {
|
||||
self.collected == Some(true) && self.success_files == self.total_files
|
||||
}
|
||||
|
||||
pub fn failed(self) -> bool { self.collected == Some(false) }
|
||||
|
||||
pub fn cleaned(self) -> bool { self.cleaned }
|
||||
|
||||
pub fn percent(self) -> Option<f32> {
|
||||
Some(if self.success() {
|
||||
100.0
|
||||
} else if self.total_bytes == 0 {
|
||||
99.99
|
||||
} else {
|
||||
} else if self.failed() {
|
||||
0.0
|
||||
} else if self.total_bytes != 0 {
|
||||
99.99f32.min(self.processed_bytes as f32 / self.total_bytes as f32 * 100.0)
|
||||
} else {
|
||||
99.99
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -66,6 +72,8 @@ impl FileProgLink {
|
|||
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub fn failed(self) -> bool { self.state == Some(false) }
|
||||
|
||||
pub fn cleaned(self) -> bool { false }
|
||||
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
|
|
@ -77,7 +85,7 @@ pub struct FileProgHardlink {
|
|||
pub total: u32,
|
||||
pub success: u32,
|
||||
pub failed: u32,
|
||||
pub collected: bool,
|
||||
pub collected: Option<bool>,
|
||||
}
|
||||
|
||||
impl From<FileProgHardlink> for TaskSummary {
|
||||
|
|
@ -92,9 +100,13 @@ impl From<FileProgHardlink> for TaskSummary {
|
|||
}
|
||||
|
||||
impl FileProgHardlink {
|
||||
pub fn running(self) -> bool { !self.collected || self.success + self.failed != self.total }
|
||||
pub fn running(self) -> bool {
|
||||
self.collected.is_none() || self.success + self.failed != self.total
|
||||
}
|
||||
|
||||
pub fn success(self) -> bool { self.collected && self.success == self.total }
|
||||
pub fn success(self) -> bool { self.collected == Some(true) && self.success == self.total }
|
||||
|
||||
pub fn failed(self) -> bool { self.collected == Some(false) }
|
||||
|
||||
pub fn cleaned(self) -> bool { false }
|
||||
|
||||
|
|
@ -109,7 +121,7 @@ pub struct FileProgDelete {
|
|||
pub failed_files: u32,
|
||||
pub total_bytes: u64,
|
||||
pub processed_bytes: u64,
|
||||
pub collected: bool,
|
||||
pub collected: Option<bool>,
|
||||
pub cleaned: bool,
|
||||
}
|
||||
|
||||
|
|
@ -126,20 +138,26 @@ impl From<FileProgDelete> for TaskSummary {
|
|||
|
||||
impl FileProgDelete {
|
||||
pub fn running(self) -> bool {
|
||||
!self.collected || self.success_files + self.failed_files != self.total_files
|
||||
self.collected.is_none() || self.success_files + self.failed_files != self.total_files
|
||||
}
|
||||
|
||||
pub fn success(self) -> bool { self.collected && self.success_files == self.total_files }
|
||||
pub fn success(self) -> bool {
|
||||
self.collected == Some(true) && self.success_files == self.total_files
|
||||
}
|
||||
|
||||
pub fn failed(self) -> bool { self.collected == Some(false) }
|
||||
|
||||
pub fn cleaned(self) -> bool { self.cleaned }
|
||||
|
||||
pub fn percent(self) -> Option<f32> {
|
||||
Some(if self.success() {
|
||||
100.0
|
||||
} else if self.total_bytes == 0 {
|
||||
99.99
|
||||
} else {
|
||||
} else if self.failed() {
|
||||
0.0
|
||||
} else if self.total_bytes != 0 {
|
||||
99.99f32.min(self.processed_bytes as f32 / self.total_bytes as f32 * 100.0)
|
||||
} else {
|
||||
99.99
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -166,6 +184,8 @@ impl FileProgTrash {
|
|||
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub fn failed(self) -> bool { self.state == Some(false) }
|
||||
|
||||
pub fn cleaned(self) -> bool { false }
|
||||
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ impl Ongoing {
|
|||
|
||||
for task in self.values() {
|
||||
let s: TaskSummary = task.prog.into();
|
||||
if s.total == 0 {
|
||||
if s.total == 0 && !task.prog.failed() {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ impl PluginProgEntry {
|
|||
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub fn failed(self) -> bool { self.state == Some(false) }
|
||||
|
||||
pub fn cleaned(self) -> bool { false }
|
||||
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ impl PreworkProgFetch {
|
|||
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub fn failed(self) -> bool { self.state == Some(false) }
|
||||
|
||||
pub fn cleaned(self) -> bool { false }
|
||||
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
|
|
@ -50,6 +52,8 @@ impl PreworkProgLoad {
|
|||
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub fn failed(self) -> bool { self.state == Some(false) }
|
||||
|
||||
pub fn cleaned(self) -> bool { false }
|
||||
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
|
|
@ -77,6 +81,8 @@ impl PreworkProgSize {
|
|||
|
||||
pub fn success(self) -> bool { self.done }
|
||||
|
||||
pub fn failed(self) -> bool { false }
|
||||
|
||||
pub fn cleaned(self) -> bool { false }
|
||||
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ impl ProcessProgBlock {
|
|||
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub fn failed(self) -> bool { self.state == Some(false) }
|
||||
|
||||
pub fn cleaned(self) -> bool { self.cleaned }
|
||||
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
|
|
@ -52,6 +54,8 @@ impl ProcessProgOrphan {
|
|||
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub fn failed(self) -> bool { self.state == Some(false) }
|
||||
|
||||
pub fn cleaned(self) -> bool { self.cleaned }
|
||||
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
|
|
@ -80,6 +84,8 @@ impl ProcessProgBg {
|
|||
|
||||
pub fn success(self) -> bool { self.state == Some(true) }
|
||||
|
||||
pub fn failed(self) -> bool { self.state == Some(false) }
|
||||
|
||||
pub fn cleaned(self) -> bool { self.cleaned }
|
||||
|
||||
pub fn percent(self) -> Option<f32> { None }
|
||||
|
|
|
|||
|
|
@ -101,6 +101,27 @@ impl TaskProg {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn failed(self) -> bool {
|
||||
match self {
|
||||
// File
|
||||
Self::FilePaste(p) => p.failed(),
|
||||
Self::FileLink(p) => p.failed(),
|
||||
Self::FileHardlink(p) => p.failed(),
|
||||
Self::FileDelete(p) => p.failed(),
|
||||
Self::FileTrash(p) => p.failed(),
|
||||
// Plugin
|
||||
Self::PluginEntry(p) => p.failed(),
|
||||
// Prework
|
||||
Self::PreworkFetch(p) => p.failed(),
|
||||
Self::PreworkLoad(p) => p.failed(),
|
||||
Self::PreworkSize(p) => p.failed(),
|
||||
// Process
|
||||
Self::ProcessBlock(p) => p.failed(),
|
||||
Self::ProcessOrphan(p) => p.failed(),
|
||||
Self::ProcessBg(p) => p.failed(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cleaned(self) -> bool {
|
||||
match self {
|
||||
// File
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ impl Scheduler {
|
|||
let id = ongoing.add::<FileProgPaste>(format!("Cut {} to {}", from.display(), to.display()));
|
||||
|
||||
if to.starts_with(&from) && !to.covariant(&from) {
|
||||
return self.ops.out(id, FileOutPaste::Deform("Cannot cut directory into itself".to_owned()));
|
||||
return self.ops.out(id, FileOutPaste::Fail("Cannot cut directory into itself".to_owned()));
|
||||
}
|
||||
|
||||
ongoing.hooks.add_async(id, {
|
||||
|
|
@ -114,9 +114,7 @@ impl Scheduler {
|
|||
));
|
||||
|
||||
if to.starts_with(&from) && !to.covariant(&from) {
|
||||
return self
|
||||
.ops
|
||||
.out(id, FileOutPaste::Deform("Cannot copy directory into itself".to_owned()));
|
||||
return self.ops.out(id, FileOutPaste::Fail("Cannot copy directory into itself".to_owned()));
|
||||
}
|
||||
|
||||
let file = self.file.clone();
|
||||
|
|
@ -154,7 +152,7 @@ impl Scheduler {
|
|||
if to.starts_with(&from) && !to.covariant(&from) {
|
||||
return self
|
||||
.ops
|
||||
.out(id, FileOutHardlink::Deform("Cannot hardlink directory into itself".to_owned()));
|
||||
.out(id, FileOutHardlink::Fail("Cannot hardlink directory into itself".to_owned()));
|
||||
}
|
||||
|
||||
let file = self.file.clone();
|
||||
|
|
@ -212,16 +210,14 @@ impl Scheduler {
|
|||
|
||||
pub fn file_download(&self, from: UrlBuf, done: Option<oneshot::Sender<bool>>) {
|
||||
let mut ongoing = self.ongoing.lock();
|
||||
let id = self.ongoing.lock().add::<FileProgPaste>(format!("Download {}", from.display()));
|
||||
let id = ongoing.add::<FileProgPaste>(format!("Download {}", from.display()));
|
||||
|
||||
if let Some(tx) = done {
|
||||
ongoing.hooks.add_sync(id, move |canceled| _ = tx.send(canceled));
|
||||
}
|
||||
|
||||
let Some(to) = from.cache().map(UrlBuf::from) else {
|
||||
return self
|
||||
.ops
|
||||
.out(id, FileOutPaste::Deform("Unable to download non-remote file".to_owned()));
|
||||
return self.ops.out(id, FileOutPaste::Fail("Cannot download non-remote file".to_owned()));
|
||||
};
|
||||
|
||||
let file = self.file.clone();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue