From 679007ba643f104eef6f91fc1140977c1d5e31e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20DOUIN?= Date: Mon, 17 Jul 2023 11:28:46 +0200 Subject: [PATCH] resolve folder aliases from backend implems instead #95 --- CHANGELOG.md | 5 ++ Cargo.lock | 5 +- Cargo.toml | 2 +- src/cache/id_mapper.rs | 14 ++++-- src/domain/email/handlers.rs | 19 -------- src/main.rs | 95 +++++++++++++++--------------------- src/ui/editor.rs | 5 +- 7 files changed, 61 insertions(+), 84 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17ac18e..de74c69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Made the code async using the tokio async runtime. - On Linux, made the kernel keyring the default one (the one based on keyutils). +### Fixed + +- Fixed the way folder aliases are resolved. In some case, aliases were resolved CLI side and lib side, which led to alias errors [sourcehut#95]. + ## [0.8.1] - 2023-06-15 ### Added @@ -744,3 +748,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [sourcehut#54]: https://todo.sr.ht/~soywod/pimalaya/54 [sourcehut#59]: https://todo.sr.ht/~soywod/pimalaya/59 [sourcehut#60]: https://todo.sr.ht/~soywod/pimalaya/60 +[sourcehut#95]: https://todo.sr.ht/~soywod/pimalaya/95 diff --git a/Cargo.lock b/Cargo.lock index 072cb91..ad5a797 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1883,9 +1883,8 @@ dependencies = [ [[package]] name = "pimalaya-email" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2070e988ba8e4a38a18efaaf14cc1cc2b95029c645419811ea35ebc0dfe32b62" +version = "0.13.1-beta" +source = "git+https://git.sr.ht/~soywod/pimalaya#866279f6cc9e14a565d8ea7d6722a08f5b9293e2" dependencies = [ "advisory-lock", "ammonia", diff --git a/Cargo.toml b/Cargo.toml index 1e6f28c..d195ed3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ indicatif = "0.17" log = "0.4" md5 = "0.7.0" once_cell = "1.16.0" -pimalaya-email = { version = "=0.13.0", default-features = false } +pimalaya-email = { git = "https://git.sr.ht/~soywod/pimalaya", default-features = false } pimalaya-keyring = "=0.0.5" pimalaya-oauth2 = "=0.0.3" pimalaya-process = "=0.0.5" diff --git a/src/cache/id_mapper.rs b/src/cache/id_mapper.rs index aa96b70..d93b540 100644 --- a/src/cache/id_mapper.rs +++ b/src/cache/id_mapper.rs @@ -4,7 +4,10 @@ use log::{debug, trace}; use pimalaya_email::backend::ImapBackend; #[cfg(feature = "notmuch-backend")] use pimalaya_email::backend::NotmuchBackend; -use pimalaya_email::backend::{Backend, MaildirBackend}; +use pimalaya_email::{ + account::AccountConfig, + backend::{Backend, MaildirBackend}, +}; use std::path::{Path, PathBuf}; const ID_MAPPER_DB_FILE_NAME: &str = ".id-mapper.sqlite"; @@ -36,7 +39,11 @@ impl IdMapper { db_path } - pub fn new(backend: &dyn Backend, account: &str, folder: &str) -> Result { + pub fn new( + backend: &dyn Backend, + account_config: &AccountConfig, + folder: &str, + ) -> Result { #[cfg(feature = "imap-backend")] if backend.as_any().is::() { return Ok(IdMapper::Dummy); @@ -53,7 +60,8 @@ impl IdMapper { db_path = Self::find_closest_db_path(backend.path()) } - let digest = md5::compute(account.to_string() + folder); + let folder = account_config.get_folder_alias(folder)?; + let digest = md5::compute(account_config.name.clone() + &folder); let table = format!("id_mapper_{digest:x}"); debug!("creating id mapper table {table} at {db_path:?}…"); diff --git a/src/domain/email/handlers.rs b/src/domain/email/handlers.rs index 09ca8e5..ffe4421 100644 --- a/src/domain/email/handlers.rs +++ b/src/domain/email/handlers.rs @@ -28,7 +28,6 @@ pub async fn attachments( folder: &str, ids: Vec<&str>, ) -> Result<()> { - let folder = config.folder_alias(folder)?; let ids = id_mapper.get_ids(ids)?; let ids = ids.iter().map(String::as_str).collect::>(); let emails = backend.get_emails(&folder, ids.clone()).await?; @@ -78,7 +77,6 @@ pub async fn attachments( } pub async fn copy( - config: &AccountConfig, printer: &mut P, id_mapper: &IdMapper, backend: &mut dyn Backend, @@ -86,8 +84,6 @@ pub async fn copy( to_folder: &str, ids: Vec<&str>, ) -> Result<()> { - let from_folder = config.folder_alias(from_folder)?; - let to_folder = config.folder_alias(to_folder)?; let ids = id_mapper.get_ids(ids)?; let ids = ids.iter().map(String::as_str).collect::>(); backend.copy_emails(&from_folder, &to_folder, ids).await?; @@ -95,14 +91,12 @@ pub async fn copy( } pub async fn delete( - config: &AccountConfig, printer: &mut P, id_mapper: &IdMapper, backend: &mut dyn Backend, folder: &str, ids: Vec<&str>, ) -> Result<()> { - let folder = config.folder_alias(folder)?; let ids = id_mapper.get_ids(ids)?; let ids = ids.iter().map(String::as_str).collect::>(); backend.delete_emails(&folder, ids).await?; @@ -120,8 +114,6 @@ pub async fn forward( headers: Option>, body: Option<&str>, ) -> Result<()> { - let folder = config.folder_alias(folder)?; - let ids = id_mapper.get_ids([id])?; let ids = ids.iter().map(String::as_str).collect::>(); @@ -150,7 +142,6 @@ pub async fn list( page_size: Option, page: usize, ) -> Result<()> { - let folder = config.folder_alias(folder)?; let page_size = page_size.unwrap_or(config.email_listing_page_size()); debug!("page size: {}", page_size); @@ -202,7 +193,6 @@ pub async fn mailto( } pub async fn move_( - config: &AccountConfig, printer: &mut P, id_mapper: &IdMapper, backend: &mut dyn Backend, @@ -210,8 +200,6 @@ pub async fn move_( to_folder: &str, ids: Vec<&str>, ) -> Result<()> { - let from_folder = config.folder_alias(from_folder)?; - let to_folder = config.folder_alias(to_folder)?; let ids = id_mapper.get_ids(ids)?; let ids = ids.iter().map(String::as_str).collect::>(); backend.move_emails(&from_folder, &to_folder, ids).await?; @@ -229,7 +217,6 @@ pub async fn read( raw: bool, headers: Vec<&str>, ) -> Result<()> { - let folder = config.folder_alias(folder)?; let ids = id_mapper.get_ids(ids)?; let ids = ids.iter().map(String::as_str).collect::>(); let emails = backend.get_emails(&folder, ids).await?; @@ -275,8 +262,6 @@ pub async fn reply( headers: Option>, body: Option<&str>, ) -> Result<()> { - let folder = config.folder_alias(folder)?; - let ids = id_mapper.get_ids([id])?; let ids = ids.iter().map(String::as_str).collect::>(); @@ -300,14 +285,12 @@ pub async fn reply( } pub async fn save( - config: &AccountConfig, printer: &mut P, id_mapper: &IdMapper, backend: &mut dyn Backend, folder: &str, raw_email: String, ) -> Result<()> { - let folder = config.folder_alias(folder)?; let is_tty = atty::is(Stream::Stdin); let is_json = printer.is_json(); let raw_email = if is_tty || is_json { @@ -340,7 +323,6 @@ pub async fn search( page_size: Option, page: usize, ) -> Result<()> { - let folder = config.folder_alias(folder)?; let page_size = page_size.unwrap_or(config.email_listing_page_size()); let envelopes = Envelopes::from_backend( config, @@ -369,7 +351,6 @@ pub async fn sort( page_size: Option, page: usize, ) -> Result<()> { - let folder = config.folder_alias(folder)?; let page_size = page_size.unwrap_or(config.email_listing_page_size()); let envelopes = Envelopes::from_backend( config, diff --git a/src/main.rs b/src/main.rs index 1d119fe..d4950a4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -101,7 +101,6 @@ async fn main() -> Result<()> { let config = DeserializedConfig::from_opt_path(config::args::parse_arg(&m))?; let account_config = config.to_account_config(account::args::parse_arg(&m))?; - let account_name = account_config.name.clone(); let folder = folder::args::parse_source_arg(&m); let disable_cache = cache::args::parse_disable_cache_flag(&m); @@ -115,7 +114,7 @@ async fn main() -> Result<()> { #[cfg(feature = "imap-backend")] if let BackendConfig::Imap(imap_config) = &account_config.backend { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); match imap::args::matches(&m)? { Some(imap::args::Cmd::Notify(keepalive)) => { let mut backend = @@ -159,7 +158,6 @@ async fn main() -> Result<()> { let folder = folder .ok_or_else(|| anyhow!("the folder argument is missing")) .context("cannot create folder")?; - let folder = account_config.folder_alias(folder)?; let mut backend = backend_builder.build().await?; folder::handlers::create(&mut printer, backend.as_mut(), &folder).await?; return Ok(()); @@ -171,16 +169,13 @@ async fn main() -> Result<()> { return Ok(()); } Some(folder::args::Cmd::Expunge) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.build().await?; folder::handlers::expunge(&mut printer, backend.as_mut(), &folder).await?; return Ok(()); } Some(folder::args::Cmd::Delete) => { - let folder = folder - .ok_or_else(|| anyhow!("the folder argument is missing")) - .context("cannot delete folder")?; - let folder = account_config.folder_alias(folder)?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.build().await?; folder::handlers::delete(&mut printer, backend.as_mut(), &folder).await?; return Ok(()); @@ -191,9 +186,9 @@ async fn main() -> Result<()> { // checks email commands match email::args::matches(&m)? { Some(email::args::Cmd::Attachments(ids)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; email::handlers::attachments( &account_config, &mut printer, @@ -206,12 +201,11 @@ async fn main() -> Result<()> { return Ok(()); } Some(email::args::Cmd::Copy(ids, to_folder)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; email::handlers::copy( - &account_config, &mut printer, &id_mapper, backend.as_mut(), @@ -224,27 +218,20 @@ async fn main() -> Result<()> { return Ok(()); } Some(email::args::Cmd::Delete(ids)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; - email::handlers::delete( - &account_config, - &mut printer, - &id_mapper, - backend.as_mut(), - &folder, - ids, - ) - .await?; + email::handlers::delete(&mut printer, &id_mapper, backend.as_mut(), &folder, ids) + .await?; return Ok(()); } Some(email::args::Cmd::Forward(id, headers, body)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; let mut sender = sender_builder.build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; email::handlers::forward( &account_config, @@ -262,9 +249,9 @@ async fn main() -> Result<()> { return Ok(()); } Some(email::args::Cmd::List(max_width, page_size, page)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; email::handlers::list( &account_config, @@ -281,12 +268,11 @@ async fn main() -> Result<()> { return Ok(()); } Some(email::args::Cmd::Move(ids, to_folder)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; email::handlers::move_( - &account_config, &mut printer, &id_mapper, backend.as_mut(), @@ -299,9 +285,9 @@ async fn main() -> Result<()> { return Ok(()); } Some(email::args::Cmd::Read(ids, text_mime, raw, headers)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; email::handlers::read( &account_config, @@ -319,10 +305,10 @@ async fn main() -> Result<()> { return Ok(()); } Some(email::args::Cmd::Reply(id, all, headers, body)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; let mut sender = sender_builder.build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; email::handlers::reply( &account_config, @@ -341,12 +327,11 @@ async fn main() -> Result<()> { return Ok(()); } Some(email::args::Cmd::Save(raw_email)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; email::handlers::save( - &account_config, &mut printer, &id_mapper, backend.as_mut(), @@ -358,9 +343,9 @@ async fn main() -> Result<()> { return Ok(()); } Some(email::args::Cmd::Search(query, max_width, page_size, page)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; email::handlers::search( &account_config, @@ -378,9 +363,9 @@ async fn main() -> Result<()> { return Ok(()); } Some(email::args::Cmd::Sort(criteria, query, max_width, page_size, page)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; email::handlers::sort( &account_config, @@ -414,9 +399,9 @@ async fn main() -> Result<()> { } Some(email::args::Cmd::Flag(m)) => match m { Some(flag::args::Cmd::Set(ids, ref flags)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; flag::handlers::set( &mut printer, @@ -431,9 +416,9 @@ async fn main() -> Result<()> { return Ok(()); } Some(flag::args::Cmd::Add(ids, ref flags)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; flag::handlers::add( &mut printer, @@ -448,9 +433,9 @@ async fn main() -> Result<()> { return Ok(()); } Some(flag::args::Cmd::Remove(ids, ref flags)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; flag::handlers::remove( &mut printer, @@ -468,9 +453,9 @@ async fn main() -> Result<()> { }, Some(email::args::Cmd::Tpl(m)) => match m { Some(tpl::args::Cmd::Forward(id, headers, body)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; tpl::handlers::forward( &account_config, @@ -491,9 +476,9 @@ async fn main() -> Result<()> { return Ok(()); } Some(tpl::args::Cmd::Reply(id, all, headers, body)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; tpl::handlers::reply( &account_config, @@ -511,9 +496,9 @@ async fn main() -> Result<()> { return Ok(()); } Some(tpl::args::Cmd::Save(tpl)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; - let id_mapper = IdMapper::new(backend.as_ref(), &account_name, &folder)?; + let id_mapper = IdMapper::new(backend.as_ref(), &account_config, &folder)?; tpl::handlers::save( &account_config, @@ -528,7 +513,7 @@ async fn main() -> Result<()> { return Ok(()); } Some(tpl::args::Cmd::Send(tpl)) => { - let folder = account_config.folder_alias(folder.unwrap_or(DEFAULT_INBOX_FOLDER))?; + let folder = folder.unwrap_or(DEFAULT_INBOX_FOLDER); let mut backend = backend_builder.clone().into_build().await?; let mut sender = sender_builder.build().await?; tpl::handlers::send( diff --git a/src/ui/editor.rs b/src/ui/editor.rs index 39a3d08..f752fcd 100644 --- a/src/ui/editor.rs +++ b/src/ui/editor.rs @@ -102,7 +102,6 @@ pub async fn edit_tpl_with_editor( break; } Ok(PostEditChoice::RemoteDraft) => { - let draft_folder = config.folder_alias("drafts")?; let email = tpl .some_pgp_sign_cmd(config.email_writing_sign_cmd.clone()) .some_pgp_encrypt_cmd(config.email_writing_encrypt_cmd.clone()) @@ -111,13 +110,13 @@ pub async fn edit_tpl_with_editor( .write_to_vec()?; backend .add_email( - &draft_folder, + "drafts", &email, &Flags::from_iter([Flag::Seen, Flag::Draft]), ) .await?; remove_local_draft()?; - printer.print(format!("Email successfully saved to {}", draft_folder))?; + printer.print("Email successfully saved to drafts")?; break; } Ok(PostEditChoice::Discard) => {