mirror of
https://github.com/sxyazi/yazi.git
synced 2024-10-05 14:47:19 +03:00
Compare commits
2 Commits
e6d6548a70
...
e6a5cc26d4
Author | SHA1 | Date | |
---|---|---|---|
|
e6a5cc26d4 | ||
|
1f3fad2322 |
@ -69,8 +69,8 @@ keymap = [
|
||||
{ on = "X", run = "unyank", desc = "Cancel the yank status of files" },
|
||||
{ on = "p", run = "paste", desc = "Paste the files" },
|
||||
{ on = "P", run = "paste --force", desc = "Paste the files (overwrite if the destination exists)" },
|
||||
{ on = "-", run = "link", desc = "Symlink the absolute path of files" },
|
||||
{ on = "_", run = "link --relative", desc = "Symlink the relative path of files" },
|
||||
{ on = "-", run = "link --relative", desc = "Symlink the files" },
|
||||
{ on = "_", run = "link --hard", desc = "Hardlink the files" },
|
||||
{ on = "d", run = "remove", desc = "Move the files to the trash" },
|
||||
{ on = "D", run = "remove --permanently", desc = "Permanently delete the files" },
|
||||
{ on = "a", run = "create", desc = "Create a file or directory (ends with / for directories)" },
|
||||
|
@ -4,11 +4,14 @@ use crate::{manager::Manager, tasks::Tasks};
|
||||
|
||||
pub struct Opt {
|
||||
relative: bool,
|
||||
hard: bool,
|
||||
force: bool,
|
||||
}
|
||||
|
||||
impl From<Cmd> for Opt {
|
||||
fn from(c: Cmd) -> Self { Self { relative: c.bool("relative"), force: c.bool("force") } }
|
||||
fn from(c: Cmd) -> Self {
|
||||
Self { relative: c.bool("relative"), hard: c.bool("hard"), force: c.bool("force") }
|
||||
}
|
||||
}
|
||||
|
||||
impl Manager {
|
||||
@ -18,6 +21,6 @@ impl Manager {
|
||||
}
|
||||
|
||||
let opt = opt.into() as Opt;
|
||||
tasks.file_link(&self.yanked, self.cwd(), opt.relative, opt.force);
|
||||
tasks.file_link(&self.yanked, self.cwd(), opt.relative, opt.hard, opt.force);
|
||||
}
|
||||
}
|
||||
|
@ -28,13 +28,13 @@ impl Tasks {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn file_link(&self, src: &HashSet<Url>, dest: &Url, relative: bool, force: bool) {
|
||||
pub fn file_link(&self, src: &HashSet<Url>, dest: &Url, relative: bool, hard: bool, force: bool) {
|
||||
for u in src {
|
||||
let to = dest.join(u.file_name().unwrap());
|
||||
if force && *u == to {
|
||||
debug!("file_link: same file, skipping {:?}", to);
|
||||
} else {
|
||||
self.scheduler.file_link(u.clone(), to, relative, force);
|
||||
self.scheduler.file_link(u.clone(), to, relative, hard, force);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,16 +81,25 @@ impl File {
|
||||
};
|
||||
|
||||
ok_or_not_found(fs::remove_file(&task.to).await)?;
|
||||
#[cfg(unix)]
|
||||
{
|
||||
fs::symlink(src, &task.to).await?
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if meta.is_dir() {
|
||||
fs::symlink_dir(src, &task.to).await?
|
||||
|
||||
if task.hard {
|
||||
if src.is_dir() {
|
||||
hard_link_directory(src, &task.to).await?;
|
||||
} else {
|
||||
fs::symlink_file(src, &task.to).await?
|
||||
fs::hard_link(src, &task.to).await?;
|
||||
}
|
||||
} else {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
fs::symlink(src, &task.to).await?
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if meta.is_dir() {
|
||||
fs::symlink_dir(src, &task.to).await?
|
||||
} else {
|
||||
fs::symlink_file(src, &task.to).await?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,6 +285,24 @@ impl File {
|
||||
}
|
||||
}
|
||||
|
||||
async fn hard_link_directory(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<()> {
|
||||
fs::create_dir(&dst).await?;
|
||||
|
||||
let mut directory = fs::read_dir(src).await?;
|
||||
|
||||
while let Some(entry) = directory.next_entry().await? {
|
||||
let target_path = dst.as_ref().join(entry.file_name());
|
||||
|
||||
if entry.file_type().await?.is_dir() {
|
||||
Box::pin(hard_link_directory(entry.path(), target_path)).await?;
|
||||
} else {
|
||||
fs::hard_link(entry.path(), target_path).await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl File {
|
||||
#[inline]
|
||||
fn succ(&self, id: usize) -> Result<()> { Ok(self.prog.send(TaskProg::Succ(id))?) }
|
||||
|
@ -54,6 +54,7 @@ pub struct FileOpLink {
|
||||
pub meta: Option<Metadata>,
|
||||
pub resolve: bool,
|
||||
pub relative: bool,
|
||||
pub hard: bool,
|
||||
pub delete: bool,
|
||||
}
|
||||
|
||||
@ -66,6 +67,7 @@ impl From<FileOpPaste> for FileOpLink {
|
||||
meta: value.meta,
|
||||
resolve: true,
|
||||
relative: false,
|
||||
hard: false,
|
||||
delete: value.cut,
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ impl Scheduler {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn file_link(&self, from: Url, mut to: Url, relative: bool, force: bool) {
|
||||
pub fn file_link(&self, from: Url, mut to: Url, relative: bool, hard: bool, force: bool) {
|
||||
let name = format!("Link {from:?} to {to:?}");
|
||||
let id = self.ongoing.lock().add(TaskKind::User, name);
|
||||
|
||||
@ -145,7 +145,16 @@ impl Scheduler {
|
||||
to = unique_path(to).await;
|
||||
}
|
||||
file
|
||||
.link(FileOpLink { id, from, to, meta: None, resolve: false, relative, delete: false })
|
||||
.link(FileOpLink {
|
||||
id,
|
||||
from,
|
||||
to,
|
||||
meta: None,
|
||||
resolve: false,
|
||||
relative,
|
||||
hard,
|
||||
delete: false,
|
||||
})
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user