diff --git a/melib/src/backends/maildir.rs b/melib/src/backends/maildir.rs index e346bd90..6fbb8d10 100644 --- a/melib/src/backends/maildir.rs +++ b/melib/src/backends/maildir.rs @@ -27,6 +27,7 @@ use crate::backends::*; use crate::email::parser; use crate::email::{Envelope, Flag}; use crate::error::{MeliError, Result}; +use crate::shellexpand::ShellExpandTrait; use memmap::{Mmap, Protection}; use std::collections::hash_map::DefaultHasher; @@ -208,6 +209,7 @@ impl MaildirFolder { * mailboxes in user configuration */ let fname = if let Ok(fname) = pathbuf.strip_prefix( PathBuf::from(&settings.root_folder) + .expand() .parent() .unwrap_or_else(|| &Path::new("/")), ) { diff --git a/melib/src/backends/maildir/backend.rs b/melib/src/backends/maildir/backend.rs index e51eec32..ae6984f9 100644 --- a/melib/src/backends/maildir/backend.rs +++ b/melib/src/backends/maildir/backend.rs @@ -28,6 +28,7 @@ use crate::async_workers::*; use crate::conf::AccountSettings; use crate::email::{Envelope, EnvelopeHash, Flag}; use crate::error::{MeliError, Result}; +use crate::shellexpand::ShellExpandTrait; extern crate notify; use self::notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; @@ -583,7 +584,7 @@ impl MaildirType { } children }; - let root_path = PathBuf::from(settings.root_folder()); + let root_path = PathBuf::from(settings.root_folder()).expand(); if !root_path.exists() { eprintln!( "Configuration error ({}): root_path `{}` is not a valid directory.", @@ -651,7 +652,7 @@ impl MaildirType { name: settings.name().to_string(), folders, hash_indexes, - path: PathBuf::from(settings.root_folder()), + path: root_path, } } fn owned_folder_idx(&self, folder: &Folder) -> FolderHash { diff --git a/melib/src/backends/mbox.rs b/melib/src/backends/mbox.rs index 16368f5d..132db42a 100644 --- a/melib/src/backends/mbox.rs +++ b/melib/src/backends/mbox.rs @@ -33,6 +33,7 @@ use crate::conf::AccountSettings; use crate::email::parser::BytesExt; use crate::email::*; use crate::error::{MeliError, Result}; +use crate::shellexpand::ShellExpandTrait; use fnv::FnvHashMap; use libc; use memmap::{Mmap, Protection}; @@ -548,7 +549,7 @@ impl MailBackend for MboxType { impl MboxType { pub fn new(s: &AccountSettings, _is_subscribed: Box bool>) -> Self { - let path = Path::new(s.root_folder.as_str()); + let path = Path::new(s.root_folder.as_str()).expand(); if !path.exists() { panic!( "\"root_folder\" {} for account {} is not a valid path.", @@ -557,7 +558,7 @@ impl MboxType { ); } let ret = MboxType { - path: PathBuf::from(path), + path, ..Default::default() }; let name: String = ret @@ -565,12 +566,12 @@ impl MboxType { .file_name() .map(|f| f.to_string_lossy().into()) .unwrap_or(String::new()); - let hash = get_path_hash!(path); + let hash = get_path_hash!(&ret.path); ret.folders.lock().unwrap().insert( hash, MboxFolder { hash, - path: PathBuf::from(path), + path: ret.path.clone(), name, content: Vec::new(), children: Vec::new(), diff --git a/melib/src/lib.rs b/melib/src/lib.rs index 1a459469..38ebfce2 100644 --- a/melib/src/lib.rs +++ b/melib/src/lib.rs @@ -128,3 +128,47 @@ pub use crate::email::{Envelope, Flag}; pub use crate::error::{MeliError, Result}; pub use crate::addressbook::*; + +pub use shellexpand::ShellExpandTrait; +pub mod shellexpand { + + use std::path::*; + + pub trait ShellExpandTrait { + fn expand(&self) -> PathBuf; + } + + impl ShellExpandTrait for Path { + fn expand(&self) -> PathBuf { + let mut ret = PathBuf::new(); + for c in self.components() { + let c_to_str = c.as_os_str().to_str(); + match c_to_str { + Some("~") => { + if let Some(home_dir) = std::env::var("HOME").ok() { + ret.push(home_dir) + } else { + return PathBuf::new(); + } + } + Some(var) if var.starts_with("$") => { + let env_name = var.split_at(1).1; + if env_name.chars().all(char::is_uppercase) { + ret.push(std::env::var(env_name).unwrap_or(String::new())); + } else { + ret.push(c); + } + } + Some(_) => { + ret.push(c); + } + None => { + /* path is invalid */ + return PathBuf::new(); + } + } + } + ret + } + } +}