summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2020-09-11 16:58:56 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2020-09-11 17:02:27 +0300
commit4829e13c478021bd96690287509008049b8d8732 (patch)
tree79691c8c0a3e144ca01b2e827158c218c8b1f818
parenta1585d40069f4bb6b14aae9a092d4c14597ac320 (diff)
melib/maildir: impl copy_messages for Maildir
-rw-r--r--melib/src/backends.rs26
-rw-r--r--melib/src/backends/imap.rs4
-rw-r--r--melib/src/backends/jmap.rs1
-rw-r--r--melib/src/backends/maildir/backend.rs220
-rw-r--r--melib/src/backends/mbox.rs19
-rw-r--r--melib/src/backends/nntp.rs1
-rw-r--r--melib/src/backends/notmuch.rs10
-rw-r--r--src/components/mail/listing.rs2
-rw-r--r--src/components/mail/listing/conversations.rs6
-rw-r--r--src/conf/accounts.rs4
10 files changed, 237 insertions, 56 deletions
diff --git a/melib/src/backends.rs b/melib/src/backends.rs
index bad05eb5..242cf0a1 100644
--- a/melib/src/backends.rs
+++ b/melib/src/backends.rs
@@ -318,24 +318,22 @@ pub trait MailBackend: ::std::fmt::Debug + Send + Sync {
mailbox_hash: MailboxHash,
flags: Option<Flag>,
) -> ResultFuture<()>;
+
fn copy_messages(
&mut self,
- _env_hashes: EnvelopeHashBatch,
- _source_mailbox_hash: MailboxHash,
- _destination_mailbox_hash: MailboxHash,
- _move_: bool,
- _destination_flags: Option<Flag>,
- ) -> ResultFuture<()> {
- Err(MeliError::new("Unimplemented."))
- }
+ env_hashes: EnvelopeHashBatch,
+ source_mailbox_hash: MailboxHash,
+ destination_mailbox_hash: MailboxHash,
+ move_: bool,
+ ) -> ResultFuture<()>;
+
fn set_flags(
&mut self,
- _env_hashes: EnvelopeHashBatch,
- _mailbox_hash: MailboxHash,
- _flags: SmallVec<[(std::result::Result<Flag, String>, bool); 8]>,
- ) -> ResultFuture<()> {
- Err(MeliError::new("Unimplemented."))
- }
+ env_hashes: EnvelopeHashBatch,
+ mailbox_hash: MailboxHash,
+ flags: SmallVec<[(std::result::Result<Flag, String>, bool); 8]>,
+ ) -> ResultFuture<()>;
+
fn delete_messages(
&self,
_env_hashes: EnvelopeHashBatch,
diff --git a/melib/src/backends/imap.rs b/melib/src/backends/imap.rs
index 4086eb60..c6cbefcb 100644
--- a/melib/src/backends/imap.rs
+++ b/melib/src/backends/imap.rs
@@ -533,7 +533,6 @@ impl MailBackend for ImapType {
source_mailbox_hash: MailboxHash,
destination_mailbox_hash: MailboxHash,
move_: bool,
- destination_flags: Option<Flag>,
) -> ResultFuture<()> {
let uid_store = self.uid_store.clone();
let connection = self.connection.clone();
@@ -607,9 +606,6 @@ impl MailBackend for ImapType {
conn.send_command(command.as_bytes()).await?;
conn.read_response(&mut response, RequiredResponses::empty())
.await?;
- if let Some(_flags) = destination_flags {
- //FIXME
- }
if move_ {
let command = {
let mut cmd = format!("UID STORE {}", uids[0]);
diff --git a/melib/src/backends/jmap.rs b/melib/src/backends/jmap.rs
index ea88c3ac..c3cf9b35 100644
--- a/melib/src/backends/jmap.rs
+++ b/melib/src/backends/jmap.rs
@@ -380,7 +380,6 @@ impl MailBackend for JmapType {
_source_mailbox_hash: MailboxHash,
_destination_mailbox_hash: MailboxHash,
_move_: bool,
- _destination_flags: Option<Flag>,
) -> ResultFuture<()> {
Err(MeliError::new("Unimplemented."))
}
diff --git a/melib/src/backends/maildir/backend.rs b/melib/src/backends/maildir/backend.rs
index b969acdb..a0e759c5 100644
--- a/melib/src/backends/maildir/backend.rs
+++ b/melib/src/backends/maildir/backend.rs
@@ -23,7 +23,7 @@ use super::{MaildirMailbox, MaildirOp, MaildirPathTrait};
use crate::backends::{RefreshEventKind::*, *};
use crate::conf::AccountSettings;
use crate::email::{Envelope, EnvelopeHash, Flag};
-use crate::error::{MeliError, Result};
+use crate::error::{ErrorKind, MeliError, Result};
use crate::shellexpand::ShellExpandTrait;
use futures::prelude::Stream;
@@ -565,6 +565,14 @@ impl MailBackend for MaildirType {
DebouncedEvent::Rename(src, dest) => {
debug!("DebouncedEvent::Rename(src = {:?}, dest = {:?})", src, dest);
let mailbox_hash = get_path_hash!(src);
+ let dest_mailbox = {
+ let dest_mailbox = get_path_hash!(dest);
+ if dest_mailbox == mailbox_hash {
+ None
+ } else {
+ Some(dest_mailbox)
+ }
+ };
let old_hash: EnvelopeHash = get_file_hash(src.as_path());
let new_hash: EnvelopeHash = get_file_hash(dest.as_path());
@@ -578,39 +586,88 @@ impl MailBackend for MaildirType {
if index_lock.contains_key(&old_hash) && !index_lock[&old_hash].removed
{
debug!("contains_old_key");
- index_lock.entry(old_hash).and_modify(|e| {
- debug!(&e.modified);
- e.modified = Some(PathMod::Hash(new_hash));
- });
- (sender)(
- account_hash,
- BackendEvent::Refresh(RefreshEvent {
+ if let Some(dest_mailbox) = dest_mailbox {
+ index_lock.entry(old_hash).and_modify(|e| {
+ e.removed = true;
+ });
+
+ (sender)(
account_hash,
- mailbox_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;
- }
- if old_flags != new_flags {
+ BackendEvent::Refresh(RefreshEvent {
+ account_hash,
+ mailbox_hash,
+ kind: Remove(old_hash),
+ }),
+ );
+ let file_name = dest
+ .as_path()
+ .strip_prefix(&root_path)
+ .unwrap()
+ .to_path_buf();
+ drop(hash_indexes_lock);
+ if let Ok(env) = add_path_to_index(
+ &hash_indexes,
+ dest_mailbox,
+ dest.as_path(),
+ &cache_dir,
+ file_name,
+ ) {
+ mailbox_index
+ .lock()
+ .unwrap()
+ .insert(env.hash(), dest_mailbox);
+ debug!(
+ "Create event {} {} {}",
+ env.hash(),
+ env.subject(),
+ dest.display()
+ );
+ if !env.is_seen() {
+ *mailbox_counts[&dest_mailbox].0.lock().unwrap() += 1;
+ }
+ *mailbox_counts[&dest_mailbox].1.lock().unwrap() += 1;
+ (sender)(
+ account_hash,
+ BackendEvent::Refresh(RefreshEvent {
+ account_hash,
+ mailbox_hash: dest_mailbox,
+ kind: Create(Box::new(env)),
+ }),
+ );
+ }
+ } else {
+ index_lock.entry(old_hash).and_modify(|e| {
+ debug!(&e.modified);
+ e.modified = Some(PathMod::Hash(new_hash));
+ });
(sender)(
account_hash,
BackendEvent::Refresh(RefreshEvent {
account_hash,
- mailbox_hash: get_path_hash!(dest),
- kind: NewFlags(new_hash, (new_flags, vec![])),
+ mailbox_hash,
+ 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;
+ }
+ if old_flags != new_flags {
+ (sender)(
+ account_hash,
+ BackendEvent::Refresh(RefreshEvent {
+ account_hash,
+ mailbox_hash,
+ kind: NewFlags(new_hash, (new_flags, vec![])),
+ }),
+ );
+ }
+ mailbox_index.lock().unwrap().insert(new_hash, mailbox_hash);
+ index_lock.insert(new_hash, dest.into());
}
- 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
@@ -640,7 +697,7 @@ impl MailBackend for MaildirType {
drop(hash_indexes_lock);
if let Ok(env) = add_path_to_index(
&hash_indexes,
- mailbox_hash,
+ dest_mailbox.unwrap_or(mailbox_hash),
dest.as_path(),
&cache_dir,
file_name,
@@ -648,7 +705,7 @@ impl MailBackend for MaildirType {
mailbox_index
.lock()
.unwrap()
- .insert(env.hash(), mailbox_hash);
+ .insert(env.hash(), dest_mailbox.unwrap_or(mailbox_hash));
debug!(
"Create event {} {} {}",
env.hash(),
@@ -656,14 +713,20 @@ impl MailBackend for MaildirType {
dest.display()
);
if !env.is_seen() {
- *mailbox_counts[&mailbox_hash].0.lock().unwrap() += 1;
+ *mailbox_counts[&dest_mailbox.unwrap_or(mailbox_hash)]
+ .0
+ .lock()
+ .unwrap() += 1;
}
- *mailbox_counts[&mailbox_hash].1.lock().unwrap() += 1;
+ *mailbox_counts[&dest_mailbox.unwrap_or(mailbox_hash)]
+ .1
+ .lock()
+ .unwrap() += 1;
(sender)(
account_hash,
BackendEvent::Refresh(RefreshEvent {
account_hash,
- mailbox_hash,
+ mailbox_hash: dest_mailbox.unwrap_or(mailbox_hash),
kind: Create(Box::new(env)),
}),
);
@@ -671,6 +734,43 @@ impl MailBackend for MaildirType {
} else {
debug!("not valid email");
}
+ } else if let Some(dest_mailbox) = dest_mailbox {
+ drop(hash_indexes_lock);
+ let file_name = dest
+ .as_path()
+ .strip_prefix(&root_path)
+ .unwrap()
+ .to_path_buf();
+ if let Ok(env) = add_path_to_index(
+ &hash_indexes,
+ dest_mailbox,
+ dest.as_path(),
+ &cache_dir,
+ file_name,
+ ) {
+ mailbox_index
+ .lock()
+ .unwrap()
+ .insert(env.hash(), dest_mailbox);
+ debug!(
+ "Create event {} {} {}",
+ env.hash(),
+ env.subject(),
+ dest.display()
+ );
+ if !env.is_seen() {
+ *mailbox_counts[&dest_mailbox].0.lock().unwrap() += 1;
+ }
+ *mailbox_counts[&dest_mailbox].1.lock().unwrap() += 1;
+ (sender)(
+ account_hash,
+ BackendEvent::Refresh(RefreshEvent {
+ account_hash,
+ mailbox_hash: dest_mailbox,
+ kind: Create(Box::new(env)),
+ }),
+ );
+ }
} else {
if was_seen && !is_seen {
*mailbox_counts[&mailbox_hash].0.lock().unwrap() += 1;
@@ -679,7 +779,7 @@ impl MailBackend for MaildirType {
account_hash,
BackendEvent::Refresh(RefreshEvent {
account_hash,
- mailbox_hash: get_path_hash!(dest),
+ mailbox_hash,
kind: Rename(old_hash, new_hash),
}),
);
@@ -689,7 +789,7 @@ impl MailBackend for MaildirType {
account_hash,
BackendEvent::Refresh(RefreshEvent {
account_hash,
- mailbox_hash: get_path_hash!(dest),
+ mailbox_hash,
kind: NewFlags(new_hash, (new_flags, vec![])),
}),
);
@@ -813,6 +913,60 @@ impl MailBackend for MaildirType {
}))
}
+ fn copy_messages(
+ &mut self,
+ env_hashes: EnvelopeHashBatch,
+ source_mailbox_hash: MailboxHash,
+ destination_mailbox_hash: MailboxHash,
+ move_: bool,
+ ) -> ResultFuture<()> {
+ let hash_index = self.hash_indexes.clone();
+ if !self.mailboxes.contains_key(&source_mailbox_hash) {
+ return Err(MeliError::new("Invalid source mailbox hash").set_kind(ErrorKind::Bug));
+ } else if !self.mailboxes.contains_key(&destination_mailbox_hash) {
+ return Err(MeliError::new("Invalid destination mailbox hash").set_kind(ErrorKind::Bug));
+ }
+ let mut dest_path: PathBuf = self.mailboxes[&destination_mailbox_hash].fs_path().into();
+ dest_path.push("cur");
+ Ok(Box::pin(async move {
+ let mut hash_indexes_lck = hash_index.lock().unwrap();
+ let hash_index = hash_indexes_lck.entry(source_mailbox_hash).or_default();
+
+ for env_hash in env_hashes.iter() {
+ let path_src = {
+ if !hash_index.contains_key(&env_hash) {
+ continue;
+ }
+ if let Some(modif) = &hash_index[&env_hash].modified {
+ match modif {
+ PathMod::Path(ref path) => path.clone(),
+ PathMod::Hash(hash) => hash_index[&hash].to_path_buf(),
+ }
+ } else {
+ hash_index[&env_hash].to_path_buf()
+ }
+ };
+ let filename = path_src
+ .file_name()
+ .expect(&format!("Could not get filename of {}", path_src.display()));
+ dest_path.push(filename);
+ hash_index.entry(env_hash).or_default().modified =
+ Some(PathMod::Path(dest_path.clone()));
+ if move_ {
+ debug!("renaming {:?} to {:?}", path_src, dest_path);
+ fs::rename(&path_src, &dest_path)?;
+ debug!("success in rename");
+ } else {
+ debug!("copying {:?} to {:?}", path_src, dest_path);
+ fs::copy(&path_src, &dest_path)?;
+ debug!("success in copy");
+ }
+ dest_path.pop();
+ }
+ Ok(())
+ }))
+ }
+
fn create_mailbox(
&mut self,
new_path: String,
diff --git a/melib/src/backends/mbox.rs b/melib/src/backends/mbox.rs
index 075d8d1c..378ba062 100644
--- a/melib/src/backends/mbox.rs
+++ b/melib/src/backends/mbox.rs
@@ -993,6 +993,25 @@ impl MailBackend for MboxType {
)))
}
+ fn copy_messages(
+ &mut self,
+ _env_hashes: EnvelopeHashBatch,
+ _source_mailbox_hash: MailboxHash,
+ _destination_mailbox_hash: MailboxHash,
+ _move_: bool,
+ ) -> ResultFuture<()> {
+ Err(MeliError::new("Unimplemented."))
+ }
+
+ fn set_flags(
+ &mut self,
+ _env_hashes: EnvelopeHashBatch,
+ _mailbox_hash: MailboxHash,
+ _flags: SmallVec<[(std::result::Result<Flag, String>, bool); 8]>,
+ ) -> ResultFuture<()> {
+ Err(MeliError::new("Unimplemented."))
+ }
+
fn save(
&self,
_bytes: Vec<u8>,
diff --git a/melib/src/backends/nntp.rs b/melib/src/backends/nntp.rs
index eff3fb1d..413c2134 100644
--- a/melib/src/backends/nntp.rs
+++ b/melib/src/backends/nntp.rs
@@ -287,7 +287,6 @@ impl MailBackend for NntpType {
_source_mailbox_hash: MailboxHash,
_destination_mailbox_hash: MailboxHash,
_move_: bool,
- _destination_flags: Option<Flag>,
) -> ResultFuture<()> {
Err(MeliError::new("Unimplemented."))
}
diff --git a/melib/src/backends/notmuch.rs b/melib/src/backends/notmuch.rs
index 5611ff39..512fcf00 100644
--- a/melib/src/backends/notmuch.rs
+++ b/melib/src/backends/notmuch.rs
@@ -684,6 +684,16 @@ impl MailBackend for NotmuchDb {
Ok(Box::pin(async { Ok(()) }))
}
+ fn copy_messages(
+ &mut self,
+ _env_hashes: EnvelopeHashBatch,
+ _source_mailbox_hash: MailboxHash,
+ _destination_mailbox_hash: MailboxHash,
+ _move_: bool,
+ ) -> ResultFuture<()> {
+ Err(MeliError::new("Unimplemented."))
+ }
+
fn set_flags(
&mut self,
env_hashes: EnvelopeHashBatch,
diff --git a/src/components/mail/listing.rs b/src/components/mail/listing.rs
index e5dbce68..0fbece3b 100644
--- a/src/components/mail/listing.rs
+++ b/src/components/mail/listing.rs
@@ -270,7 +270,6 @@ pub trait MailListingTrait: ListingTrait {
mailbox_hash,
destination_mailbox_hash,
/* move? */ false,
- /* flags */ None,
)
}) {
Err(err) => {
@@ -309,7 +308,6 @@ pub trait MailListingTrait: ListingTrait {
mailbox_hash,
destination_mailbox_hash,
/* move? */ true,
- /* flags */ None,
)
}) {
Err(err) => {
diff --git a/src/components/mail/listing/conversations.rs b/src/components/mail/listing/conversations.rs
index a910628d..00e2c31b 100644
--- a/src/components/mail/listing/conversations.rs
+++ b/src/components/mail/listing/conversations.rs
@@ -1437,6 +1437,12 @@ impl Component for ConversationsListing {
);
}
}
+ UIEvent::EnvelopeRemove(ref _env_hash, ref thread_hash) => {
+ if self.order.contains_key(thread_hash) {
+ self.refresh_mailbox(context, false);
+ self.set_dirty(true);
+ }
+ }
UIEvent::EnvelopeUpdate(ref env_hash) => {
let account = &context.accounts[&self.cursor_pos.0];
let threads = account.collection.get_threads(self.cursor_pos.1);
diff --git a/src/conf/accounts.rs b/src/conf/accounts.rs
index 60799871..ffef7325 100644
--- a/src/conf/accounts.rs
+++ b/src/conf/accounts.rs
@@ -605,7 +605,9 @@ impl Account {
}
pub fn reload(&mut self, event: RefreshEvent, mailbox_hash: MailboxHash) -> Option<UIEvent> {
- if !self.mailbox_entries[&mailbox_hash].status.is_available() {
+ if !self.mailbox_entries[&mailbox_hash].status.is_available()
+ && !self.mailbox_entries[&mailbox_hash].status.is_parsing()
+ {
self.event_queue.push_back((mailbox_hash, event));
return None;
}