From e7755ad0be98540c777d86c67605386ff11522a3 Mon Sep 17 00:00:00 2001 From: Jeff Zhao Date: Sat, 3 Sep 2022 12:45:51 -0400 Subject: add symlink relative --- src/io/file_operation.rs | 23 ++++++++++++++++++++-- src/io/io_observer.rs | 9 ++------- src/io/io_worker.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 11 deletions(-) (limited to 'src/io') diff --git a/src/io/file_operation.rs b/src/io/file_operation.rs index 9d39716..43589aa 100644 --- a/src/io/file_operation.rs +++ b/src/io/file_operation.rs @@ -2,16 +2,35 @@ pub enum FileOperation { Cut, Copy, - Symlink, + Symlink { relative: bool }, Delete, } +impl FileOperation { + pub fn actioning_str(&self) -> &'static str { + match *self { + Self::Cut => "Moving", + Self::Copy => "Copying", + Self::Symlink { .. } => "Symlinking", + Self::Delete => "Deleting", + } + } + pub fn actioned_str(&self) -> &'static str { + match *self { + Self::Cut => "moved", + Self::Copy => "copied", + Self::Symlink { .. } => "symlinked", + Self::Delete => "deleted", + } + } +} + impl std::fmt::Display for FileOperation { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Self::Cut => write!(f, "Cut"), Self::Copy => write!(f, "Copy"), - Self::Symlink => write!(f, "Symlink"), + Self::Symlink { relative } => write!(f, "Symlink --relative={}", relative), Self::Delete => write!(f, "Delete"), } } diff --git a/src/io/io_observer.rs b/src/io/io_observer.rs index 44d4248..93a1b15 100644 --- a/src/io/io_observer.rs +++ b/src/io/io_observer.rs @@ -1,7 +1,7 @@ use std::path; use std::thread; -use crate::io::{FileOperation, FileOperationProgress}; +use crate::io::FileOperationProgress; use crate::util::format; #[derive(Debug)] @@ -34,12 +34,7 @@ impl IoWorkerObserver { match self.progress.as_ref() { None => {} Some(progress) => { - let op_str = match progress.kind() { - FileOperation::Cut => "Moving", - FileOperation::Copy => "Copying", - FileOperation::Symlink => "Symlinking", - FileOperation::Delete => "Deleting", - }; + let op_str = progress.kind().actioning_str(); let processed_size = format::file_size_to_string(progress.bytes_processed()); let total_size = format::file_size_to_string(progress.total_bytes()); diff --git a/src/io/io_worker.rs b/src/io/io_worker.rs index f9d86d9..54385ec 100644 --- a/src/io/io_worker.rs +++ b/src/io/io_worker.rs @@ -44,7 +44,8 @@ impl IoWorkerThread { match self.kind() { FileOperation::Cut => self.paste_cut(tx), FileOperation::Copy => self.paste_copy(tx), - FileOperation::Symlink => self.paste_link(tx), + FileOperation::Symlink { relative: false } => self.paste_link_absolute(tx), + FileOperation::Symlink { relative: true } => self.paste_link_relative(tx), FileOperation::Delete => self.delete(tx), } } @@ -87,7 +88,7 @@ impl IoWorkerThread { Ok(progress) } - fn paste_link( + fn paste_link_absolute( &self, tx: mpsc::Sender, ) -> io::Result { @@ -112,6 +113,52 @@ impl IoWorkerThread { Ok(progress) } + fn paste_link_relative( + &self, + tx: mpsc::Sender, + ) -> io::Result { + let total_files = self.paths.len(); + let total_bytes = total_files as u64; + let mut progress = FileOperationProgress::new(self.kind(), 0, total_files, 0, total_bytes); + + #[cfg(unix)] + for src in self.paths.iter() { + let _ = tx.send(progress.clone()); + let mut dest_buf = self.dest.to_path_buf(); + if let Some(s) = src.file_name() { + dest_buf.push(s); + } + if !self.options.overwrite { + rename_filename_conflict(&mut dest_buf); + } + let mut src_components = src.components(); + let mut dest_components = dest_buf.components(); + + // skip to where the two paths diverge + let mut non_relative_path = path::PathBuf::new(); + for (s, d) in src_components.by_ref().zip(dest_components.by_ref()) { + if s != d { + non_relative_path.push(s); + break; + } + } + + let mut relative_path = path::PathBuf::new(); + for _ in dest_components { + relative_path.push(".."); + } + relative_path.push(non_relative_path); + for s in src_components { + relative_path.push(s); + } + unix::fs::symlink(relative_path, &dest_buf)?; + + progress.set_files_processed(progress.files_processed() + 1); + progress.set_bytes_processed(progress.bytes_processed() + 1); + } + Ok(progress) + } + fn delete( &self, _tx: mpsc::Sender, -- cgit v1.2.3