152 lines
5.3 KiB
Rust
152 lines
5.3 KiB
Rust
|
//
|
||
|
// imag - the personal information management suite for the commandline
|
||
|
// Copyright (C) 2015-2019 Matthias Beyer <mail@beyermatthias.de> and contributors
|
||
|
//
|
||
|
// This library is free software; you can redistribute it and/or
|
||
|
// modify it under the terms of the GNU Lesser General Public
|
||
|
// License as published by the Free Software Foundation; version
|
||
|
// 2.1 of the License.
|
||
|
//
|
||
|
// This library is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
// Lesser General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Lesser General Public
|
||
|
// License along with this library; if not, write to the Free Software
|
||
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
//
|
||
|
|
||
|
use std::path::Path;
|
||
|
use std::path::PathBuf;
|
||
|
use std::fmt::Debug;
|
||
|
|
||
|
use failure::Fallible as Result;
|
||
|
use toml::Value;
|
||
|
use toml_query::insert::TomlValueInsertExt;
|
||
|
|
||
|
use libimagstore::store::FileLockEntry;
|
||
|
use libimagstore::store::Store;
|
||
|
use libimagstore::storeid::IntoStoreId;
|
||
|
use libimagstore::storeid::StoreId;
|
||
|
use libimagstore::iter::Entries;
|
||
|
use libimagentryref::hasher::default::DefaultHasher;
|
||
|
use libimagentryref::reference::Config;
|
||
|
use libimagentryref::reference::RefFassade;
|
||
|
use libimagentryref::reference::Ref;
|
||
|
use libimagentryref::reference::MutRef;
|
||
|
|
||
|
use module_path::ModuleEntryPath;
|
||
|
use mid::MessageId;
|
||
|
use mail::Mail;
|
||
|
use hasher::MailHasher;
|
||
|
use util::get_message_id_for_mailfile;
|
||
|
|
||
|
pub trait MailStore<'a> {
|
||
|
fn create_mail_from_path<P, CollName>(&'a self, p: P, collection_name: CollName, config: &Config)
|
||
|
-> Result<FileLockEntry<'a>>
|
||
|
where P: AsRef<Path> + Debug,
|
||
|
CollName: AsRef<str> + Debug;
|
||
|
|
||
|
fn get_mail_from_path<P>(&'a self, p: P)
|
||
|
-> Result<Option<FileLockEntry<'a>>>
|
||
|
where P: AsRef<Path> + Debug;
|
||
|
|
||
|
fn retrieve_mail_from_path<P, CollName>(&'a self, p: P, collection_name: CollName, config: &Config)
|
||
|
-> Result<FileLockEntry<'a>>
|
||
|
where P: AsRef<Path> + Debug,
|
||
|
CollName: AsRef<str> + Debug;
|
||
|
|
||
|
fn get_mail(&'a self, mid: MessageId) -> Result<Option<FileLockEntry<'a>>>;
|
||
|
fn all_mails(&'a self) -> Result<Entries<'a>>;
|
||
|
}
|
||
|
|
||
|
impl<'a> MailStore<'a> for Store {
|
||
|
|
||
|
fn create_mail_from_path<P, CollName>(&'a self, p: P, collection_name: CollName, config: &Config)
|
||
|
-> Result<FileLockEntry<'a>>
|
||
|
where P: AsRef<Path> + Debug,
|
||
|
CollName: AsRef<str> + Debug
|
||
|
{
|
||
|
let message_id = get_message_id_for_mailfile(p.as_ref())?;
|
||
|
let new_sid = ModuleEntryPath::new(message_id.clone()).into_storeid()?;
|
||
|
|
||
|
let mut entry = self.create(new_sid)?;
|
||
|
let _ = entry
|
||
|
.as_ref_with_hasher_mut::<MailHasher>()
|
||
|
.make_ref(p, collection_name, config, false)?;
|
||
|
|
||
|
let _ = entry
|
||
|
.get_header_mut()
|
||
|
.insert("mail.message-id", Value::String(message_id))?;
|
||
|
|
||
|
Ok(entry)
|
||
|
}
|
||
|
|
||
|
/// Same as MailStore::retrieve_mail_from_path() but uses Store::get() instead of
|
||
|
/// Store::retrieve()
|
||
|
fn get_mail_from_path<P>(&'a self, p: P)
|
||
|
-> Result<Option<FileLockEntry<'a>>>
|
||
|
where P: AsRef<Path> + Debug
|
||
|
{
|
||
|
let message_id = get_message_id_for_mailfile(p.as_ref())?;
|
||
|
let new_sid = ModuleEntryPath::new(message_id.clone()).into_storeid()?;
|
||
|
|
||
|
match self.get(new_sid)? {
|
||
|
Some(mut entry) => {
|
||
|
if !entry.is_ref()? {
|
||
|
return Err(format_err!("{} is not a ref", entry.get_location()))
|
||
|
}
|
||
|
|
||
|
if p.as_ref().ends_with(entry.as_ref_with_hasher::<MailHasher>().get_relative_path()?) {
|
||
|
return Err(format_err!("{} is not a ref to {:?}",
|
||
|
entry.get_location(),
|
||
|
p.as_ref().display()))
|
||
|
}
|
||
|
|
||
|
let _ = entry.get_header_mut().insert("mail.message-id", Value::String(message_id))?;
|
||
|
Ok(Some(entry))
|
||
|
},
|
||
|
None => Ok(None),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn retrieve_mail_from_path<P, CollName>(&'a self, p: P, collection_name: CollName, config: &Config)
|
||
|
-> Result<FileLockEntry<'a>>
|
||
|
where P: AsRef<Path> + Debug,
|
||
|
CollName: AsRef<str> + Debug
|
||
|
{
|
||
|
let message_id = get_message_id_for_mailfile(&p)?;
|
||
|
let new_sid = ModuleEntryPath::new(message_id.clone()).into_storeid()?;
|
||
|
let mut entry = self.retrieve(new_sid)?;
|
||
|
|
||
|
let _ = entry
|
||
|
.get_header_mut()
|
||
|
.insert("mail.message-id", Value::String(message_id))?;
|
||
|
|
||
|
let _ = entry
|
||
|
.as_ref_with_hasher_mut::<DefaultHasher>()
|
||
|
.make_ref(p, collection_name, config, false)?;
|
||
|
|
||
|
Ok(entry)
|
||
|
}
|
||
|
|
||
|
fn get_mail(&'a self, mid: MessageId) -> Result<Option<FileLockEntry<'a>>> {
|
||
|
let mid_s : String = mid.into();
|
||
|
self.get(StoreId::new(PathBuf::from(mid_s))?)
|
||
|
.and_then(|oe| match oe {
|
||
|
Some(e) => if e.is_mail()? {
|
||
|
Ok(Some(e))
|
||
|
} else {
|
||
|
Err(format_err!("{} is not a mail entry", e.get_location()))
|
||
|
},
|
||
|
None => Ok(None)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
fn all_mails(&'a self) -> Result<Entries<'a>> {
|
||
|
self.entries().map(|ent| ent.in_collection("mail"))
|
||
|
}
|
||
|
}
|
||
|
|