mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
6f74d84a6e
commit
f63746371e
4 changed files with 57 additions and 36 deletions
|
|
@ -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"]}
|
||||
|
|
@ -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) => {
|
||||
|
|
@ -142,7 +142,11 @@ 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()))?;
|
||||
|
|
@ -150,7 +154,7 @@ impl File {
|
|||
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);
|
||||
}
|
||||
|
|
@ -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>());
|
||||
|
|
@ -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?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue