maildir: mark removed paths
Remove events almost always come immediately before Rename events, showing that the previous name of a file is removed and then renamed. Keep proper tabs by marking removed paths instead of actually removing them.embed
parent
c87ed5012d
commit
ac04195007
|
@ -73,10 +73,13 @@ impl MaildirOp {
|
|||
debug!("{:#?}", e);
|
||||
}
|
||||
}
|
||||
if let Some(path) = &map[&self.hash].modified {
|
||||
path.clone()
|
||||
if let Some(modif) = &map[&self.hash].modified {
|
||||
match modif {
|
||||
PathMod::Path(ref path) => path.clone(),
|
||||
PathMod::Hash(hash) => map[&hash].to_path_buf(),
|
||||
}
|
||||
} else {
|
||||
map.get(&self.hash).unwrap().buf.to_path_buf()
|
||||
map.get(&self.hash).unwrap().to_path_buf()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +164,7 @@ impl<'a> BackendOp for MaildirOp {
|
|||
let hash_index = self.hash_index.clone();
|
||||
let mut map = hash_index.lock().unwrap();
|
||||
let map = map.entry(self.folder_hash).or_default();
|
||||
map.entry(old_hash).or_default().modified = Some(new_name.clone());
|
||||
map.entry(old_hash).or_default().modified = Some(PathMod::Path(new_name.clone()));
|
||||
|
||||
debug!("renaming {:?} to {:?}", path, new_name);
|
||||
fs::rename(&path, &new_name)?;
|
||||
|
|
|
@ -49,21 +49,30 @@ use std::result;
|
|||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub(super) enum PathMod {
|
||||
Path(PathBuf),
|
||||
Hash(EnvelopeHash),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct MaildirPath {
|
||||
pub(super) buf: PathBuf,
|
||||
pub(super) modified: Option<PathBuf>,
|
||||
pub(super) modified: Option<PathMod>,
|
||||
pub(super) removed: bool,
|
||||
}
|
||||
|
||||
impl Deref for MaildirPath {
|
||||
type Target = PathBuf;
|
||||
fn deref(&self) -> &PathBuf {
|
||||
assert!(!(self.removed && self.modified.is_none()));
|
||||
&self.buf
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for MaildirPath {
|
||||
fn deref_mut(&mut self) -> &mut PathBuf {
|
||||
assert!(!(self.removed && self.modified.is_none()));
|
||||
&mut self.buf
|
||||
}
|
||||
}
|
||||
|
@ -73,6 +82,7 @@ impl From<PathBuf> for MaildirPath {
|
|||
MaildirPath {
|
||||
buf: val,
|
||||
modified: None,
|
||||
removed: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -321,16 +331,25 @@ impl MailBackend for MaildirType {
|
|||
debug!("removed but not contained in index");
|
||||
continue;
|
||||
};
|
||||
if let Some(path) = &index_lock[&hash].modified {
|
||||
debug!(
|
||||
if let Some(ref modif) = &index_lock[&hash].modified {
|
||||
match modif {
|
||||
PathMod::Path(path) => debug!(
|
||||
"envelope {} has modified path set {}",
|
||||
hash,
|
||||
path.display()
|
||||
);
|
||||
),
|
||||
PathMod::Hash(hash) => debug!(
|
||||
"envelope {} has modified path set {}",
|
||||
hash,
|
||||
&index_lock[&hash].buf.display()
|
||||
),
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
index_lock.remove(&hash);
|
||||
index_lock.entry(hash).and_modify(|e| {
|
||||
e.removed = true;
|
||||
});
|
||||
|
||||
sender.send(RefreshEvent {
|
||||
hash: folder_hash,
|
||||
|
@ -356,7 +375,11 @@ impl MailBackend for MaildirType {
|
|||
hash: get_path_hash!(dest),
|
||||
kind: Rename(old_hash, new_hash),
|
||||
});
|
||||
index_lock.remove(&old_hash);
|
||||
index_lock.entry(old_hash).and_modify(|e| {
|
||||
debug!(&e.modified);
|
||||
e.modified = Some(PathMod::Hash(new_hash));
|
||||
e.removed = false;
|
||||
});
|
||||
index_lock.insert(new_hash, dest.into());
|
||||
continue;
|
||||
} else if !index_lock.contains_key(&new_hash) {
|
||||
|
|
Loading…
Reference in New Issue