From c15cebbcfa19832792f087895174e211e77af3de Mon Sep 17 00:00:00 2001 From: sxyazi Date: Sat, 30 Dec 2023 02:52:31 +0800 Subject: [PATCH] Add `follow` option for copy-paste --- yazi-core/src/manager/commands/paste.rs | 13 ++++++-- yazi-core/src/tasks/tasks.rs | 4 +-- yazi-scheduler/src/scheduler.rs | 4 +-- yazi-shared/src/fs/fns.rs | 40 ++++--------------------- 4 files changed, 19 insertions(+), 42 deletions(-) diff --git a/yazi-core/src/manager/commands/paste.rs b/yazi-core/src/manager/commands/paste.rs index 88c9fe9a..f1f11637 100644 --- a/yazi-core/src/manager/commands/paste.rs +++ b/yazi-core/src/manager/commands/paste.rs @@ -3,11 +3,14 @@ use yazi_shared::event::Exec; use crate::{manager::Manager, tasks::Tasks}; pub struct Opt { - force: bool, + force: bool, + follow: bool, } impl From<&Exec> for Opt { - fn from(e: &Exec) -> Self { Self { force: e.named.contains_key("force") } } + fn from(e: &Exec) -> Self { + Self { force: e.named.contains_key("force"), follow: e.named.contains_key("follow") } + } } impl Manager { @@ -16,6 +19,10 @@ impl Manager { let (cut, ref src) = self.yanked; let opt = opt.into() as Opt; - if cut { tasks.file_cut(src, dest, opt.force) } else { tasks.file_copy(src, dest, opt.force) } + if cut { + tasks.file_cut(src, dest, opt.force) + } else { + tasks.file_copy(src, dest, opt.force, opt.follow) + } } } diff --git a/yazi-core/src/tasks/tasks.rs b/yazi-core/src/tasks/tasks.rs index 40bcfb90..e60afd4a 100644 --- a/yazi-core/src/tasks/tasks.rs +++ b/yazi-core/src/tasks/tasks.rs @@ -89,13 +89,13 @@ impl Tasks { false } - pub fn file_copy(&self, src: &HashSet, dest: &Url, force: bool) -> bool { + pub fn file_copy(&self, src: &HashSet, dest: &Url, force: bool, follow: bool) -> bool { for u in src { let to = dest.join(u.file_name().unwrap()); if force && u == &to { debug!("file_copy: same file, skipping {:?}", to); } else { - self.scheduler.file_copy(u.clone(), to, force); + self.scheduler.file_copy(u.clone(), to, force, follow); } } false diff --git a/yazi-scheduler/src/scheduler.rs b/yazi-scheduler/src/scheduler.rs index ad0111f9..c4000409 100644 --- a/yazi-scheduler/src/scheduler.rs +++ b/yazi-scheduler/src/scheduler.rs @@ -207,7 +207,7 @@ impl Scheduler { ); } - pub fn file_copy(&self, from: Url, mut to: Url, force: bool) { + pub fn file_copy(&self, from: Url, mut to: Url, force: bool, follow: bool) { let name = format!("Copy {:?} to {:?}", from, to); let id = self.running.write().add(TaskKind::User, name); @@ -217,7 +217,7 @@ impl Scheduler { if !force { to = unique_path(to).await; } - file.paste(FileOpPaste { id, from, to, cut: false, follow: true, retry: 0 }).await.ok(); + file.paste(FileOpPaste { id, from, to, cut: false, follow, retry: 0 }).await.ok(); } .boxed(), LOW, diff --git a/yazi-shared/src/fs/fns.rs b/yazi-shared/src/fs/fns.rs index a019b35c..cfd1f6d7 100644 --- a/yazi-shared/src/fs/fns.rs +++ b/yazi-shared/src/fs/fns.rs @@ -38,40 +38,15 @@ pub async fn calculate_size(path: &Path) -> u64 { pub fn copy_with_progress(from: &Path, to: &Path) -> mpsc::Receiver> { let (tx, rx) = mpsc::channel(1); let (tick_tx, mut tick_rx) = oneshot::channel(); - let is_symlink = from.is_symlink(); tokio::spawn({ let (from, to) = (from.to_path_buf(), to.to_path_buf()); async move { - if is_symlink { - #[cfg(unix)] - { - _ = match fs::symlink(from, to).await { - Ok(()) => tick_tx.send(Ok(1)), - Err(e) => tick_tx.send(Err(e)), - } - } - #[cfg(windows)] - { - if from.is_dir() { - _ = match fs::symlink_dir(from, to).await { - Ok(()) => tick_tx.send(Ok(1)), - Err(e) => tick_tx.send(Err(e)), - } - } else { - _ = match fs::symlink_file(from, to).await { - Ok(()) => tick_tx.send(Ok(1)), - Err(e) => tick_tx.send(Err(e)), - } - } - } - } else { - _ = match fs::copy(from, to).await { - Ok(len) => tick_tx.send(Ok(len)), - Err(e) => tick_tx.send(Err(e)), - }; - } + _ = match fs::copy(from, to).await { + Ok(len) => tick_tx.send(Ok(len)), + Err(e) => tick_tx.send(Err(e)), + }; } }); @@ -104,12 +79,7 @@ pub fn copy_with_progress(from: &Path, to: &Path) -> mpsc::Receiver {} } - let len = if is_symlink { - 1 - } else { - fs::symlink_metadata(&to).await.map(|m| m.len()).unwrap_or(0) - }; - + let len = fs::symlink_metadata(&to).await.map(|m| m.len()).unwrap_or(0); if len > last { tx.send(Ok(len - last)).await.ok(); last = len;