Compare commits

...

2 Commits

Author SHA1 Message Date
Lauri Niskanen
e6a5cc26d4
Change the default keymap for creating links
I removed the absolute link key since absolute path symlinks are usually
not desired as they don't work if the filesystem is ever mounted in a
different path.
2024-07-07 07:22:28 +03:00
Lauri Niskanen
1f3fad2322
Add '--hard' option to 'link' command
Resolves #1258.
2024-07-07 07:22:23 +03:00
6 changed files with 58 additions and 17 deletions

View File

@ -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)" },

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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))?) }

View File

@ -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,
}
}

View File

@ -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();
}