Fix unreachable-pub and disjoint-capture lint errors
Tests / Test on ${{ matrix.build }} (linux-amd64, ubuntu-latest, stable, x86_64-unknown-linux-gnu) (push) Failing after 6m8s
Details
Tests / Test on ${{ matrix.build }} (linux-amd64, ubuntu-latest, stable, x86_64-unknown-linux-gnu) (push) Failing after 6m8s
Details
parent
1d0405ed5b
commit
8e698cabcf
|
@ -29,7 +29,7 @@ use quote::{format_ident, quote};
|
|||
use regex::Regex;
|
||||
|
||||
// Write ConfigStructOverride to overrides.rs
|
||||
pub fn override_derive(filenames: &[(&str, &str)]) {
|
||||
pub(crate) fn override_derive(filenames: &[(&str, &str)]) {
|
||||
let mut output_file =
|
||||
File::create("src/conf/overrides.rs").expect("Unable to open output file");
|
||||
let mut output_string = r##"// @generated
|
||||
|
|
|
@ -40,7 +40,7 @@ use super::*;
|
|||
use crate::{conf::accounts::JobRequest, jobs::JoinHandle, terminal::embed::EmbedTerminal};
|
||||
|
||||
#[cfg(feature = "gpgme")]
|
||||
mod gpg;
|
||||
pub mod gpg;
|
||||
|
||||
pub mod edit_attachments;
|
||||
use edit_attachments::*;
|
||||
|
|
|
@ -444,8 +444,327 @@ pub trait MailListingTrait: ListingTrait {
|
|||
envs_to_set: SmallVec<[EnvelopeHash; 8]>,
|
||||
a: &ListingAction,
|
||||
) {
|
||||
fn inner(
|
||||
context: &mut Context,
|
||||
envs_to_set: SmallVec<[EnvelopeHash; 8]>,
|
||||
account_hash: AccountHash,
|
||||
mailbox_hash: MailboxHash,
|
||||
a: &ListingAction,
|
||||
) {
|
||||
let env_hashes = if let Ok(batch) = EnvelopeHashBatch::try_from(envs_to_set.as_slice())
|
||||
{
|
||||
batch
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
let account = &mut context.accounts[&account_hash];
|
||||
match a {
|
||||
ListingAction::SetSeen => {
|
||||
let job = account.backend.write().unwrap().set_flags(
|
||||
env_hashes.clone(),
|
||||
mailbox_hash,
|
||||
smallvec::smallvec![(Ok(Flag::SEEN), true)],
|
||||
);
|
||||
match job {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("set_seen".into(), fut);
|
||||
account.insert_job(
|
||||
handle.job_id,
|
||||
JobRequest::SetFlags { env_hashes, handle },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::SetUnseen => {
|
||||
let job = account.backend.write().unwrap().set_flags(
|
||||
env_hashes.clone(),
|
||||
mailbox_hash,
|
||||
smallvec::smallvec![(Ok(Flag::SEEN), false)],
|
||||
);
|
||||
match job {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("set_unseen".into(), fut);
|
||||
account.insert_job(
|
||||
handle.job_id,
|
||||
JobRequest::SetFlags { env_hashes, handle },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::Tag(Remove(ref tag_str)) => {
|
||||
let job = account.backend.write().unwrap().set_flags(
|
||||
env_hashes.clone(),
|
||||
mailbox_hash,
|
||||
smallvec::smallvec![(Err(tag_str.to_string()), false)],
|
||||
);
|
||||
match job {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("remove_tag".into(), fut);
|
||||
account.insert_job(
|
||||
handle.job_id,
|
||||
JobRequest::SetFlags { env_hashes, handle },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::Tag(Add(ref tag_str)) => {
|
||||
let job = account.backend.write().unwrap().set_flags(
|
||||
env_hashes.clone(),
|
||||
mailbox_hash,
|
||||
smallvec::smallvec![(Err(tag_str.to_string()), true)],
|
||||
);
|
||||
match job {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("add_tag".into(), fut);
|
||||
account.insert_job(
|
||||
handle.job_id,
|
||||
JobRequest::SetFlags { env_hashes, handle },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::Delete => {
|
||||
let job = account
|
||||
.backend
|
||||
.write()
|
||||
.unwrap()
|
||||
.delete_messages(env_hashes.clone(), mailbox_hash);
|
||||
match job {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("delete".into(), fut);
|
||||
account.insert_job(
|
||||
handle.job_id,
|
||||
JobRequest::DeleteMessages { env_hashes, handle },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::CopyTo(ref mailbox_path) => {
|
||||
match account.mailbox_by_path(mailbox_path).and_then(
|
||||
|destination_mailbox_hash| {
|
||||
account.backend.write().unwrap().copy_messages(
|
||||
env_hashes,
|
||||
mailbox_hash,
|
||||
destination_mailbox_hash,
|
||||
/* move? */ false,
|
||||
)
|
||||
},
|
||||
) {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("copy_to_mailbox".into(), fut);
|
||||
account.insert_job(
|
||||
handle.job_id,
|
||||
JobRequest::Generic {
|
||||
name: "message copying".into(),
|
||||
handle,
|
||||
on_finish: None,
|
||||
log_level: LogLevel::INFO,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::CopyToOtherAccount(ref _account_name, ref _mailbox_path) => {
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
|
||||
"Copying to another account is currently unimplemented".into(),
|
||||
)));
|
||||
}
|
||||
ListingAction::MoveTo(ref mailbox_path) => {
|
||||
match account.mailbox_by_path(mailbox_path).and_then(
|
||||
|destination_mailbox_hash| {
|
||||
account.backend.write().unwrap().copy_messages(
|
||||
env_hashes,
|
||||
mailbox_hash,
|
||||
destination_mailbox_hash,
|
||||
/* move? */ true,
|
||||
)
|
||||
},
|
||||
) {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("move_to_mailbox".into(), fut);
|
||||
account.insert_job(
|
||||
handle.job_id,
|
||||
JobRequest::Generic {
|
||||
name: "message moving".into(),
|
||||
handle,
|
||||
on_finish: None,
|
||||
log_level: LogLevel::INFO,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::ExportMbox(format, ref path) => {
|
||||
use std::{future::Future, io::Write, pin::Pin};
|
||||
|
||||
use futures::future::try_join_all;
|
||||
|
||||
let futures: Result<Vec<_>> = envs_to_set
|
||||
.iter()
|
||||
.map(|&env_hash| {
|
||||
account.operation(env_hash).and_then(|mut op| op.as_bytes())
|
||||
})
|
||||
.collect::<Result<Vec<_>>>();
|
||||
let path_ = path.to_path_buf();
|
||||
let format = (*format).unwrap_or_default();
|
||||
let collection = account.collection.clone();
|
||||
let (sender, mut receiver) = crate::jobs::oneshot::channel();
|
||||
let fut: Pin<Box<dyn Future<Output = Result<()>> + Send + 'static>> =
|
||||
Box::pin(async move {
|
||||
let cl = async move {
|
||||
use melib::backends::mbox::MboxMetadata;
|
||||
let bytes: Vec<Vec<u8>> = try_join_all(futures?).await?;
|
||||
let envs: Vec<_> = envs_to_set
|
||||
.iter()
|
||||
.map(|&env_hash| collection.get_env(env_hash))
|
||||
.collect();
|
||||
let mut file =
|
||||
std::io::BufWriter::new(std::fs::File::create(&path_)?);
|
||||
let mut iter = envs.iter().zip(bytes.into_iter());
|
||||
let tags_lck = collection.tag_index.read().unwrap();
|
||||
if let Some((env, ref bytes)) = iter.next() {
|
||||
let tags: Vec<&str> = env
|
||||
.tags()
|
||||
.iter()
|
||||
.filter_map(|h| tags_lck.get(h).map(|s| s.as_str()))
|
||||
.collect();
|
||||
format.append(
|
||||
&mut file,
|
||||
bytes.as_slice(),
|
||||
env.from().get(0),
|
||||
Some(env.date()),
|
||||
(env.flags(), tags),
|
||||
MboxMetadata::CClient,
|
||||
true,
|
||||
false,
|
||||
)?;
|
||||
}
|
||||
for (env, bytes) in iter {
|
||||
let tags: Vec<&str> = env
|
||||
.tags()
|
||||
.iter()
|
||||
.filter_map(|h| tags_lck.get(h).map(|s| s.as_str()))
|
||||
.collect();
|
||||
format.append(
|
||||
&mut file,
|
||||
bytes.as_slice(),
|
||||
env.from().get(0),
|
||||
Some(env.date()),
|
||||
(env.flags(), tags),
|
||||
MboxMetadata::CClient,
|
||||
false,
|
||||
false,
|
||||
)?;
|
||||
}
|
||||
file.flush()?;
|
||||
Ok(())
|
||||
};
|
||||
let r: Result<()> = cl.await;
|
||||
let _ = sender.send(r);
|
||||
Ok(())
|
||||
});
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_blocking("export_to_mbox".into(), fut);
|
||||
let path = path.to_path_buf();
|
||||
account.insert_job(
|
||||
handle.job_id,
|
||||
JobRequest::Generic {
|
||||
name: "exporting mbox".into(),
|
||||
handle,
|
||||
on_finish: Some(CallbackFn(Box::new(move |context: &mut Context| {
|
||||
context.replies.push_back(match receiver.try_recv() {
|
||||
Err(_) | Ok(None) => UIEvent::Notification(
|
||||
Some("Could not export mbox".to_string()),
|
||||
"Job was canceled.".to_string(),
|
||||
Some(NotificationType::Info),
|
||||
),
|
||||
Ok(Some(Err(err))) => UIEvent::Notification(
|
||||
Some("Could not export mbox".to_string()),
|
||||
err.to_string(),
|
||||
Some(NotificationType::Error(err.kind)),
|
||||
),
|
||||
Ok(Some(Ok(()))) => UIEvent::Notification(
|
||||
Some("Succesfully exported mbox".to_string()),
|
||||
format!("Wrote to file {}", path.display()),
|
||||
Some(NotificationType::Info),
|
||||
),
|
||||
});
|
||||
}))),
|
||||
log_level: LogLevel::INFO,
|
||||
},
|
||||
);
|
||||
}
|
||||
ListingAction::MoveToOtherAccount(ref _account_name, ref _mailbox_path) => {
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
|
||||
"Moving to another account is currently unimplemented".into(),
|
||||
)));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
let account_hash = self.coordinates().0;
|
||||
let account = &mut context.accounts[&account_hash];
|
||||
let mailbox_hash = self.coordinates().1;
|
||||
/*{
|
||||
let threads_lck = account.collection.get_threads(mailbox_hash);
|
||||
|
@ -457,305 +776,7 @@ pub trait MailListingTrait: ListingTrait {
|
|||
}
|
||||
}
|
||||
*/
|
||||
let env_hashes = if let Ok(batch) = EnvelopeHashBatch::try_from(envs_to_set.as_slice()) {
|
||||
batch
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
match a {
|
||||
ListingAction::SetSeen => {
|
||||
let job = account.backend.write().unwrap().set_flags(
|
||||
env_hashes.clone(),
|
||||
mailbox_hash,
|
||||
smallvec::smallvec![(Ok(Flag::SEEN), true)],
|
||||
);
|
||||
match job {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("set_seen".into(), fut);
|
||||
account
|
||||
.insert_job(handle.job_id, JobRequest::SetFlags { env_hashes, handle });
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::SetUnseen => {
|
||||
let job = account.backend.write().unwrap().set_flags(
|
||||
env_hashes.clone(),
|
||||
mailbox_hash,
|
||||
smallvec::smallvec![(Ok(Flag::SEEN), false)],
|
||||
);
|
||||
match job {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("set_unseen".into(), fut);
|
||||
account
|
||||
.insert_job(handle.job_id, JobRequest::SetFlags { env_hashes, handle });
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::Tag(Remove(ref tag_str)) => {
|
||||
let job = account.backend.write().unwrap().set_flags(
|
||||
env_hashes.clone(),
|
||||
mailbox_hash,
|
||||
smallvec::smallvec![(Err(tag_str.to_string()), false)],
|
||||
);
|
||||
match job {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("remove_tag".into(), fut);
|
||||
account
|
||||
.insert_job(handle.job_id, JobRequest::SetFlags { env_hashes, handle });
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::Tag(Add(ref tag_str)) => {
|
||||
let job = account.backend.write().unwrap().set_flags(
|
||||
env_hashes.clone(),
|
||||
mailbox_hash,
|
||||
smallvec::smallvec![(Err(tag_str.to_string()), true)],
|
||||
);
|
||||
match job {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("add_tag".into(), fut);
|
||||
account
|
||||
.insert_job(handle.job_id, JobRequest::SetFlags { env_hashes, handle });
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::Delete => {
|
||||
let job = account
|
||||
.backend
|
||||
.write()
|
||||
.unwrap()
|
||||
.delete_messages(env_hashes.clone(), mailbox_hash);
|
||||
match job {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("delete".into(), fut);
|
||||
account.insert_job(
|
||||
handle.job_id,
|
||||
JobRequest::DeleteMessages { env_hashes, handle },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::CopyTo(ref mailbox_path) => {
|
||||
match account
|
||||
.mailbox_by_path(mailbox_path)
|
||||
.and_then(|destination_mailbox_hash| {
|
||||
account.backend.write().unwrap().copy_messages(
|
||||
env_hashes,
|
||||
mailbox_hash,
|
||||
destination_mailbox_hash,
|
||||
/* move? */ false,
|
||||
)
|
||||
}) {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("copy_to_mailbox".into(), fut);
|
||||
account.insert_job(
|
||||
handle.job_id,
|
||||
JobRequest::Generic {
|
||||
name: "message copying".into(),
|
||||
handle,
|
||||
on_finish: None,
|
||||
log_level: LogLevel::INFO,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::CopyToOtherAccount(ref _account_name, ref _mailbox_path) => {
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
|
||||
"Copying to another account is currently unimplemented".into(),
|
||||
)));
|
||||
}
|
||||
ListingAction::MoveTo(ref mailbox_path) => {
|
||||
match account
|
||||
.mailbox_by_path(mailbox_path)
|
||||
.and_then(|destination_mailbox_hash| {
|
||||
account.backend.write().unwrap().copy_messages(
|
||||
env_hashes,
|
||||
mailbox_hash,
|
||||
destination_mailbox_hash,
|
||||
/* move? */ true,
|
||||
)
|
||||
}) {
|
||||
Err(err) => {
|
||||
context.replies.push_back(UIEvent::StatusEvent(
|
||||
StatusEvent::DisplayMessage(err.to_string()),
|
||||
));
|
||||
}
|
||||
Ok(fut) => {
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_specialized("move_to_mailbox".into(), fut);
|
||||
account.insert_job(
|
||||
handle.job_id,
|
||||
JobRequest::Generic {
|
||||
name: "message moving".into(),
|
||||
handle,
|
||||
on_finish: None,
|
||||
log_level: LogLevel::INFO,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
ListingAction::ExportMbox(format, ref path) => {
|
||||
use std::{future::Future, io::Write, pin::Pin};
|
||||
|
||||
use futures::future::try_join_all;
|
||||
|
||||
let futures: Result<Vec<_>> = envs_to_set
|
||||
.iter()
|
||||
.map(|&env_hash| account.operation(env_hash).and_then(|mut op| op.as_bytes()))
|
||||
.collect::<Result<Vec<_>>>();
|
||||
let path_ = path.to_path_buf();
|
||||
let format = (*format).unwrap_or_default();
|
||||
let collection = account.collection.clone();
|
||||
let (sender, mut receiver) = crate::jobs::oneshot::channel();
|
||||
let fut: Pin<Box<dyn Future<Output = Result<()>> + Send + 'static>> =
|
||||
Box::pin(async move {
|
||||
let cl = async move {
|
||||
use melib::backends::mbox::MboxMetadata;
|
||||
let bytes: Vec<Vec<u8>> = try_join_all(futures?).await?;
|
||||
let envs: Vec<_> = envs_to_set
|
||||
.iter()
|
||||
.map(|&env_hash| collection.get_env(env_hash))
|
||||
.collect();
|
||||
let mut file = std::io::BufWriter::new(std::fs::File::create(&path_)?);
|
||||
let mut iter = envs.iter().zip(bytes.into_iter());
|
||||
let tags_lck = collection.tag_index.read().unwrap();
|
||||
if let Some((env, ref bytes)) = iter.next() {
|
||||
let tags: Vec<&str> = env
|
||||
.tags()
|
||||
.iter()
|
||||
.filter_map(|h| tags_lck.get(h).map(|s| s.as_str()))
|
||||
.collect();
|
||||
format.append(
|
||||
&mut file,
|
||||
bytes.as_slice(),
|
||||
env.from().get(0),
|
||||
Some(env.date()),
|
||||
(env.flags(), tags),
|
||||
MboxMetadata::CClient,
|
||||
true,
|
||||
false,
|
||||
)?;
|
||||
}
|
||||
for (env, bytes) in iter {
|
||||
let tags: Vec<&str> = env
|
||||
.tags()
|
||||
.iter()
|
||||
.filter_map(|h| tags_lck.get(h).map(|s| s.as_str()))
|
||||
.collect();
|
||||
format.append(
|
||||
&mut file,
|
||||
bytes.as_slice(),
|
||||
env.from().get(0),
|
||||
Some(env.date()),
|
||||
(env.flags(), tags),
|
||||
MboxMetadata::CClient,
|
||||
false,
|
||||
false,
|
||||
)?;
|
||||
}
|
||||
file.flush()?;
|
||||
Ok(())
|
||||
};
|
||||
let r: Result<()> = cl.await;
|
||||
let _ = sender.send(r);
|
||||
Ok(())
|
||||
});
|
||||
let handle = account
|
||||
.main_loop_handler
|
||||
.job_executor
|
||||
.spawn_blocking("export_to_mbox".into(), fut);
|
||||
let path = path.to_path_buf();
|
||||
account.insert_job(
|
||||
handle.job_id,
|
||||
JobRequest::Generic {
|
||||
name: "exporting mbox".into(),
|
||||
handle,
|
||||
on_finish: Some(CallbackFn(Box::new(move |context: &mut Context| {
|
||||
context.replies.push_back(match receiver.try_recv() {
|
||||
Err(_) | Ok(None) => UIEvent::Notification(
|
||||
Some("Could not export mbox".to_string()),
|
||||
"Job was canceled.".to_string(),
|
||||
Some(NotificationType::Info),
|
||||
),
|
||||
Ok(Some(Err(err))) => UIEvent::Notification(
|
||||
Some("Could not export mbox".to_string()),
|
||||
err.to_string(),
|
||||
Some(NotificationType::Error(err.kind)),
|
||||
),
|
||||
Ok(Some(Ok(()))) => UIEvent::Notification(
|
||||
Some("Succesfully exported mbox".to_string()),
|
||||
format!("Wrote to file {}", path.display()),
|
||||
Some(NotificationType::Info),
|
||||
),
|
||||
});
|
||||
}))),
|
||||
log_level: LogLevel::INFO,
|
||||
},
|
||||
);
|
||||
}
|
||||
ListingAction::MoveToOtherAccount(ref _account_name, ref _mailbox_path) => {
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
|
||||
"Moving to another account is currently unimplemented".into(),
|
||||
)));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
inner(context, envs_to_set, account_hash, mailbox_hash, a);
|
||||
self.set_dirty(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ mod thread;
|
|||
pub use thread::*;
|
||||
mod types;
|
||||
pub use types::*;
|
||||
mod state;
|
||||
pub mod state;
|
||||
use state::*;
|
||||
|
||||
pub mod envelope;
|
||||
|
|
|
@ -1010,7 +1010,7 @@ mod pp {
|
|||
|
||||
/// Expands `include` macros in configuration file and other configuration
|
||||
/// files (eg. themes) in the filesystem.
|
||||
pub fn pp<P: AsRef<Path>>(path: P) -> Result<String> {
|
||||
pub(super) fn pp<P: AsRef<Path>>(path: P) -> Result<String> {
|
||||
let p_buf: PathBuf = if path.as_ref().is_relative() {
|
||||
path.as_ref().expand().canonicalize()?
|
||||
} else {
|
||||
|
|
|
@ -466,6 +466,8 @@ impl Account {
|
|||
let backend = map.get(&settings.account().format)(
|
||||
settings.account(),
|
||||
Box::new(move |path: &str| {
|
||||
// disjoint-capture-in-closures
|
||||
let _ = &s;
|
||||
s.account.subscribed_mailboxes.is_empty()
|
||||
|| (s.mailbox_confs.contains_key(path)
|
||||
&& s.mailbox_confs[path].mailbox_conf().subscribe.is_true())
|
||||
|
|
|
@ -171,7 +171,7 @@ macro_rules! named_unit_variant {
|
|||
};
|
||||
}
|
||||
|
||||
mod strings {
|
||||
pub mod strings {
|
||||
named_unit_variant!(server_submission);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,11 @@ use crate::types::{ThreadEvent, UIEvent};
|
|||
|
||||
type AsyncTask = async_task::Runnable;
|
||||
|
||||
fn find_task<T>(local: &Worker<T>, global: &Injector<T>, stealers: &[Stealer<T>]) -> Option<T> {
|
||||
fn find_task(
|
||||
local: &Worker<MeliTask>,
|
||||
global: &Injector<MeliTask>,
|
||||
stealers: &[Stealer<MeliTask>],
|
||||
) -> Option<MeliTask> {
|
||||
// Pop a task from the local queue, if not empty.
|
||||
local.pop().or_else(|| {
|
||||
// Otherwise, we need to look for a task elsewhere.
|
||||
|
|
|
@ -26,13 +26,13 @@ use serde::{de, de::Visitor, Deserialize, Deserializer};
|
|||
mod color;
|
||||
pub use color::*;
|
||||
#[macro_use]
|
||||
mod position;
|
||||
pub mod position;
|
||||
#[macro_use]
|
||||
mod cells;
|
||||
pub mod cells;
|
||||
#[macro_use]
|
||||
mod keys;
|
||||
pub mod keys;
|
||||
pub mod embed;
|
||||
mod text_editing;
|
||||
pub mod text_editing;
|
||||
use std::fmt;
|
||||
|
||||
pub use self::{cells::*, keys::*, position::*, text_editing::*};
|
||||
|
|
|
@ -746,7 +746,6 @@ impl Serialize for Color {
|
|||
}
|
||||
}
|
||||
|
||||
pub use aliases::*;
|
||||
pub mod aliases {
|
||||
use super::Color;
|
||||
|
||||
|
|
|
@ -34,10 +34,10 @@ mod watch;
|
|||
pub use watch::*;
|
||||
mod search;
|
||||
pub use search::*;
|
||||
mod cache;
|
||||
pub mod cache;
|
||||
pub mod error;
|
||||
pub mod managesieve;
|
||||
mod untagged;
|
||||
pub mod untagged;
|
||||
|
||||
use std::{
|
||||
collections::{hash_map::DefaultHasher, BTreeSet, HashMap, HashSet},
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
|
||||
use super::*;
|
||||
mod sync;
|
||||
pub mod sync;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use crate::{
|
||||
|
@ -104,7 +104,7 @@ pub trait ImapCacheReset: Send + core::fmt::Debug {
|
|||
pub use sqlite3_m::*;
|
||||
|
||||
#[cfg(feature = "sqlite3")]
|
||||
mod sqlite3_m {
|
||||
pub mod sqlite3_m {
|
||||
use super::*;
|
||||
use crate::utils::sqlite3::{
|
||||
self,
|
||||
|
@ -739,7 +739,7 @@ pub(super) async fn fetch_cached_envs(state: &mut FetchState) -> Result<Option<V
|
|||
pub use default_m::*;
|
||||
|
||||
#[cfg(not(feature = "sqlite3"))]
|
||||
mod default_m {
|
||||
pub mod default_m {
|
||||
use super::*;
|
||||
#[derive(Debug)]
|
||||
pub struct DefaultCache;
|
||||
|
|
|
@ -25,11 +25,6 @@ use std::{
|
|||
time::SystemTime,
|
||||
};
|
||||
|
||||
use nom::{
|
||||
branch::alt, bytes::complete::tag, combinator::map, multi::separated_list1,
|
||||
sequence::separated_pair,
|
||||
};
|
||||
|
||||
use super::{ImapConnection, ImapProtocol, ImapServerConf, UIDStore};
|
||||
use crate::{
|
||||
conf::AccountSettings,
|
||||
|
@ -43,17 +38,6 @@ pub struct ManageSieveConnection {
|
|||
pub inner: ImapConnection,
|
||||
}
|
||||
|
||||
pub fn managesieve_capabilities(input: &[u8]) -> Result<Vec<(&[u8], &[u8])>> {
|
||||
let (_, ret) = separated_list1(
|
||||
tag(b"\r\n"),
|
||||
alt((
|
||||
separated_pair(quoted_raw, tag(b" "), quoted_raw),
|
||||
map(quoted_raw, |q| (q, &b""[..])),
|
||||
)),
|
||||
)(input)?;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
|
||||
pub enum ManageSieveResponse<'a> {
|
||||
Ok {
|
||||
|
@ -66,231 +50,6 @@ pub enum ManageSieveResponse<'a> {
|
|||
},
|
||||
}
|
||||
|
||||
mod parser {
|
||||
use nom::{
|
||||
bytes::complete::tag,
|
||||
character::complete::crlf,
|
||||
combinator::{iterator, map, opt},
|
||||
};
|
||||
pub use nom::{
|
||||
bytes::complete::{is_not, tag_no_case},
|
||||
sequence::{delimited, pair, preceded, terminated},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
pub fn sieve_name(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
crate::backends::imap::protocol_parser::string_token(input)
|
||||
}
|
||||
|
||||
// *(sieve-name [SP "ACTIVE"] CRLF)
|
||||
// response-oknobye
|
||||
pub fn listscripts(input: &[u8]) -> IResult<&[u8], Vec<(&[u8], bool)>> {
|
||||
let mut it = iterator(
|
||||
input,
|
||||
alt((
|
||||
terminated(
|
||||
map(terminated(sieve_name, tag_no_case(b" ACTIVE")), |r| {
|
||||
(r, true)
|
||||
}),
|
||||
crlf,
|
||||
),
|
||||
terminated(map(sieve_name, |r| (r, false)), crlf),
|
||||
)),
|
||||
);
|
||||
|
||||
let parsed = (&mut it).collect::<Vec<(&[u8], bool)>>();
|
||||
let res: IResult<_, _> = it.finish();
|
||||
let (rest, _) = res?;
|
||||
Ok((rest, parsed))
|
||||
}
|
||||
|
||||
// response-getscript = (sieve-script CRLF response-ok) /
|
||||
// response-nobye
|
||||
pub fn getscript(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
sieve_name(input)
|
||||
}
|
||||
|
||||
pub fn response_oknobye(input: &[u8]) -> IResult<&[u8], ManageSieveResponse> {
|
||||
alt((
|
||||
map(
|
||||
terminated(
|
||||
pair(
|
||||
preceded(
|
||||
tag_no_case(b"ok"),
|
||||
opt(preceded(
|
||||
tag(b" "),
|
||||
delimited(tag(b"("), is_not(")"), tag(b")")),
|
||||
)),
|
||||
),
|
||||
opt(preceded(tag(b" "), sieve_name)),
|
||||
),
|
||||
crlf,
|
||||
),
|
||||
|(code, message)| ManageSieveResponse::Ok { code, message },
|
||||
),
|
||||
map(
|
||||
terminated(
|
||||
pair(
|
||||
preceded(
|
||||
alt((tag_no_case(b"no"), tag_no_case(b"bye"))),
|
||||
opt(preceded(
|
||||
tag(b" "),
|
||||
delimited(tag(b"("), is_not(")"), tag(b")")),
|
||||
)),
|
||||
),
|
||||
opt(preceded(tag(b" "), sieve_name)),
|
||||
),
|
||||
crlf,
|
||||
),
|
||||
|(code, message)| ManageSieveResponse::NoBye { code, message },
|
||||
),
|
||||
))(input)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managesieve_listscripts() {
|
||||
let input_1 = b"\"summer_script\"\r\n\"vacation_script\"\r\n{13}\r\nclever\"script\r\n\"main_script\" ACTIVE\r\nOK";
|
||||
assert_eq!(
|
||||
terminated(listscripts, tag_no_case(b"OK"))(input_1),
|
||||
Ok((
|
||||
&b""[..],
|
||||
vec![
|
||||
(&b"summer_script"[..], false),
|
||||
(&b"vacation_script"[..], false),
|
||||
(&b"clever\"script"[..], false),
|
||||
(&b"main_script"[..], true)
|
||||
]
|
||||
))
|
||||
);
|
||||
|
||||
let input_2 = b"\"summer_script\"\r\n\"main_script\" active\r\nok";
|
||||
assert_eq!(
|
||||
terminated(listscripts, tag_no_case(b"OK"))(input_2),
|
||||
Ok((
|
||||
&b""[..],
|
||||
vec![(&b"summer_script"[..], false), (&b"main_script"[..], true)]
|
||||
))
|
||||
);
|
||||
let input_3 = b"ok";
|
||||
assert_eq!(
|
||||
terminated(listscripts, tag_no_case(b"OK"))(input_3),
|
||||
Ok((&b""[..], vec![]))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managesieve_general() {
|
||||
assert_eq!(managesieve_capabilities(b"\"IMPLEMENTATION\" \"Dovecot Pigeonhole\"\r\n\"SIEVE\" \"fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date index ihave duplicate mime foreverypart extracttext\"\r\n\"NOTIFY\" \"mailto\"\r\n\"SASL\" \"PLAIN\"\r\n\"STARTTLS\"\r\n\"VERSION\" \"1.0\"\r\n").unwrap(), vec![
|
||||
(&b"IMPLEMENTATION"[..],&b"Dovecot Pigeonhole"[..]),
|
||||
(&b"SIEVE"[..],&b"fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date index ihave duplicate mime foreverypart extracttext"[..]),
|
||||
(&b"NOTIFY"[..],&b"mailto"[..]),
|
||||
(&b"SASL"[..],&b"PLAIN"[..]),
|
||||
(&b"STARTTLS"[..], &b""[..]),
|
||||
(&b"VERSION"[..],&b"1.0"[..])]
|
||||
|
||||
);
|
||||
|
||||
let response_ok = b"OK (WARNINGS) \"line 8: server redirect action limit is 2, this redirect might be ignored\"\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_ok),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::Ok {
|
||||
code: Some(&b"WARNINGS"[..]),
|
||||
message: Some(&b"line 8: server redirect action limit is 2, this redirect might be ignored"[..]),
|
||||
}
|
||||
))
|
||||
);
|
||||
let response_ok = b"OK (WARNINGS)\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_ok),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::Ok {
|
||||
code: Some(&b"WARNINGS"[..]),
|
||||
message: None,
|
||||
}
|
||||
))
|
||||
);
|
||||
let response_ok =
|
||||
b"OK \"line 8: server redirect action limit is 2, this redirect might be ignored\"\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_ok),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::Ok {
|
||||
code: None,
|
||||
message: Some(&b"line 8: server redirect action limit is 2, this redirect might be ignored"[..]),
|
||||
}
|
||||
))
|
||||
);
|
||||
let response_ok = b"Ok\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_ok),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::Ok {
|
||||
code: None,
|
||||
message: None,
|
||||
}
|
||||
))
|
||||
);
|
||||
|
||||
let response_nobye = b"No (NONEXISTENT) \"There is no script by that name\"\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_nobye),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::NoBye {
|
||||
code: Some(&b"NONEXISTENT"[..]),
|
||||
message: Some(&b"There is no script by that name"[..]),
|
||||
}
|
||||
))
|
||||
);
|
||||
let response_nobye = b"No (NONEXISTENT) {31}\r\nThere is no script by that name\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_nobye),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::NoBye {
|
||||
code: Some(&b"NONEXISTENT"[..]),
|
||||
message: Some(&b"There is no script by that name"[..]),
|
||||
}
|
||||
))
|
||||
);
|
||||
|
||||
let response_nobye = b"No\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_nobye),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::NoBye {
|
||||
code: None,
|
||||
message: None,
|
||||
}
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Return a byte sequence surrounded by "s and decoded if necessary
|
||||
pub fn quoted_raw(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
if input.is_empty() || input[0] != b'"' {
|
||||
return Err(nom::Err::Error((input, "empty").into()));
|
||||
}
|
||||
|
||||
let mut i = 1;
|
||||
while i < input.len() {
|
||||
if input[i] == b'\"' && input[i - 1] != b'\\' {
|
||||
return Ok((&input[i + 1..], &input[1..i]));
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
Err(nom::Err::Error((input, "no quotes").into()))
|
||||
}
|
||||
|
||||
impl ManageSieveConnection {
|
||||
pub fn new(
|
||||
account_hash: crate::backends::AccountHash,
|
||||
|
@ -479,3 +238,247 @@ impl ManageSieveConnection {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub mod parser {
|
||||
use nom::{
|
||||
branch::alt,
|
||||
bytes::complete::tag,
|
||||
character::complete::crlf,
|
||||
combinator::{iterator, map, opt},
|
||||
multi::separated_list1,
|
||||
sequence::separated_pair,
|
||||
};
|
||||
pub use nom::{
|
||||
bytes::complete::{is_not, tag_no_case},
|
||||
sequence::{delimited, pair, preceded, terminated},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Return a byte sequence surrounded by "s and decoded if necessary
|
||||
pub fn quoted_raw(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
if input.is_empty() || input[0] != b'"' {
|
||||
return Err(nom::Err::Error((input, "empty").into()));
|
||||
}
|
||||
|
||||
let mut i = 1;
|
||||
while i < input.len() {
|
||||
if input[i] == b'\"' && input[i - 1] != b'\\' {
|
||||
return Ok((&input[i + 1..], &input[1..i]));
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
Err(nom::Err::Error((input, "no quotes").into()))
|
||||
}
|
||||
|
||||
pub fn managesieve_capabilities(input: &[u8]) -> Result<Vec<(&[u8], &[u8])>> {
|
||||
let (_, ret) = separated_list1(
|
||||
tag(b"\r\n"),
|
||||
alt((
|
||||
separated_pair(quoted_raw, tag(b" "), quoted_raw),
|
||||
map(quoted_raw, |q| (q, &b""[..])),
|
||||
)),
|
||||
)(input)?;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub fn sieve_name(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
crate::backends::imap::protocol_parser::string_token(input)
|
||||
}
|
||||
|
||||
// *(sieve-name [SP "ACTIVE"] CRLF)
|
||||
// response-oknobye
|
||||
pub fn listscripts(input: &[u8]) -> IResult<&[u8], Vec<(&[u8], bool)>> {
|
||||
let mut it = iterator(
|
||||
input,
|
||||
alt((
|
||||
terminated(
|
||||
map(terminated(sieve_name, tag_no_case(b" ACTIVE")), |r| {
|
||||
(r, true)
|
||||
}),
|
||||
crlf,
|
||||
),
|
||||
terminated(map(sieve_name, |r| (r, false)), crlf),
|
||||
)),
|
||||
);
|
||||
|
||||
let parsed = (&mut it).collect::<Vec<(&[u8], bool)>>();
|
||||
let res: IResult<_, _> = it.finish();
|
||||
let (rest, _) = res?;
|
||||
Ok((rest, parsed))
|
||||
}
|
||||
|
||||
// response-getscript = (sieve-script CRLF response-ok) /
|
||||
// response-nobye
|
||||
pub fn getscript(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
sieve_name(input)
|
||||
}
|
||||
|
||||
pub fn response_oknobye(input: &[u8]) -> IResult<&[u8], ManageSieveResponse> {
|
||||
alt((
|
||||
map(
|
||||
terminated(
|
||||
pair(
|
||||
preceded(
|
||||
tag_no_case(b"ok"),
|
||||
opt(preceded(
|
||||
tag(b" "),
|
||||
delimited(tag(b"("), is_not(")"), tag(b")")),
|
||||
)),
|
||||
),
|
||||
opt(preceded(tag(b" "), sieve_name)),
|
||||
),
|
||||
crlf,
|
||||
),
|
||||
|(code, message)| ManageSieveResponse::Ok { code, message },
|
||||
),
|
||||
map(
|
||||
terminated(
|
||||
pair(
|
||||
preceded(
|
||||
alt((tag_no_case(b"no"), tag_no_case(b"bye"))),
|
||||
opt(preceded(
|
||||
tag(b" "),
|
||||
delimited(tag(b"("), is_not(")"), tag(b")")),
|
||||
)),
|
||||
),
|
||||
opt(preceded(tag(b" "), sieve_name)),
|
||||
),
|
||||
crlf,
|
||||
),
|
||||
|(code, message)| ManageSieveResponse::NoBye { code, message },
|
||||
),
|
||||
))(input)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_managesieve_listscripts() {
|
||||
let input_1 = b"\"summer_script\"\r\n\"vacation_script\"\r\n{13}\r\nclever\"script\r\n\"main_script\" ACTIVE\r\nOK";
|
||||
assert_eq!(
|
||||
terminated(listscripts, tag_no_case(b"OK"))(input_1),
|
||||
Ok((
|
||||
&b""[..],
|
||||
vec![
|
||||
(&b"summer_script"[..], false),
|
||||
(&b"vacation_script"[..], false),
|
||||
(&b"clever\"script"[..], false),
|
||||
(&b"main_script"[..], true)
|
||||
]
|
||||
))
|
||||
);
|
||||
|
||||
let input_2 = b"\"summer_script\"\r\n\"main_script\" active\r\nok";
|
||||
assert_eq!(
|
||||
terminated(listscripts, tag_no_case(b"OK"))(input_2),
|
||||
Ok((
|
||||
&b""[..],
|
||||
vec![(&b"summer_script"[..], false), (&b"main_script"[..], true)]
|
||||
))
|
||||
);
|
||||
let input_3 = b"ok";
|
||||
assert_eq!(
|
||||
terminated(listscripts, tag_no_case(b"OK"))(input_3),
|
||||
Ok((&b""[..], vec![]))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_managesieve_general() {
|
||||
assert_eq!(managesieve_capabilities(b"\"IMPLEMENTATION\" \"Dovecot Pigeonhole\"\r\n\"SIEVE\" \"fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date index ihave duplicate mime foreverypart extracttext\"\r\n\"NOTIFY\" \"mailto\"\r\n\"SASL\" \"PLAIN\"\r\n\"STARTTLS\"\r\n\"VERSION\" \"1.0\"\r\n").unwrap(), vec![
|
||||
(&b"IMPLEMENTATION"[..],&b"Dovecot Pigeonhole"[..]),
|
||||
(&b"SIEVE"[..],&b"fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date index ihave duplicate mime foreverypart extracttext"[..]),
|
||||
(&b"NOTIFY"[..],&b"mailto"[..]),
|
||||
(&b"SASL"[..],&b"PLAIN"[..]),
|
||||
(&b"STARTTLS"[..], &b""[..]),
|
||||
(&b"VERSION"[..],&b"1.0"[..])]
|
||||
|
||||
);
|
||||
|
||||
let response_ok = b"OK (WARNINGS) \"line 8: server redirect action limit is 2, this redirect might be ignored\"\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_ok),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::Ok {
|
||||
code: Some(&b"WARNINGS"[..]),
|
||||
message: Some(&b"line 8: server redirect action limit is 2, this redirect might be ignored"[..]),
|
||||
}
|
||||
))
|
||||
);
|
||||
let response_ok = b"OK (WARNINGS)\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_ok),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::Ok {
|
||||
code: Some(&b"WARNINGS"[..]),
|
||||
message: None,
|
||||
}
|
||||
))
|
||||
);
|
||||
let response_ok =
|
||||
b"OK \"line 8: server redirect action limit is 2, this redirect might be ignored\"\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_ok),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::Ok {
|
||||
code: None,
|
||||
message: Some(&b"line 8: server redirect action limit is 2, this redirect might be ignored"[..]),
|
||||
}
|
||||
))
|
||||
);
|
||||
let response_ok = b"Ok\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_ok),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::Ok {
|
||||
code: None,
|
||||
message: None,
|
||||
}
|
||||
))
|
||||
);
|
||||
|
||||
let response_nobye = b"No (NONEXISTENT) \"There is no script by that name\"\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_nobye),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::NoBye {
|
||||
code: Some(&b"NONEXISTENT"[..]),
|
||||
message: Some(&b"There is no script by that name"[..]),
|
||||
}
|
||||
))
|
||||
);
|
||||
let response_nobye = b"No (NONEXISTENT) {31}\r\nThere is no script by that name\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_nobye),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::NoBye {
|
||||
code: Some(&b"NONEXISTENT"[..]),
|
||||
message: Some(&b"There is no script by that name"[..]),
|
||||
}
|
||||
))
|
||||
);
|
||||
|
||||
let response_nobye = b"No\r\n";
|
||||
assert_eq!(
|
||||
response_oknobye(response_nobye),
|
||||
Ok((
|
||||
&b""[..],
|
||||
ManageSieveResponse::NoBye {
|
||||
code: None,
|
||||
message: None,
|
||||
}
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,20 +202,20 @@ fn get_rw_lock_blocking(f: &File, path: &Path) -> Result<()> {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MboxMailbox {
|
||||
hash: MailboxHash,
|
||||
name: String,
|
||||
path: PathBuf,
|
||||
fs_path: PathBuf,
|
||||
content: Vec<u8>,
|
||||
children: Vec<MailboxHash>,
|
||||
parent: Option<MailboxHash>,
|
||||
usage: Arc<RwLock<SpecialUsageMailbox>>,
|
||||
is_subscribed: bool,
|
||||
permissions: MailboxPermissions,
|
||||
pub struct MboxMailbox {
|
||||
pub hash: MailboxHash,
|
||||
pub name: String,
|
||||
pub path: PathBuf,
|
||||
pub fs_path: PathBuf,
|
||||
pub content: Vec<u8>,
|
||||
pub children: Vec<MailboxHash>,
|
||||
pub parent: Option<MailboxHash>,
|
||||
pub usage: Arc<RwLock<SpecialUsageMailbox>>,
|
||||
pub is_subscribed: bool,
|
||||
pub permissions: MailboxPermissions,
|
||||
pub total: Arc<Mutex<usize>>,
|
||||
pub unseen: Arc<Mutex<usize>>,
|
||||
index: Arc<Mutex<HashMap<EnvelopeHash, (Offset, Length)>>>,
|
||||
pub index: Arc<Mutex<HashMap<EnvelopeHash, (Offset, Length)>>>,
|
||||
}
|
||||
|
||||
impl BackendMailbox for MboxMailbox {
|
||||
|
@ -285,11 +285,11 @@ impl BackendMailbox for MboxMailbox {
|
|||
/// `BackendOp` implementor for Mbox
|
||||
#[derive(Debug, Default)]
|
||||
pub struct MboxOp {
|
||||
_hash: EnvelopeHash,
|
||||
path: PathBuf,
|
||||
offset: Offset,
|
||||
length: Length,
|
||||
slice: std::cell::RefCell<Option<Vec<u8>>>,
|
||||
pub _hash: EnvelopeHash,
|
||||
pub path: PathBuf,
|
||||
pub offset: Offset,
|
||||
pub length: Length,
|
||||
pub slice: std::cell::RefCell<Option<Vec<u8>>>,
|
||||
}
|
||||
|
||||
impl MboxOp {
|
||||
|
|
|
@ -30,6 +30,7 @@ use smallvec::SmallVec;
|
|||
|
||||
use crate::{get_conf_val, get_path_hash};
|
||||
mod store;
|
||||
pub use store::*;
|
||||
#[macro_use]
|
||||
mod protocol_parser;
|
||||
pub use protocol_parser::*;
|
||||
|
|
|
@ -55,7 +55,7 @@ CREATE TABLE IF NOT EXISTS article (
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Store {
|
||||
connection: Connection,
|
||||
pub connection: Connection,
|
||||
}
|
||||
|
||||
impl Store {
|
||||
|
|
|
@ -718,7 +718,7 @@ impl MailBackend for NotmuchDb {
|
|||
use notify::{watcher, RecursiveMode, Watcher};
|
||||
|
||||
let account_hash = self.account_hash;
|
||||
let collection = self.collection.clone();
|
||||
let tag_index = self.collection.tag_index.clone();
|
||||
let lib = self.lib.clone();
|
||||
let path = self.path.clone();
|
||||
let revision_uuid = self.revision_uuid.clone();
|
||||
|
@ -748,7 +748,7 @@ impl MailBackend for NotmuchDb {
|
|||
mailboxes.clone(),
|
||||
index.clone(),
|
||||
mailbox_index.clone(),
|
||||
collection.tag_index.clone(),
|
||||
tag_index.clone(),
|
||||
account_hash,
|
||||
event_consumer.clone(),
|
||||
new_revision_uuid,
|
||||
|
@ -826,7 +826,7 @@ impl MailBackend for NotmuchDb {
|
|||
self.lib.clone(),
|
||||
true,
|
||||
)?;
|
||||
let collection = self.collection.clone();
|
||||
let tag_index = self.collection.clone().tag_index;
|
||||
let index = self.index.clone();
|
||||
|
||||
Ok(Box::pin(async move {
|
||||
|
@ -914,11 +914,7 @@ impl MailBackend for NotmuchDb {
|
|||
for (f, v) in flags.iter() {
|
||||
if let (Err(tag), true) = (f, v) {
|
||||
let hash = TagHash::from_bytes(tag.as_bytes());
|
||||
collection
|
||||
.tag_index
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(hash, tag.to_string());
|
||||
tag_index.write().unwrap().insert(hash, tag.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ macro_rules! named_unit_variant {
|
|||
};
|
||||
}
|
||||
|
||||
mod strings {
|
||||
pub mod strings {
|
||||
named_unit_variant!(ask);
|
||||
}
|
||||
|
||||
|
@ -253,7 +253,7 @@ impl<'de> Deserialize<'de> for ToggleFlag {
|
|||
{
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum InnerToggleFlag {
|
||||
enum InnerToggleFlag {
|
||||
Bool(bool),
|
||||
#[serde(with = "strings::ask")]
|
||||
Ask,
|
||||
|
|
|
@ -2595,25 +2595,26 @@ pub mod address {
|
|||
))
|
||||
}
|
||||
|
||||
///`no-fold-literal = "[" *dtext "]"`
|
||||
pub fn no_fold_literal(input: &[u8]) -> IResult<&[u8], Cow<'_, [u8]>> {
|
||||
let orig_input = input;
|
||||
let (input, _) = tag("[")(input)?;
|
||||
let (input, ret) = many0(dtext)(input)?;
|
||||
let (input, _) = tag("]")(input)?;
|
||||
Ok((input, Cow::Borrowed(&orig_input[0..ret.len() + 1])))
|
||||
}
|
||||
|
||||
///`id-left = dot-atom-text / obs-id-left`
|
||||
pub fn id_left(input: &[u8]) -> IResult<&[u8], Cow<'_, [u8]>> {
|
||||
dot_atom_text(input)
|
||||
}
|
||||
///`id-right = dot-atom-text / no-fold-literal / obs-id-right`
|
||||
pub fn id_right(input: &[u8]) -> IResult<&[u8], Cow<'_, [u8]>> {
|
||||
alt((dot_atom_text, no_fold_literal))(input)
|
||||
}
|
||||
|
||||
///`msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]`
|
||||
pub fn msg_id(input: &[u8]) -> IResult<&[u8], MessageID> {
|
||||
///`no-fold-literal = "[" *dtext "]"`
|
||||
pub fn no_fold_literal(input: &[u8]) -> IResult<&[u8], Cow<'_, [u8]>> {
|
||||
let orig_input = input;
|
||||
let (input, _) = tag("[")(input)?;
|
||||
let (input, ret) = many0(dtext)(input)?;
|
||||
let (input, _) = tag("]")(input)?;
|
||||
Ok((input, Cow::Borrowed(&orig_input[0..ret.len() + 1])))
|
||||
}
|
||||
|
||||
///`id-left = dot-atom-text / obs-id-left`
|
||||
pub fn id_left(input: &[u8]) -> IResult<&[u8], Cow<'_, [u8]>> {
|
||||
dot_atom_text(input)
|
||||
}
|
||||
///`id-right = dot-atom-text / no-fold-literal / obs-id-right`
|
||||
pub fn id_right(input: &[u8]) -> IResult<&[u8], Cow<'_, [u8]>> {
|
||||
alt((dot_atom_text, no_fold_literal))(input)
|
||||
}
|
||||
let (input, _) = opt(cfws)(input)?;
|
||||
let orig_input = input;
|
||||
let (input, _) = tag("<")(input)?;
|
||||
|
|
|
@ -30,6 +30,9 @@ struct TagData {
|
|||
io_state: Arc<Mutex<IoState>>,
|
||||
}
|
||||
|
||||
///
|
||||
/// # Safety
|
||||
/// .
|
||||
pub unsafe extern "C" fn gpgme_register_io_cb(
|
||||
data: *mut ::std::os::raw::c_void,
|
||||
fd: ::std::os::raw::c_int,
|
||||
|
@ -66,6 +69,9 @@ pub unsafe extern "C" fn gpgme_register_io_cb(
|
|||
0
|
||||
}
|
||||
|
||||
///
|
||||
/// # Safety
|
||||
/// .
|
||||
pub unsafe extern "C" fn gpgme_remove_io_cb(tag: *mut ::std::os::raw::c_void) {
|
||||
let tag_data: Arc<TagData> = Arc::from_raw(tag as *const _);
|
||||
let mut io_state_lck = tag_data.io_state.lock().unwrap();
|
||||
|
@ -75,6 +81,9 @@ pub unsafe extern "C" fn gpgme_remove_io_cb(tag: *mut ::std::os::raw::c_void) {
|
|||
let _ = Arc::into_raw(tag_data);
|
||||
}
|
||||
|
||||
///
|
||||
/// # Safety
|
||||
/// .
|
||||
pub unsafe extern "C" fn gpgme_event_io_cb(
|
||||
data: *mut ::std::os::raw::c_void,
|
||||
type_: gpgme_event_io_t,
|
||||
|
|
|
@ -72,9 +72,9 @@ macro_rules! c_string_literal {
|
|||
}
|
||||
}};
|
||||
}
|
||||
mod bindings;
|
||||
pub mod bindings;
|
||||
use bindings::*;
|
||||
mod io;
|
||||
pub mod io;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum GpgmeFlag {
|
||||
|
@ -804,7 +804,8 @@ impl Context {
|
|||
.chain_err_summary(|| {
|
||||
"libgpgme error: could not perform seek on signature data object"
|
||||
})?;
|
||||
_ = text;
|
||||
// disjoint-capture-in-closures
|
||||
let _ = &text;
|
||||
sig.into_bytes()
|
||||
})
|
||||
}
|
||||
|
@ -1127,7 +1128,8 @@ impl Context {
|
|||
cipher
|
||||
.seek(std::io::SeekFrom::Start(0))
|
||||
.chain_err_summary(|| "libgpgme error: could not perform seek on plain text")?;
|
||||
_ = plain;
|
||||
// disjoint-capture-in-closures
|
||||
let _ = &plain;
|
||||
cipher.into_bytes()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
pub mod grapheme_clusters;
|
||||
pub mod line_break;
|
||||
pub mod search;
|
||||
mod tables;
|
||||
mod types;
|
||||
pub mod tables;
|
||||
pub mod types;
|
||||
pub use types::Reflow;
|
||||
pub mod wcwidth;
|
||||
pub use grapheme_clusters::*;
|
||||
|
|
|
@ -741,7 +741,7 @@ const TIMEZONE_ABBR: &[(&[u8], (i8, i8))] = &[
|
|||
(b"YEKT", (05, 0)),
|
||||
];
|
||||
|
||||
mod lib {
|
||||
pub mod lib {
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use libc::tm;
|
||||
|
|
Loading…
Reference in New Issue