summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2022-09-02 13:07:15 +0300
committerManos Pitsidianakis <el13635@mail.ntua.gr>2022-09-02 15:17:30 +0300
commita484b397c68fd126c17073ac9c9f02432c413341 (patch)
tree159ae733673e495274af6fcd499db2a8de80f618
parenteb5949dc9bbcf05f86c58b3c93d1066204313e2a (diff)
downloadmeli-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.511
-rw-r--r--melib/src/backends.rs70
-rw-r--r--melib/src/backends/notmuch.rs35
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!(