Skip to content

Commit

Permalink
..
Browse files Browse the repository at this point in the history
  • Loading branch information
sxyazi committed Apr 20, 2024
1 parent 6f74d84 commit f637463
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 36 deletions.
2 changes: 1 addition & 1 deletion cspell.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"flagWords":[],"language":"en","version":"0.2","words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","imagesize","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset"]}
{"version":"0.2","flagWords":[],"language":"en","words":["Punct","KEYMAP","splitn","crossterm","YAZI","unar","peekable","ratatui","syntect","pbpaste","pbcopy","ffmpegthumbnailer","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","nvim","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","️ Überzug","️ Überzug","Konsole","Alacritty","Überzug","pkgs","paru","unarchiver","pdftoppm","poppler","prebuild","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","imagesize","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime"]}
41 changes: 15 additions & 26 deletions yazi-scheduler/src/file/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl File {
_ => {}
}

let mut it = copy_with_progress(&task.from, &task.to);
let mut it = copy_with_progress(&task.from, &task.to, task.meta.as_ref().unwrap());
while let Some(res) = it.recv().await {
match res {
Ok(0) => {
Expand Down Expand Up @@ -142,15 +142,19 @@ impl File {
}
}

let meta = Self::metadata(&task.from, task.follow).await?;
if task.meta.is_none() {
task.meta = Some(Self::metadata(&task.from, task.follow).await?);
}

let meta = task.meta.as_ref().unwrap();
if !meta.is_dir() {
let id = task.id;
self.prog.send(TaskProg::New(id, meta.len()))?;

if meta.is_file() {
self.queue(FileOp::Paste(task), LOW).await?;
} else if meta.is_symlink() {
self.queue(FileOp::Link(task.to_link(meta)), NORMAL).await?;
self.queue(FileOp::Link(task.into()), NORMAL).await?;
}
return self.succ(id);
}
Expand All @@ -168,9 +172,9 @@ impl File {
};
}

let root = task.to.clone();
let root = &task.to;
let skip = task.from.components().count();
let mut dirs = VecDeque::from([task.from]);
let mut dirs = VecDeque::from([task.from.clone()]);

while let Some(src) = dirs.pop_front() {
let dest = root.join(src.components().skip(skip).collect::<PathBuf>());
Expand All @@ -181,22 +185,21 @@ impl File {

let mut it = continue_unless_ok!(fs::read_dir(&src).await);
while let Ok(Some(entry)) = it.next_entry().await {
let src = Url::from(entry.path());
let meta = continue_unless_ok!(Self::metadata(&src, task.follow).await);
let from = Url::from(entry.path());
let meta = continue_unless_ok!(Self::metadata(&from, task.follow).await);

if meta.is_dir() {
dirs.push_back(src);
dirs.push_back(from);
continue;
}

task.to = dest.join(src.file_name().unwrap());
task.from = src;
let to = dest.join(from.file_name().unwrap());
self.prog.send(TaskProg::New(task.id, meta.len()))?;

if meta.is_file() {
self.queue(FileOp::Paste(task.clone()), LOW).await?;
self.queue(FileOp::Paste(task.spawn(to, from, meta)), LOW).await?;
} else if meta.is_symlink() {
self.queue(FileOp::Link(task.to_link(meta)), NORMAL).await?;
self.queue(FileOp::Link(task.spawn(to, from, meta).into()), NORMAL).await?;
}
}
}
Expand Down Expand Up @@ -303,17 +306,3 @@ impl File {
self.macro_.send(op.into(), priority).await.map_err(|_| anyhow!("Failed to send task"))
}
}

impl FileOpPaste {
fn to_link(&self, meta: Metadata) -> FileOpLink {
FileOpLink {
id: self.id,
from: self.from.clone(),
to: self.to.clone(),
meta: Some(meta),
resolve: true,
relative: false,
delete: self.cut,
}
}
}
29 changes: 29 additions & 0 deletions yazi-scheduler/src/file/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,26 @@ pub struct FileOpPaste {
pub id: usize,
pub from: Url,
pub to: Url,
pub meta: Option<Metadata>,
pub cut: bool,
pub follow: bool,
pub retry: u8,
}

impl FileOpPaste {
pub(super) fn spawn(&self, from: Url, to: Url, meta: Metadata) -> Self {
Self {
id: self.id,
from,
to,
meta: Some(meta),
cut: self.cut,
follow: self.follow,
retry: self.retry,
}
}
}

#[derive(Clone, Debug)]
pub struct FileOpLink {
pub id: usize,
Expand All @@ -42,6 +57,20 @@ pub struct FileOpLink {
pub delete: bool,
}

impl From<FileOpPaste> for FileOpLink {
fn from(value: FileOpPaste) -> Self {
Self {
id: value.id,
from: value.from.clone(),
to: value.to.clone(),
meta: value.meta.clone(),
resolve: true,
relative: false,
delete: value.cut,
}
}
}

#[derive(Clone, Debug)]
pub struct FileOpDelete {
pub id: usize,
Expand Down
21 changes: 12 additions & 9 deletions yazi-shared/src/fs/fns.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::VecDeque, path::{Path, PathBuf}};
use std::{collections::VecDeque, fs::Metadata, path::{Path, PathBuf}};

use anyhow::Result;
use filetime::{set_file_times, FileTime};
Expand Down Expand Up @@ -35,22 +35,25 @@ pub async fn calculate_size(path: &Path) -> u64 {
total
}

pub fn copy_with_progress(from: &Path, to: &Path) -> mpsc::Receiver<Result<u64, io::Error>> {
pub fn copy_with_progress(
from: &Path,
to: &Path,
meta: &Metadata,
) -> mpsc::Receiver<Result<u64, io::Error>> {
let (tx, rx) = mpsc::channel(1);
let (tick_tx, mut tick_rx) = oneshot::channel();

tokio::spawn({
let (from, to) = (from.to_path_buf(), to.to_path_buf());
let (from, to, meta) = (from.to_owned(), to.to_owned(), meta.clone());

async move {
_ = match fs::copy(&from, &to).await {
Ok(len) => {
// Attempt to preserve file's accessed at and modified at timestamps
if let Ok(metadata) = fs::metadata(from).await {
let mtime = FileTime::from_last_modification_time(&metadata);
let atime = FileTime::from_last_access_time(&metadata);
_ = set_file_times(to, atime, mtime);
};
_ = set_file_times(
to,
FileTime::from_last_access_time(&meta),
FileTime::from_last_modification_time(&meta),
);

tick_tx.send(Ok(len))
}
Expand Down

0 comments on commit f637463

Please sign in to comment.