pub mod config;
use async_trait::async_trait;
use log::info;
use maildirpp::Maildir;
use notmuch::{Database, DatabaseMode};
use shellexpand_utils::shellexpand_path;
use std::{ops::Deref, sync::Arc};
use thiserror::Error;
use tokio::sync::Mutex;
#[cfg(feature = "envelope-get")]
use crate::envelope::get::{notmuch::GetNotmuchEnvelope, GetEnvelope};
#[cfg(feature = "envelope-list")]
use crate::envelope::list::{notmuch::ListNotmuchEnvelopes, ListEnvelopes};
#[cfg(feature = "flag-add")]
use crate::flag::add::{notmuch::AddNotmuchFlags, AddFlags};
#[cfg(feature = "flag-remove")]
use crate::flag::remove::{notmuch::RemoveNotmuchFlags, RemoveFlags};
#[cfg(feature = "flag-set")]
use crate::flag::set::{notmuch::SetNotmuchFlags, SetFlags};
#[cfg(feature = "folder-add")]
use crate::folder::add::{notmuch::AddNotmuchFolder, AddFolder};
#[cfg(feature = "folder-list")]
use crate::folder::list::{notmuch::ListNotmuchFolders, ListFolders};
#[cfg(feature = "message-add")]
use crate::message::add::{notmuch::AddNotmuchMessage, AddMessage};
#[cfg(feature = "message-copy")]
use crate::message::copy::{notmuch::CopyNotmuchMessages, CopyMessages};
#[cfg(feature = "message-delete")]
use crate::message::delete::{notmuch::DeleteNotmuchMessages, DeleteMessages};
#[cfg(feature = "message-get")]
use crate::message::get::{notmuch::GetNotmuchMessages, GetMessages};
#[cfg(feature = "message-peek")]
use crate::message::peek::{notmuch::PeekNotmuchMessages, PeekMessages};
#[cfg(feature = "message-move")]
use crate::message::r#move::{notmuch::MoveNotmuchMessages, MoveMessages};
use crate::{
account::config::AccountConfig,
backend::{BackendContext, BackendContextBuilder, BackendFeatureBuilder},
maildir::{config::MaildirConfig, MaildirContext},
Result,
};
use self::config::NotmuchConfig;
#[derive(Debug, Error)]
pub enum Error {
#[error("cannot open notmuch database")]
OpenDatabaseError(#[source] notmuch::Error),
}
pub struct NotmuchContext {
pub account_config: Arc<AccountConfig>,
pub notmuch_config: Arc<NotmuchConfig>,
pub mdir_ctx: MaildirContext,
}
impl NotmuchContext {
pub fn open_db(&self) -> Result<Database> {
let db_path = self
.notmuch_config
.database_path
.as_ref()
.map(shellexpand_path);
let db_mode = DatabaseMode::ReadWrite;
let config_path = self.notmuch_config.find_config_path();
let profile = self.notmuch_config.find_profile();
let db = Database::open_with_config(db_path, db_mode, config_path, profile)
.map_err(Error::OpenDatabaseError)?;
Ok(db)
}
}
#[derive(Clone)]
pub struct NotmuchContextSync {
pub account_config: Arc<AccountConfig>,
pub notmuch_config: Arc<NotmuchConfig>,
inner: Arc<Mutex<NotmuchContext>>,
}
impl Deref for NotmuchContextSync {
type Target = Arc<Mutex<NotmuchContext>>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl BackendContext for NotmuchContextSync {}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct NotmuchContextBuilder {
pub notmuch_config: Arc<NotmuchConfig>,
}
impl NotmuchContextBuilder {
pub fn new(notmuch_config: Arc<NotmuchConfig>) -> Self {
Self { notmuch_config }
}
}
#[async_trait]
impl BackendContextBuilder for NotmuchContextBuilder {
type Context = NotmuchContextSync;
#[cfg(feature = "folder-add")]
fn add_folder(&self) -> BackendFeatureBuilder<Self::Context, dyn AddFolder> {
Some(Arc::new(AddNotmuchFolder::some_new_boxed))
}
#[cfg(feature = "folder-list")]
fn list_folders(&self) -> BackendFeatureBuilder<Self::Context, dyn ListFolders> {
Some(Arc::new(ListNotmuchFolders::some_new_boxed))
}
#[cfg(feature = "envelope-list")]
fn list_envelopes(&self) -> BackendFeatureBuilder<Self::Context, dyn ListEnvelopes> {
Some(Arc::new(ListNotmuchEnvelopes::some_new_boxed))
}
#[cfg(feature = "envelope-get")]
fn get_envelope(&self) -> BackendFeatureBuilder<Self::Context, dyn GetEnvelope> {
Some(Arc::new(GetNotmuchEnvelope::some_new_boxed))
}
#[cfg(feature = "flag-add")]
fn add_flags(&self) -> BackendFeatureBuilder<Self::Context, dyn AddFlags> {
Some(Arc::new(AddNotmuchFlags::some_new_boxed))
}
#[cfg(feature = "flag-set")]
fn set_flags(&self) -> BackendFeatureBuilder<Self::Context, dyn SetFlags> {
Some(Arc::new(SetNotmuchFlags::some_new_boxed))
}
#[cfg(feature = "flag-remove")]
fn remove_flags(&self) -> BackendFeatureBuilder<Self::Context, dyn RemoveFlags> {
Some(Arc::new(RemoveNotmuchFlags::some_new_boxed))
}
#[cfg(feature = "message-add")]
fn add_message(&self) -> BackendFeatureBuilder<Self::Context, dyn AddMessage> {
Some(Arc::new(AddNotmuchMessage::some_new_boxed))
}
#[cfg(feature = "message-peek")]
fn peek_messages(&self) -> BackendFeatureBuilder<Self::Context, dyn PeekMessages> {
Some(Arc::new(PeekNotmuchMessages::some_new_boxed))
}
#[cfg(feature = "message-get")]
fn get_messages(&self) -> BackendFeatureBuilder<Self::Context, dyn GetMessages> {
Some(Arc::new(GetNotmuchMessages::some_new_boxed))
}
#[cfg(feature = "message-copy")]
fn copy_messages(&self) -> BackendFeatureBuilder<Self::Context, dyn CopyMessages> {
Some(Arc::new(CopyNotmuchMessages::some_new_boxed))
}
#[cfg(feature = "message-move")]
fn move_messages(&self) -> BackendFeatureBuilder<Self::Context, dyn MoveMessages> {
Some(Arc::new(MoveNotmuchMessages::some_new_boxed))
}
#[cfg(feature = "message-delete")]
fn delete_messages(&self) -> BackendFeatureBuilder<Self::Context, dyn DeleteMessages> {
Some(Arc::new(DeleteNotmuchMessages::some_new_boxed))
}
async fn build(self, account_config: Arc<AccountConfig>) -> Result<Self::Context> {
info!("building new notmuch context");
let root = Maildir::from(self.notmuch_config.get_maildir_path()?);
let maildir_config = Arc::new(MaildirConfig {
root_dir: root.path().to_owned(),
});
let mdir_ctx = MaildirContext {
account_config: account_config.clone(),
maildir_config,
root,
};
let ctx = NotmuchContext {
account_config: account_config.clone(),
notmuch_config: self.notmuch_config.clone(),
mdir_ctx,
};
Ok(NotmuchContextSync {
account_config,
notmuch_config: self.notmuch_config,
inner: Arc::new(Mutex::new(ctx)),
})
}
}