mirror of
https://github.com/soywod/himalaya.git
synced 2024-07-08 10:35:13 +00:00
improve maildir and notmuch tests
This commit is contained in:
parent
886b66a017
commit
5f13489e83
|
@ -76,42 +76,39 @@ impl IdMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append(&mut self, lines: Vec<(String, String)>) -> Result<usize> {
|
pub fn append(&mut self, lines: Vec<(String, String)>) -> Result<usize> {
|
||||||
let mut entries = String::new();
|
self.extend(lines);
|
||||||
|
|
||||||
self.extend(lines.clone());
|
let mut entries = String::new();
|
||||||
|
let mut short_hash_len = self.short_hash_len;
|
||||||
|
|
||||||
for (hash, id) in self.iter() {
|
for (hash, id) in self.iter() {
|
||||||
entries.push_str(&format!("{} {}\n", hash, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (hash, id) in lines {
|
|
||||||
loop {
|
loop {
|
||||||
let short_hash = &hash[0..self.short_hash_len];
|
let short_hash = &hash[0..self.short_hash_len];
|
||||||
let conflict_found = self
|
let conflict_found = self
|
||||||
.map
|
.map
|
||||||
.keys()
|
.keys()
|
||||||
.find(|cached_hash| {
|
.find(|cached_hash| cached_hash.starts_with(short_hash) && cached_hash != &hash)
|
||||||
cached_hash.starts_with(short_hash) && *cached_hash != &hash
|
|
||||||
})
|
|
||||||
.is_some();
|
.is_some();
|
||||||
if self.short_hash_len > 32 || !conflict_found {
|
if self.short_hash_len > 32 || !conflict_found {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
self.short_hash_len += 1;
|
short_hash_len += 1;
|
||||||
}
|
}
|
||||||
entries.push_str(&format!("{} {}\n", hash, id));
|
entries.push_str(&format!("{} {}\n", hash, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.short_hash_len = short_hash_len;
|
||||||
|
|
||||||
OpenOptions::new()
|
OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.create(true)
|
.create(true)
|
||||||
.truncate(true)
|
.truncate(true)
|
||||||
.open(&self.path)
|
.open(&self.path)
|
||||||
.context("cannot open maildir id hash map cache")?
|
.context("cannot open maildir id hash map cache")?
|
||||||
.write(format!("{}\n{}", self.short_hash_len, entries).as_bytes())
|
.write(format!("{}\n{}", short_hash_len, entries).as_bytes())
|
||||||
.context("cannot write maildir id hash map cache")?;
|
.context("cannot write maildir id hash map cache")?;
|
||||||
|
|
||||||
Ok(self.short_hash_len)
|
Ok(short_hash_len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,12 @@ impl<'a> MaildirBackend<'a> {
|
||||||
// maildir subdirectory by adding a "." in front
|
// maildir subdirectory by adding a "." in front
|
||||||
// of the name as described in the spec:
|
// of the name as described in the spec:
|
||||||
// https://cr.yp.to/proto/maildir.html
|
// https://cr.yp.to/proto/maildir.html
|
||||||
|
let dir = self
|
||||||
|
.account_config
|
||||||
|
.mailboxes
|
||||||
|
.get(dir)
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(dir);
|
||||||
let path = self.mdir.path().join(format!(".{}", dir));
|
let path = self.mdir.path().join(format!(".{}", dir));
|
||||||
self.validate_mdir_path(path)
|
self.validate_mdir_path(path)
|
||||||
})
|
})
|
||||||
|
|
|
@ -193,24 +193,16 @@ impl<'a> Backend<'a> for NotmuchBackend<'a> {
|
||||||
Ok(envelopes)
|
Ok(envelopes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_msg(&mut self, dir: &str, msg: &[u8], tags: &str) -> Result<Box<dyn ToString>> {
|
fn add_msg(&mut self, _: &str, msg: &[u8], tags: &str) -> Result<Box<dyn ToString>> {
|
||||||
info!(">> add notmuch envelopes");
|
info!(">> add notmuch envelopes");
|
||||||
debug!("dir: {:?}", dir);
|
|
||||||
debug!("tags: {:?}", tags);
|
debug!("tags: {:?}", tags);
|
||||||
|
|
||||||
let mdir = self
|
let dir = &self.notmuch_config.notmuch_database_dir;
|
||||||
.mdir
|
|
||||||
.get_mdir_from_dir(dir)
|
|
||||||
.with_context(|| format!("cannot get maildir instance from {:?}", dir))?;
|
|
||||||
let mdir_path_str = mdir
|
|
||||||
.path()
|
|
||||||
.to_str()
|
|
||||||
.ok_or_else(|| anyhow!("cannot parse maildir path to string"))?;
|
|
||||||
|
|
||||||
// Adds the message to the maildir folder and gets its hash.
|
// Adds the message to the maildir folder and gets its hash.
|
||||||
let hash = self
|
let hash = self
|
||||||
.mdir
|
.mdir
|
||||||
.add_msg(mdir_path_str, msg, "seen")
|
.add_msg("inbox", msg, "seen")
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
format!(
|
format!(
|
||||||
"cannot add notmuch message to maildir {:?}",
|
"cannot add notmuch message to maildir {:?}",
|
||||||
|
@ -222,12 +214,13 @@ impl<'a> Backend<'a> for NotmuchBackend<'a> {
|
||||||
|
|
||||||
// Retrieves the file path of the added message by its maildir
|
// Retrieves the file path of the added message by its maildir
|
||||||
// identifier.
|
// identifier.
|
||||||
let id = IdMapper::new(mdir.path())
|
let mut mapper = IdMapper::new(dir)
|
||||||
.with_context(|| format!("cannot create id mapper instance for {:?}", dir))?
|
.with_context(|| format!("cannot create id mapper instance for {:?}", dir))?;
|
||||||
|
let id = mapper
|
||||||
.find(&hash)
|
.find(&hash)
|
||||||
.with_context(|| format!("cannot find notmuch message from short hash {:?}", hash))?;
|
.with_context(|| format!("cannot find notmuch message from short hash {:?}", hash))?;
|
||||||
debug!("id: {:?}", id);
|
debug!("id: {:?}", id);
|
||||||
let file_path = mdir.path().join("cur").join(format!("{}:2,S", id));
|
let file_path = dir.join("cur").join(format!("{}:2,S", id));
|
||||||
debug!("file path: {:?}", file_path);
|
debug!("file path: {:?}", file_path);
|
||||||
|
|
||||||
// Adds the message to the notmuch database by indexing it.
|
// Adds the message to the notmuch database by indexing it.
|
||||||
|
@ -240,13 +233,6 @@ impl<'a> Backend<'a> for NotmuchBackend<'a> {
|
||||||
let hash = format!("{:x}", md5::compute(&id));
|
let hash = format!("{:x}", md5::compute(&id));
|
||||||
|
|
||||||
// Appends hash entry to the id mapper cache file.
|
// Appends hash entry to the id mapper cache file.
|
||||||
let mut mapper =
|
|
||||||
IdMapper::new(&self.notmuch_config.notmuch_database_dir).with_context(|| {
|
|
||||||
format!(
|
|
||||||
"cannot create id mapper instance for {:?}",
|
|
||||||
self.notmuch_config.notmuch_database_dir
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
mapper
|
mapper
|
||||||
.append(vec![(hash.clone(), id.clone())])
|
.append(vec![(hash.clone(), id.clone())])
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
|
@ -264,7 +250,7 @@ impl<'a> Backend<'a> for NotmuchBackend<'a> {
|
||||||
Ok(Box::new(hash))
|
Ok(Box::new(hash))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_msg(&mut self, _virt_mbox: &str, short_hash: &str) -> Result<Msg> {
|
fn get_msg(&mut self, _: &str, short_hash: &str) -> Result<Msg> {
|
||||||
info!(">> add notmuch envelopes");
|
info!(">> add notmuch envelopes");
|
||||||
debug!("short hash: {:?}", short_hash);
|
debug!("short hash: {:?}", short_hash);
|
||||||
|
|
||||||
|
@ -300,7 +286,7 @@ impl<'a> Backend<'a> for NotmuchBackend<'a> {
|
||||||
Ok(msg)
|
Ok(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy_msg(&mut self, _mbox_src: &str, _mbox_dst: &str, _id: &str) -> Result<()> {
|
fn copy_msg(&mut self, _dir_src: &str, _dir_dst: &str, _short_hash: &str) -> Result<()> {
|
||||||
info!(">> copy notmuch message");
|
info!(">> copy notmuch message");
|
||||||
info!("<< copy notmuch message");
|
info!("<< copy notmuch message");
|
||||||
Err(anyhow!(
|
Err(anyhow!(
|
||||||
|
@ -308,7 +294,7 @@ impl<'a> Backend<'a> for NotmuchBackend<'a> {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_msg(&mut self, _src: &str, _dst: &str, _id: &str) -> Result<()> {
|
fn move_msg(&mut self, _dir_src: &str, _dir_dst: &str, _short_hash: &str) -> Result<()> {
|
||||||
info!(">> move notmuch message");
|
info!(">> move notmuch message");
|
||||||
info!("<< move notmuch message");
|
info!("<< move notmuch message");
|
||||||
Err(anyhow!(
|
Err(anyhow!(
|
||||||
|
|
|
@ -19,7 +19,10 @@ fn test_maildir_backend() {
|
||||||
|
|
||||||
// configure accounts
|
// configure accounts
|
||||||
let account_config = AccountConfig {
|
let account_config = AccountConfig {
|
||||||
mailboxes: HashMap::from_iter([("inbox".into(), "INBOX".into())]),
|
mailboxes: HashMap::from_iter([
|
||||||
|
("inbox".into(), "INBOX".into()),
|
||||||
|
("subdir".into(), "Subdir".into()),
|
||||||
|
]),
|
||||||
..AccountConfig::default()
|
..AccountConfig::default()
|
||||||
};
|
};
|
||||||
let mdir_config = MaildirBackendConfig {
|
let mdir_config = MaildirBackendConfig {
|
||||||
|
@ -33,16 +36,16 @@ fn test_maildir_backend() {
|
||||||
|
|
||||||
// check that a message can be added
|
// check that a message can be added
|
||||||
let msg = include_bytes!("./emails/alice-to-patrick.eml");
|
let msg = include_bytes!("./emails/alice-to-patrick.eml");
|
||||||
let hash = mdir.add_msg("INBOX", msg, "seen").unwrap().to_string();
|
let hash = mdir.add_msg("inbox", msg, "seen").unwrap().to_string();
|
||||||
|
|
||||||
// check that the added message exists
|
// check that the added message exists
|
||||||
let msg = mdir.get_msg("INBOX", &hash).unwrap();
|
let msg = mdir.get_msg("inbox", &hash).unwrap();
|
||||||
assert_eq!("alice@localhost", msg.from.clone().unwrap().to_string());
|
assert_eq!("alice@localhost", msg.from.clone().unwrap().to_string());
|
||||||
assert_eq!("patrick@localhost", msg.to.clone().unwrap().to_string());
|
assert_eq!("patrick@localhost", msg.to.clone().unwrap().to_string());
|
||||||
assert_eq!("Ceci est un message.", msg.fold_text_plain_parts());
|
assert_eq!("Ceci est un message.", msg.fold_text_plain_parts());
|
||||||
|
|
||||||
// check that the envelope of the added message exists
|
// check that the envelope of the added message exists
|
||||||
let envelopes = mdir.get_envelopes("INBOX", 10, 0).unwrap();
|
let envelopes = mdir.get_envelopes("inbox", 10, 0).unwrap();
|
||||||
let envelopes: &MaildirEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
let envelopes: &MaildirEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
||||||
let envelope = envelopes.first().unwrap();
|
let envelope = envelopes.first().unwrap();
|
||||||
assert_eq!(1, envelopes.len());
|
assert_eq!(1, envelopes.len());
|
||||||
|
@ -50,9 +53,9 @@ fn test_maildir_backend() {
|
||||||
assert_eq!("Plain message", envelope.subject);
|
assert_eq!("Plain message", envelope.subject);
|
||||||
|
|
||||||
// check that a flag can be added to the message
|
// check that a flag can be added to the message
|
||||||
mdir.add_flags("INBOX", &envelope.hash, "flagged passed")
|
mdir.add_flags("inbox", &envelope.hash, "flagged passed")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let envelopes = mdir.get_envelopes("INBOX", 1, 0).unwrap();
|
let envelopes = mdir.get_envelopes("inbox", 1, 0).unwrap();
|
||||||
let envelopes: &MaildirEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
let envelopes: &MaildirEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
||||||
let envelope = envelopes.first().unwrap();
|
let envelope = envelopes.first().unwrap();
|
||||||
assert!(envelope.flags.contains(&MaildirFlag::Seen));
|
assert!(envelope.flags.contains(&MaildirFlag::Seen));
|
||||||
|
@ -60,8 +63,8 @@ fn test_maildir_backend() {
|
||||||
assert!(envelope.flags.contains(&MaildirFlag::Passed));
|
assert!(envelope.flags.contains(&MaildirFlag::Passed));
|
||||||
|
|
||||||
// check that the message flags can be changed
|
// check that the message flags can be changed
|
||||||
mdir.set_flags("INBOX", &envelope.hash, "passed").unwrap();
|
mdir.set_flags("inbox", &envelope.hash, "passed").unwrap();
|
||||||
let envelopes = mdir.get_envelopes("INBOX", 1, 0).unwrap();
|
let envelopes = mdir.get_envelopes("inbox", 1, 0).unwrap();
|
||||||
let envelopes: &MaildirEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
let envelopes: &MaildirEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
||||||
let envelope = envelopes.first().unwrap();
|
let envelope = envelopes.first().unwrap();
|
||||||
assert!(!envelope.flags.contains(&MaildirFlag::Seen));
|
assert!(!envelope.flags.contains(&MaildirFlag::Seen));
|
||||||
|
@ -69,8 +72,8 @@ fn test_maildir_backend() {
|
||||||
assert!(envelope.flags.contains(&MaildirFlag::Passed));
|
assert!(envelope.flags.contains(&MaildirFlag::Passed));
|
||||||
|
|
||||||
// check that a flag can be removed from the message
|
// check that a flag can be removed from the message
|
||||||
mdir.del_flags("INBOX", &envelope.hash, "passed").unwrap();
|
mdir.del_flags("inbox", &envelope.hash, "passed").unwrap();
|
||||||
let envelopes = mdir.get_envelopes("INBOX", 1, 0).unwrap();
|
let envelopes = mdir.get_envelopes("inbox", 1, 0).unwrap();
|
||||||
let envelopes: &MaildirEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
let envelopes: &MaildirEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
||||||
let envelope = envelopes.first().unwrap();
|
let envelope = envelopes.first().unwrap();
|
||||||
assert!(!envelope.flags.contains(&MaildirFlag::Seen));
|
assert!(!envelope.flags.contains(&MaildirFlag::Seen));
|
||||||
|
@ -78,19 +81,19 @@ fn test_maildir_backend() {
|
||||||
assert!(!envelope.flags.contains(&MaildirFlag::Passed));
|
assert!(!envelope.flags.contains(&MaildirFlag::Passed));
|
||||||
|
|
||||||
// check that the message can be copied
|
// check that the message can be copied
|
||||||
mdir.copy_msg("INBOX", "Subdir", &envelope.hash).unwrap();
|
mdir.copy_msg("inbox", "subdir", &envelope.hash).unwrap();
|
||||||
assert!(mdir.get_msg("INBOX", &hash).is_ok());
|
assert!(mdir.get_msg("inbox", &hash).is_ok());
|
||||||
assert!(mdir.get_msg("Subdir", &hash).is_ok());
|
assert!(mdir.get_msg("subdir", &hash).is_ok());
|
||||||
assert!(mdir_subdir.get_msg("INBOX", &hash).is_ok());
|
assert!(mdir_subdir.get_msg("inbox", &hash).is_ok());
|
||||||
|
|
||||||
// check that the message can be moved
|
// check that the message can be moved
|
||||||
mdir.move_msg("INBOX", "Subdir", &envelope.hash).unwrap();
|
mdir.move_msg("inbox", "subdir", &envelope.hash).unwrap();
|
||||||
assert!(mdir.get_msg("INBOX", &hash).is_err());
|
assert!(mdir.get_msg("inbox", &hash).is_err());
|
||||||
assert!(mdir.get_msg("Subdir", &hash).is_ok());
|
assert!(mdir.get_msg("subdir", &hash).is_ok());
|
||||||
assert!(mdir_subdir.get_msg("INBOX", &hash).is_ok());
|
assert!(mdir_subdir.get_msg("inbox", &hash).is_ok());
|
||||||
|
|
||||||
// check that the message can be deleted
|
// check that the message can be deleted
|
||||||
mdir.del_msg("Subdir", &hash).unwrap();
|
mdir.del_msg("subdir", &hash).unwrap();
|
||||||
assert!(mdir.get_msg("Subdir", &hash).is_err());
|
assert!(mdir.get_msg("subdir", &hash).is_err());
|
||||||
assert!(mdir_subdir.get_msg("INBOX", &hash).is_err());
|
assert!(mdir_subdir.get_msg("inbox", &hash).is_err());
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ fn test_notmuch_backend() {
|
||||||
notmuch
|
notmuch
|
||||||
.add_flags("", &envelope.hash, "flagged passed")
|
.add_flags("", &envelope.hash, "flagged passed")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let envelopes = notmuch.get_envelopes("inbox", 1, 0).unwrap();
|
let envelopes = notmuch.get_envelopes("inbox", 10, 0).unwrap();
|
||||||
let envelopes: &NotmuchEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
let envelopes: &NotmuchEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
||||||
let envelope = envelopes.first().unwrap();
|
let envelope = envelopes.first().unwrap();
|
||||||
assert!(envelope.flags.contains(&"inbox".into()));
|
assert!(envelope.flags.contains(&"inbox".into()));
|
||||||
|
@ -61,7 +61,7 @@ fn test_notmuch_backend() {
|
||||||
notmuch
|
notmuch
|
||||||
.set_flags("", &envelope.hash, "inbox passed")
|
.set_flags("", &envelope.hash, "inbox passed")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let envelopes = notmuch.get_envelopes("inbox", 1, 0).unwrap();
|
let envelopes = notmuch.get_envelopes("inbox", 10, 0).unwrap();
|
||||||
let envelopes: &NotmuchEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
let envelopes: &NotmuchEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
||||||
let envelope = envelopes.first().unwrap();
|
let envelope = envelopes.first().unwrap();
|
||||||
assert!(envelope.flags.contains(&"inbox".into()));
|
assert!(envelope.flags.contains(&"inbox".into()));
|
||||||
|
@ -71,11 +71,15 @@ fn test_notmuch_backend() {
|
||||||
|
|
||||||
// check that a flag can be removed from the message
|
// check that a flag can be removed from the message
|
||||||
notmuch.del_flags("", &envelope.hash, "passed").unwrap();
|
notmuch.del_flags("", &envelope.hash, "passed").unwrap();
|
||||||
let envelopes = notmuch.get_envelopes("inbox", 1, 0).unwrap();
|
let envelopes = notmuch.get_envelopes("inbox", 10, 0).unwrap();
|
||||||
let envelopes: &NotmuchEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
let envelopes: &NotmuchEnvelopes = envelopes.as_any().downcast_ref().unwrap();
|
||||||
let envelope = envelopes.first().unwrap();
|
let envelope = envelopes.first().unwrap();
|
||||||
assert!(envelope.flags.contains(&"inbox".into()));
|
assert!(envelope.flags.contains(&"inbox".into()));
|
||||||
assert!(!envelope.flags.contains(&"seen".into()));
|
assert!(!envelope.flags.contains(&"seen".into()));
|
||||||
assert!(!envelope.flags.contains(&"flagged".into()));
|
assert!(!envelope.flags.contains(&"flagged".into()));
|
||||||
assert!(!envelope.flags.contains(&"passed".into()));
|
assert!(!envelope.flags.contains(&"passed".into()));
|
||||||
|
|
||||||
|
// check that the message can be deleted
|
||||||
|
notmuch.del_msg("", &hash).unwrap();
|
||||||
|
assert!(notmuch.get_msg("inbox", &hash).is_err());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue