diff options
author | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2019-08-01 12:04:38 +0300 |
---|---|---|
committer | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2019-08-02 01:00:37 +0300 |
commit | ac041950078310e325e5a22e50a73f647b84c972 (patch) | |
tree | 6e69170ed97dab13be002d9e713a21b3b394251f /melib | |
parent | c87ed5012d98fcd2ebbd202bcf7b805f4037c8cc (diff) |
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.
Diffstat (limited to 'melib')
-rw-r--r-- | melib/src/backends/maildir.rs | 11 | ||||
-rw-r--r-- | melib/src/backends/maildir/backend.rs | 41 |
2 files changed, 39 insertions, 13 deletions
diff --git a/melib/src/backends/maildir.rs b/melib/src/backends/maildir.rs index 9dd3c8cc..be6de086 100644 --- a/melib/src/backends/maildir.rs +++ b/melib/src/backends/maildir.rs @@ -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)?; diff --git a/melib/src/backends/maildir/backend.rs b/melib/src/backends/maildir/backend.rs index 41d81874..2c5c053c 100644 --- a/melib/src/backends/maildir/backend.rs +++ b/melib/src/backends/maildir/backend.rs @@ -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!( - "envelope {} has modified path set {}", - hash, - path.display() - ); + 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) { |