maildir: update mailbox unread count on file rename event

memfd
Manos Pitsidianakis 2020-05-06 17:38:29 +03:00
parent d580b25415
commit 330134af5a
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
2 changed files with 56 additions and 27 deletions

View File

@ -96,30 +96,10 @@ impl<'a> BackendOp for MaildirOp {
/* Unwrap is safe since we use ? above. */
Ok(unsafe { self.slice.as_ref().unwrap().as_slice() })
}
fn fetch_flags(&self) -> Flag {
let mut flag = Flag::default();
let path = self.path();
let path = path.to_str().unwrap(); // Assume UTF-8 validity
if !path.contains(":2,") {
return flag;
}
for f in path.chars().rev() {
match f {
',' => break,
'D' => flag |= Flag::DRAFT,
'F' => flag |= Flag::FLAGGED,
'P' => flag |= Flag::PASSED,
'R' => flag |= Flag::REPLIED,
'S' => flag |= Flag::SEEN,
'T' => flag |= Flag::TRASHED,
_ => {
debug!("DEBUG: in fetch_flags, path is {}", path);
}
}
}
flag
path.flags()
}
fn set_flag(&mut self, envelope: &mut Envelope, f: Flag, value: bool) -> Result<()> {
@ -313,3 +293,34 @@ impl BackendMailbox for MaildirMailbox {
Ok((*self.unseen.lock()?, *self.total.lock()?))
}
}
pub trait MaildirPathTrait {
fn flags(&self) -> Flag;
}
impl MaildirPathTrait for Path {
fn flags(&self) -> Flag {
let mut flag = Flag::default();
let path = self.to_string_lossy();
if !path.contains(":2,") {
return flag;
}
for f in path.chars().rev() {
match f {
',' => break,
'D' => flag |= Flag::DRAFT,
'F' => flag |= Flag::FLAGGED,
'P' => flag |= Flag::PASSED,
'R' => flag |= Flag::REPLIED,
'S' => flag |= Flag::SEEN,
'T' => flag |= Flag::TRASHED,
_ => {
debug!("DEBUG: in MaildirPathTrait::flags(), encountered unknown flag marker {:?}, path is {}", f, path);
}
}
}
flag
}
}

View File

@ -20,7 +20,7 @@
*/
use super::{
BackendMailbox, BackendOp, MailBackend, Mailbox, MailboxHash, RefreshEvent,
BackendMailbox, BackendOp, MailBackend, Mailbox, MailboxHash, MaildirPathTrait, RefreshEvent,
RefreshEventConsumer, RefreshEventKind::*,
};
use super::{MaildirMailbox, MaildirOp};
@ -485,15 +485,20 @@ impl MailBackend for MaildirType {
&index_lock[&hash].buf.display()
),
}
index_lock.entry(hash).and_modify(|e| {
e.removed = false;
});
continue;
}
*mailbox_counts[&mailbox_hash].1.lock().unwrap() -= 1;
if !pathbuf.flags().contains(Flag::SEEN) {
*mailbox_counts[&mailbox_hash].0.lock().unwrap() -= 1;
}
index_lock.entry(hash).and_modify(|e| {
e.removed = true;
});
//FIXME: check if envelope was unseen to update unseen count
*mailbox_counts[&mailbox_hash].1.lock().unwrap() += 1;
sender.send(RefreshEvent {
hash: mailbox_hash,
kind: Remove(hash),
@ -511,6 +516,10 @@ impl MailBackend for MaildirType {
let mut hash_indexes_lock = hash_indexes.lock().unwrap();
let index_lock = hash_indexes_lock.entry(mailbox_hash).or_default();
// TODO: Represent index states with an enum: make illegal
// states unrepresentable.
let was_seen: bool = src.flags().contains(Flag::SEEN);
let is_seen: bool = dest.flags().contains(Flag::SEEN);
if index_lock.contains_key(&old_hash)
&& !index_lock[&old_hash].removed
@ -524,11 +533,17 @@ impl MailBackend for MaildirType {
hash: get_path_hash!(dest),
kind: Rename(old_hash, new_hash),
});
if !was_seen && is_seen {
let mut lck = mailbox_counts[&mailbox_hash].0.lock().unwrap();
*lck = lck.saturating_sub(1);
} else if was_seen && !is_seen {
*mailbox_counts[&mailbox_hash].0.lock().unwrap() += 1;
}
mailbox_index.lock().unwrap().insert(new_hash,get_path_hash!(dest) );
index_lock.insert(new_hash, dest.into());
continue;
} else if !index_lock.contains_key(&new_hash)
|| index_lock
&& index_lock
.get(&old_hash)
.map(|e| e.removed)
.unwrap_or(false)
@ -571,7 +586,7 @@ impl MailBackend for MaildirType {
if !env.is_seen() {
*mailbox_counts[&mailbox_hash].0.lock().unwrap() += 1;
}
*mailbox_counts[&mailbox_hash].1.lock().unwrap() += 1;
*mailbox_counts[&mailbox_hash].1.lock().unwrap() += 1;
sender.send(RefreshEvent {
hash: mailbox_hash,
kind: Create(Box::new(env)),
@ -581,6 +596,9 @@ impl MailBackend for MaildirType {
debug!("not valid email");
}
} else {
if was_seen && !is_seen {
*mailbox_counts[&mailbox_hash].0.lock().unwrap() += 1;
}
sender.send(RefreshEvent {
hash: get_path_hash!(dest),
kind: Rename(old_hash, new_hash),