diff options
author | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2022-09-02 13:07:15 +0300 |
---|---|---|
committer | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2022-09-02 15:17:30 +0300 |
commit | a484b397c68fd126c17073ac9c9f02432c413341 (patch) | |
tree | 159ae733673e495274af6fcd499db2a8de80f618 | |
parent | eb5949dc9bbcf05f86c58b3c93d1066204313e2a (diff) | |
download | meli-a484b397c68fd126c17073ac9c9f02432c413341.zip |
melib/notmuch: show informative error messages if libloading fails
Add instructions on how to solve this, and also a config setting
`library_file_path` to set the path manually if necessary.
-rw-r--r-- | docs/meli.conf.5 | 11 | ||||
-rw-r--r-- | melib/src/backends.rs | 70 | ||||
-rw-r--r-- | melib/src/backends/notmuch.rs | 35 |
3 files changed, 96 insertions, 20 deletions
diff --git a/docs/meli.conf.5 b/docs/meli.conf.5 index 87aa1641..cf2eca84 100644 --- a/docs/meli.conf.5 +++ b/docs/meli.conf.5 @@ -182,7 +182,11 @@ Its format is described below in \&. .El .Ss notmuch only -.Ic root_mailbox +notmuch is supported by loading the dynamic library libnotmuch. +If its location is missing from your library paths, you must add it yourself. +Alternatively, you can specify its path by using a setting. +.Bl -tag -width 36n +.It Ic root_mailbox points to the directory which contains the .Pa .notmuch/ subdirectory. @@ -192,10 +196,15 @@ You must explicitly state the mailboxes you want in the field and set the .Ar query property to each of them. +.It Ic library_file_path Ar Path +Use an arbitrary location of libnotmuch by specifying its full filesystem path. +.Pq Em optional +.El Example: .Bd -literal [accounts.notmuch] format = "notmuch" +#library_file_path = "/opt/homebrew/lib/libnotmuch.5.dylib" \&... [accounts.notmuch.mailboxes] "INBOX" = { query="tag:inbox", subscribe = true } diff --git a/melib/src/backends.rs b/melib/src/backends.rs index 94d8bc4a..4410cd7c 100644 --- a/melib/src/backends.rs +++ b/melib/src/backends.rs @@ -108,10 +108,45 @@ impl Default for Backends { #[cfg(feature = "notmuch_backend")] pub const NOTMUCH_ERROR_MSG: &str = - "libnotmuch5 was not found in your system. Make sure it is installed and in the library paths.\n"; + "libnotmuch5 was not found in your system. Make sure it is installed and in the library paths. For a custom file path, use `library_file_path` setting in your notmuch account.\n"; #[cfg(not(feature = "notmuch_backend"))] pub const NOTMUCH_ERROR_MSG: &str = "this version of meli is not compiled with notmuch support. Use an appropriate version and make sure libnotmuch5 is installed and in the library paths.\n"; +#[cfg(not(feature = "notmuch_backend"))] +pub const NOTMUCH_ERROR_DETAILS: &str = ""; + +#[cfg(all(feature = "notmuch_backend", target_os = "unix"))] +pub const NOTMUCH_ERROR_DETAILS: &str = r#"If you have installed the library manually, try setting the `LD_LIBRARY_PATH` environment variable to its `lib` directory. Otherwise, set it to the location of libnotmuch.5.so. Example: + +LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/path/to/notmuch/lib" meli + +or, put this in your shell init script (.bashenv, .zshenv, .bashrc, .zshrc, .profile): + +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/path/to/notmuch/lib" + +You can also set any location by specifying the library file path with the configuration flag `library_file_path`."#; + +#[cfg(all(feature = "notmuch_backend", target_os = "macos"))] +pub const NOTMUCH_ERROR_DETAILS: &str = r#"If you have installed the library via homebrew, try setting the `DYLD_LIBRARY_PATH` environment variable to its `lib` directory. Otherwise, set it to the location of libnotmuch.5.dylib. Example: + +DYLD_LIBRARY_PATH="$(brew --prefix)/lib" meli + +or, put this in your shell init script (.bashenv, .zshenv, .bashrc, .zshrc, .profile): + +export DYLD_LIBRARY_PATH="$(brew --prefix)/lib" + +Make sure to append to DYLD_LIBRARY_PATH if it's not empty, by prepending a colon to the libnotmuch5.dylib location: + +export DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:$(brew --prefix)/lib" + +You can also set any location by specifying the library file path with the configuration flag `library_file_path`."#; + +#[cfg(all( + feature = "notmuch_backend", + not(any(target_os = "unix", target_os = "macos")) +))] +pub const NOTMUCH_ERROR_DETAILS: &str = r#"If notmuch is installed but the library isn't found, consult your system's documentation on how to make dynamic libraries discoverable."#; + impl Backends { pub fn new() -> Self { let mut b = Backends { @@ -156,19 +191,13 @@ impl Backends { } #[cfg(feature = "notmuch_backend")] { - #[cfg(not(target_os = "macos"))] - let dlpath = "libnotmuch.so.5"; - #[cfg(target_os = "macos")] - let dlpath = "libnotmuch.5.dylib"; - if unsafe { libloading::Library::new(dlpath) }.is_ok() { - b.register( - "notmuch".to_string(), - Backend { - create_fn: Box::new(|| Box::new(|f, i, ev| NotmuchDb::new(f, i, ev))), - validate_conf_fn: Box::new(NotmuchDb::validate_config), - }, - ); - } + b.register( + "notmuch".to_string(), + Backend { + create_fn: Box::new(|| Box::new(|f, i, ev| NotmuchDb::new(f, i, ev))), + validate_conf_fn: Box::new(NotmuchDb::validate_config), + }, + ); } #[cfg(feature = "jmap_backend")] { @@ -187,6 +216,10 @@ impl Backends { if !self.map.contains_key(key) { if key == "notmuch" { eprint!("{}", NOTMUCH_ERROR_MSG); + #[cfg(feature = "notmuch_backend")] + { + eprint!("{}", NOTMUCH_ERROR_DETAILS); + } } panic!("{} is not a valid mail backend", key); } @@ -206,13 +239,18 @@ impl Backends { .get(key) .ok_or_else(|| { MeliError::new(format!( - "{}{} is not a valid mail backend", + "{}{} is not a valid mail backend. {}", if key == "notmuch" { NOTMUCH_ERROR_MSG } else { "" }, - key + key, + if cfg!(feature = "notmuch_backend") { + NOTMUCH_ERROR_DETAILS + } else { + "" + }, )) })? .validate_conf_fn)(s) diff --git a/melib/src/backends/notmuch.rs b/melib/src/backends/notmuch.rs index 1661cf8d..2c1b7ae0 100644 --- a/melib/src/backends/notmuch.rs +++ b/melib/src/backends/notmuch.rs @@ -310,10 +310,30 @@ impl NotmuchDb { event_consumer: BackendEventConsumer, ) -> Result<Box<dyn MailBackend>> { #[cfg(not(target_os = "macos"))] - let dlpath = "libnotmuch.so.5"; + let mut dlpath = "libnotmuch.so.5"; #[cfg(target_os = "macos")] - let dlpath = "libnotmuch.5.dylib"; - let lib = Arc::new(unsafe { libloading::Library::new(dlpath)? }); + let mut dlpath = "libnotmuch.5.dylib"; + let mut custom_dlpath = false; + if let Some(lib_path) = s.extra.get("library_file_path") { + dlpath = lib_path.as_str(); + custom_dlpath = true; + } + let lib = Arc::new(unsafe { + match libloading::Library::new(dlpath) { + Ok(l) => l, + Err(err) => { + if custom_dlpath { + return Err(MeliError::new(format!("Notmuch `library_file_path` setting value `{}` for account {} does not exist or is a directory or not a valid library file.",dlpath, s.name())) + .set_kind(ErrorKind::Configuration) + .set_source(Some(Arc::new(err)))); + } else { + return Err(MeliError::new("Could not load libnotmuch!") + .set_details(super::NOTMUCH_ERROR_DETAILS) + .set_source(Some(Arc::new(err)))); + } + } + } + }); let mut path = Path::new(s.root_mailbox.as_str()).expand(); if !path.exists() { return Err(MeliError::new(format!( @@ -423,6 +443,15 @@ impl NotmuchDb { path.pop(); let account_name = s.name().to_string(); + if let Some(lib_path) = s.extra.remove("library_file_path") { + if !Path::new(&lib_path).exists() || Path::new(&lib_path).is_dir() { + return Err(MeliError::new(format!( + "Notmuch `library_file_path` setting value `{}` for account {} does not exist or is a directory.", + &lib_path, + s.name() + )).set_kind(ErrorKind::Configuration)); + } + } for (k, f) in s.mailboxes.iter_mut() { if f.extra.remove("query").is_none() { return Err(MeliError::new(format!( |