Skip to content

Commit

Permalink
..
Browse files Browse the repository at this point in the history
  • Loading branch information
sxyazi committed Sep 18, 2024
1 parent e76adae commit eabadab
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 40 deletions.
6 changes: 3 additions & 3 deletions yazi-core/src/manager/commands/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use anyhow::Result;
use tokio::fs;
use yazi_config::popup::{ConfirmCfg, InputCfg};
use yazi_proxy::{ConfirmProxy, InputProxy, TabProxy, WATCHER};
use yazi_shared::{event::Cmd, fs::{maybe_exists, ok_or_not_found, symlink_realname2, File, FilesOp, Url, UrnBuf}};
use yazi_shared::{event::Cmd, fs::{maybe_exists, ok_or_not_found, realname, File, FilesOp, Url, UrnBuf}};

use crate::manager::Manager;

Expand Down Expand Up @@ -48,9 +48,9 @@ impl Manager {

if dir {
fs::create_dir_all(&new).await?;
} else if let Ok(real) = symlink_realname2(&new).await {
} else if let Some(real) = realname(&new).await {
ok_or_not_found(fs::remove_file(&new).await)?;
FilesOp::Deleting(parent.clone(), HashSet::from_iter([UrnBuf::_from2(real)])).emit();
FilesOp::Deleting(parent.clone(), HashSet::from_iter([UrnBuf::_from(real)])).emit();
fs::File::create(&new).await?;
} else {
fs::create_dir_all(&parent).await.ok();
Expand Down
17 changes: 11 additions & 6 deletions yazi-core/src/manager/commands/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use tokio::fs;
use yazi_config::popup::{ConfirmCfg, InputCfg};
use yazi_dds::Pubsub;
use yazi_proxy::{ConfirmProxy, InputProxy, TabProxy, WATCHER};
use yazi_shared::{event::Cmd, fs::{maybe_exists, ok_or_not_found, paths_to_same_file, symlink_realname2, File, FilesOp, Url, UrnBuf}};
use yazi_shared::{event::Cmd, fs::{maybe_exists, ok_or_not_found, paths_to_same_file, realname, File, FilesOp, Url, UrnBuf}};

use crate::manager::Manager;

Expand Down Expand Up @@ -78,18 +78,23 @@ impl Manager {
let Some((p_new, n_new)) = new.pair() else { return Ok(()) };
let _permit = WATCHER.acquire().await.unwrap();

let overwritten = symlink_realname2(&new).await;
let overwritten = realname(&new).await;
fs::rename(&old, &new).await?;

if let Ok(o) = overwritten {
if let Some(o) = overwritten {
ok_or_not_found(fs::rename(p_new.join(&o), &new).await)?;
FilesOp::Deleting(p_new.clone(), HashSet::from_iter([UrnBuf::_from2(o)])).emit();
FilesOp::Deleting(p_new.clone(), HashSet::from_iter([UrnBuf::_from(o)])).emit();
}
Pubsub::pub_from_rename(tab, &old, &new);

let file = File::from(new.clone()).await?;
FilesOp::Deleting(p_old, HashSet::from_iter([n_old])).emit();
FilesOp::Upserting(p_new, HashMap::from_iter([(n_new, file)])).emit();
if p_new == p_old {
FilesOp::Upserting(p_old, HashMap::from_iter([(n_old, file)])).emit();
} else {
FilesOp::Deleting(p_old, HashSet::from_iter([n_old])).emit();
FilesOp::Upserting(p_new, HashMap::from_iter([(n_new, file)])).emit();
}

Ok(TabProxy::reveal(&new))
}

Expand Down
4 changes: 2 additions & 2 deletions yazi-core/src/manager/watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use tracing::error;
use yazi_fs::{Files, Folder};
use yazi_plugin::isolate;
use yazi_proxy::WATCHER;
use yazi_shared::{fs::{symlink_realname, Cha, File, FilesOp, Url}, RoCell};
use yazi_shared::{fs::{realname_unchecked, Cha, File, FilesOp, Url}, RoCell};

use super::Linked;

Expand Down Expand Up @@ -133,7 +133,7 @@ impl Watcher {

let u = file.url();
let eq = (!file.is_link() && fs::canonicalize(u).await.is_ok_and(|p| p == **u))
|| symlink_realname(u, &mut cached).await.is_ok_and(|s| s == urn._deref()._as_path());
|| realname_unchecked(u, &mut cached).await.is_ok_and(|s| s == urn._deref()._as_path());

if !eq {
FilesOp::Deleting(parent, HashSet::from_iter([urn])).emit();
Expand Down
41 changes: 23 additions & 18 deletions yazi-core/src/manager/yanked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,31 @@ impl Yanked {
}

pub fn apply_op(&mut self, op: &FilesOp) {
// FIXME
// let (removal, addition) = match op {
// FilesOp::Deleting(_, urns) => (urns.iter().collect(), vec![]),
// FilesOp::Updating(_, urns) | FilesOp::Upserting(_, urns) => {
// urns.iter().filter(|(u, _)| self.contains(u)).map(|(u, f)| (u,
// f.url_owned())).unzip() }
// _ => (vec![], vec![]),
// };
let (removal, addition) = match op {
FilesOp::Deleting(cwd, urns) => {
(urns.iter().map(|u| cwd.join(u._deref()._as_path())).collect(), vec![])
}
FilesOp::Updating(cwd, urns) | FilesOp::Upserting(cwd, urns) => urns
.iter()
.filter(|&(u, f)| u != f.urn())
.map(|(u, f)| (cwd.join(u._deref()._as_path()), f))
.filter(|(u, _)| self.contains(u))
.map(|(u, f)| (u, f.url_owned()))
.unzip(),
_ => (vec![], vec![]),
};

// if !removal.is_empty() {
// let old = self.urls.len();
// self.urls.retain(|u| !removal.contains(&u));
// self.revision += (old != self.urls.len()) as u64;
// }
if !removal.is_empty() {
let old = self.urls.len();
self.urls.retain(|u| !removal.contains(u));
self.revision += (old != self.urls.len()) as u64;
}

// if !addition.is_empty() {
// let old = self.urls.len();
// self.urls.extend(addition);
// self.revision += (old != self.urls.len()) as u64;
// }
if !addition.is_empty() {
let old = self.urls.len();
self.urls.extend(addition);
self.revision += (old != self.urls.len()) as u64;
}
}

pub fn catchup_revision(&mut self, force: bool) -> bool {
Expand Down
25 changes: 14 additions & 11 deletions yazi-shared/src/fs/fns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,22 @@ async fn _paths_to_same_file(a: &Path, b: &Path) -> std::io::Result<bool> {
Ok(final_name(a).await? == final_name(b).await?)
}

// TODO: figure out a better name
pub async fn symlink_realname2(p: &Path) -> Result<Cow<'_, OsStr>> {
let Some(name) = p.file_name() else { bail!("no filename") };
Ok(if p == fs::canonicalize(p).await? {
Cow::Borrowed(name)
} else {
Cow::Owned(symlink_realname(p, &mut HashMap::new()).await?.into_owned())
})
pub async fn realname(p: &Path) -> Option<OsString> {
let name = p.file_name()?;
if p == fs::canonicalize(p).await.ok()? {
return None;
}

realname_unchecked(p, &mut HashMap::new())
.await
.ok()
.filter(|s| s != name)
.map(|s| s.into_owned())
}

#[cfg(unix)]
#[tokio::test]
async fn test_symlink_realpath() {
async fn test_realname_unchecked() {
fs::remove_dir_all("/tmp/issue-1173").await.ok();
fs::create_dir_all("/tmp/issue-1173/real-dir").await.unwrap();
fs::File::create("/tmp/issue-1173/A").await.unwrap();
Expand All @@ -99,7 +102,7 @@ async fn test_symlink_realpath() {

let c = &mut HashMap::new();
async fn check(a: &str, b: &str, c: &mut HashMap<PathBuf, HashSet<OsString>>) {
assert_eq!(symlink_realname(Path::new(a), c).await.ok(), Some(OsStr::new(b).into()));
assert_eq!(realname_unchecked(Path::new(a), c).await.ok(), Some(OsStr::new(b).into()));
}

check("/tmp/issue-1173/a", "A", c).await;
Expand All @@ -119,7 +122,7 @@ async fn test_symlink_realpath() {
// filesystems.
//
// Make sure the file of the path exists.
pub async fn symlink_realname<'a>(
pub async fn realname_unchecked<'a>(
path: &'a Path,
cached: &'a mut HashMap<PathBuf, HashSet<OsString>>,
) -> Result<Cow<'a, OsStr>> {
Expand Down
4 changes: 4 additions & 0 deletions yazi-shared/src/fs/urn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ impl Borrow<Urn> for UrnBuf {
fn borrow(&self) -> &Urn { Urn::new(&self.0) }
}

impl PartialEq<Urn> for UrnBuf {
fn eq(&self, other: &Urn) -> bool { self.0 == other.0 }
}

impl UrnBuf {
// FIXME: remove this
pub fn _deref(&self) -> &Urn { Urn::new(&self.0) }
Expand Down

0 comments on commit eabadab

Please sign in to comment.