@ -84,6 +84,7 @@ struct MboxMailbox {
hash : MailboxHash ,
name : String ,
path : PathBuf ,
fs_path : PathBuf ,
content : Vec < u8 > ,
children : Vec < MailboxHash > ,
parent : Option < MailboxHash > ,
@ -92,6 +93,7 @@ struct MboxMailbox {
permissions : MailboxPermissions ,
pub total : Arc < Mutex < usize > > ,
pub unseen : Arc < Mutex < usize > > ,
index : Arc < Mutex < HashMap < EnvelopeHash , ( Offset , Length ) > > > ,
}
impl BackendMailbox for MboxMailbox {
@ -117,6 +119,7 @@ impl BackendMailbox for MboxMailbox {
hash : self . hash ,
name : self . name . clone ( ) ,
path : self . path . clone ( ) ,
fs_path : self . fs_path . clone ( ) ,
content : self . content . clone ( ) ,
children : self . children . clone ( ) ,
usage : self . usage . clone ( ) ,
@ -125,6 +128,7 @@ impl BackendMailbox for MboxMailbox {
permissions : self . permissions ,
unseen : self . unseen . clone ( ) ,
total : self . total . clone ( ) ,
index : self . index . clone ( ) ,
} )
}
@ -659,7 +663,7 @@ pub fn mbox_parse(
pub struct MboxType {
account_name : String ,
path : PathBuf ,
index: Arc < Mutex < HashMap < EnvelopeHash , ( Offset , Length ) > > > ,
mailbox_ index: Arc < Mutex < HashMap < EnvelopeHash , MailboxHash > > > ,
mailboxes : Arc < Mutex < HashMap < MailboxHash , MboxMailbox > > > ,
prefer_mbox_type : Option < MboxReader > ,
}
@ -673,14 +677,13 @@ impl MailBackend for MboxType {
let mut w = AsyncBuilder ::new ( ) ;
let handle = {
let tx = w . tx ( ) ;
let index = self . index . clone ( ) ;
let mailbox_path = mailbox . path ( ) . to_string ( ) ;
let mailbox_hash = mailbox . hash ( ) ;
let mailbox_index = self . mailbox_index . clone ( ) ;
let mailboxes = self . mailboxes . clone ( ) ;
let mailbox_path = mailboxes . lock ( ) . unwrap ( ) [ & mailbox_hash ] . fs_path . clone ( ) ;
let prefer_mbox_type = self . prefer_mbox_type . clone ( ) ;
let closure = move | _work_context | {
let tx = tx . clone ( ) ;
let index = index . clone ( ) ;
let file = match std ::fs ::OpenOptions ::new ( )
. read ( true )
. write ( true )
@ -702,9 +705,18 @@ impl MailBackend for MboxType {
return ;
} ;
let mailboxes_lck = mailboxes . lock ( ) . unwrap ( ) ;
let mut mailbox_index_lck = mailbox_index . lock ( ) . unwrap ( ) ;
let index = mailboxes_lck [ & mailbox_hash ] . index . clone ( ) ;
drop ( mailboxes_lck ) ;
let payload = mbox_parse ( index , contents . as_slice ( ) , 0 , prefer_mbox_type )
. map_err ( | e | MeliError ::from ( e ) )
. map ( | ( _ , v ) | v ) ;
. map ( | ( _ , v ) | {
for v in v . iter ( ) {
mailbox_index_lck . insert ( v . hash ( ) , mailbox_hash ) ;
}
v
} ) ;
{
let mut mailbox_lock = mailboxes . lock ( ) . unwrap ( ) ;
mailbox_lock
@ -731,17 +743,16 @@ impl MailBackend for MboxType {
. map_err ( MeliError ::new ) ? ;
for f in self . mailboxes . lock ( ) . unwrap ( ) . values ( ) {
watcher
. watch ( & f . path, RecursiveMode ::Recursive )
. watch ( & f . fs_ path, RecursiveMode ::Recursive )
. map_err ( | e | e . to_string ( ) )
. map_err ( MeliError ::new ) ? ;
debug ! ( "watching {:?}" , f . path. as_path ( ) ) ;
debug ! ( "watching {:?}" , f . fs_ path. as_path ( ) ) ;
}
let account_hash = {
let mut hasher = DefaultHasher ::new ( ) ;
hasher . write ( self . account_name . as_bytes ( ) ) ;
hasher . finish ( )
} ;
let index = self . index . clone ( ) ;
let mailboxes = self . mailboxes . clone ( ) ;
let prefer_mbox_type = self . prefer_mbox_type . clone ( ) ;
let handle = std ::thread ::Builder ::new ( )
@ -750,7 +761,6 @@ impl MailBackend for MboxType {
// Move `watcher` in the closure's scope so that it doesn't get dropped.
let _watcher = watcher ;
let _work_context = work_context ;
let index = index ;
let mailboxes = mailboxes ;
loop {
match rx . recv ( ) {
@ -791,7 +801,7 @@ impl MailBackend for MboxType {
. starts_with ( mailbox_lock [ & mailbox_hash ] . content . as_slice ( ) )
{
if let Ok ( ( _ , envelopes ) ) = mbox_parse (
index. clone ( ) ,
mailbox_lock[ & mailbox_hash ] . index. clone ( ) ,
& contents [ mailbox_lock [ & mailbox_hash ] . content . len ( ) .. ] ,
mailbox_lock [ & mailbox_hash ] . content . len ( ) ,
prefer_mbox_type ,
@ -822,7 +832,7 @@ impl MailBackend for MboxType {
. lock ( )
. unwrap ( )
. values ( )
. any ( | f | & f . path = = & pathbuf )
. any ( | f | & f . fs_ path = = & pathbuf )
{
let mailbox_hash = get_path_hash ! ( & pathbuf ) ;
sender . send ( RefreshEvent {
@ -837,7 +847,12 @@ impl MailBackend for MboxType {
}
}
DebouncedEvent ::Rename ( src , dest ) = > {
if mailboxes . lock ( ) . unwrap ( ) . values ( ) . any ( | f | & f . path = = & src ) {
if mailboxes
. lock ( )
. unwrap ( )
. values ( )
. any ( | f | & f . fs_path = = & src )
{
let mailbox_hash = get_path_hash ! ( & src ) ;
sender . send ( RefreshEvent {
account_hash ,
@ -879,12 +894,20 @@ impl MailBackend for MboxType {
. map ( | ( h , f ) | ( * h , f . clone ( ) as Mailbox ) )
. collect ( ) )
}
fn operation ( & self , hash : EnvelopeHash ) -> Box < dyn BackendOp > {
fn operation ( & self , env_hash : EnvelopeHash ) -> Box < dyn BackendOp > {
let mailbox_hash = self . mailbox_index . lock ( ) . unwrap ( ) [ & env_hash ] ;
let mailboxes_lck = self . mailboxes . lock ( ) . unwrap ( ) ;
let ( offset , length ) = {
let index = self . index . lock ( ) . unwrap ( ) ;
index [ & hash]
let index = mailboxes_lck [ & mailbox_hash ] . index . lock ( ) . unwrap ( ) ;
index [ & env_ hash]
} ;
Box ::new ( MboxOp ::new ( hash , self . path . as_path ( ) , offset , length ) )
let mailbox_path = mailboxes_lck [ & mailbox_hash ] . fs_path . clone ( ) ;
Box ::new ( MboxOp ::new (
env_hash ,
mailbox_path . as_path ( ) ,
offset ,
length ,
) )
}
fn save ( & self , _bytes : & [ u8 ] , _mailbox_hash : MailboxHash , _flags : Option < Flag > ) -> Result < ( ) > {
@ -974,7 +997,8 @@ impl MboxType {
hash ,
MboxMailbox {
hash ,
path : ret . path . clone ( ) ,
path : name . clone ( ) . into ( ) ,
fs_path : ret . path . clone ( ) ,
name ,
content : Vec ::new ( ) ,
children : Vec ::new ( ) ,
@ -993,39 +1017,60 @@ impl MboxType {
} ,
unseen : Arc ::new ( Mutex ::new ( 0 ) ) ,
total : Arc ::new ( Mutex ::new ( 0 ) ) ,
index : Default ::default ( ) ,
} ,
) ;
/*
/* Look for other mailboxes */
let parent_mailbox = Path ::new ( path ) . parent ( ) . unwrap ( ) ;
let read_dir = std ::fs ::read_dir ( parent_mailbox ) ;
if read_dir . is_ok ( ) {
for f in read_dir . unwrap ( ) {
if f . is_err ( ) {
continue ;
for ( k , f ) in s . mailboxes . iter ( ) {
if let Some ( path_str ) = f . extra . get ( "path" ) {
let hash = get_path_hash ! ( path_str ) ;
let pathbuf : PathBuf = path_str . into ( ) ;
if ! pathbuf . exists ( ) | | pathbuf . is_dir ( ) {
return Err ( MeliError ::new ( format! (
"mbox mailbox configuration entry \"{}\" path value {} is not a file." ,
k , path_str
) ) ) ;
}
let f = f . unwrap ( ) . path ( ) ;
if f . is_file ( ) & & f ! = path {
let name : String = f
. file_name ( )
. map ( | f | f . to_string_lossy ( ) . into ( ) )
. unwrap_or ( String ::new ( ) ) ;
let hash = get_path_hash ! ( f ) ;
ret . mailboxes . lock ( ) . unwrap ( ) . insert (
let read_only = if let Ok ( metadata ) = std ::fs ::metadata ( & pathbuf ) {
metadata . permissions ( ) . readonly ( )
} else {
true
} ;
ret . mailboxes . lock ( ) . unwrap ( ) . insert (
hash ,
MboxMailbox {
hash ,
MboxMailbox {
hash ,
path : f ,
name ,
content : Vec ::new ( ) ,
children : Vec ::new ( ) ,
parent : None ,
name : k . to_string ( ) ,
fs_path : pathbuf ,
path : k . into ( ) ,
content : Vec ::new ( ) ,
children : Vec ::new ( ) ,
parent : None ,
usage : Arc ::new ( RwLock ::new ( f . usage . unwrap_or_default ( ) ) ) ,
is_subscribed : f . subscribe . is_true ( ) ,
permissions : MailboxPermissions {
create_messages : ! read_only ,
remove_messages : ! read_only ,
set_flags : ! read_only ,
create_child : ! read_only ,
rename_messages : ! read_only ,
delete_messages : ! read_only ,
delete_mailbox : ! read_only ,
change_permissions : false ,
} ,
) ;
}
unseen : Arc ::new ( Mutex ::new ( 0 ) ) ,
total : Arc ::new ( Mutex ::new ( 0 ) ) ,
index : Default ::default ( ) ,
} ,
) ;
} else {
return Err ( MeliError ::new ( format! (
"mbox mailbox configuration entry \"{}\" should have a \"path\" value set pointing to an mbox file." ,
k
) ) ) ;
}
}
* /
Ok ( Box ::new ( ret ) )
}