Replace old logging module with the `log` create

pull/211/head
Manos Pitsidianakis 1 year ago
parent 30cc5d3d02
commit 85d4316a6a
No known key found for this signature in database
GPG Key ID: 7729C7707F7E09D0

1
Cargo.lock generated

@ -1178,6 +1178,7 @@ dependencies = [
"isahc", "isahc",
"libc", "libc",
"libloading", "libloading",
"log",
"mailin-embedded", "mailin-embedded",
"native-tls", "native-tls",
"nix", "nix",

@ -1448,8 +1448,6 @@ Available levels are, in partial order:
.It .It
.Em OFF .Em OFF
.It .It
.Em FATAL
.It
.Em ERROR .Em ERROR
.It .It
.Em WARN .Em WARN

@ -20,6 +20,7 @@ name = "melib"
path = "src/lib.rs" path = "src/lib.rs"
[dependencies] [dependencies]
log = { version = "0.4", features = ["std"]}
async-stream = "^0.3" async-stream = "^0.3"
base64 = { version = "^0.13", optional = true } base64 = { version = "^0.13", optional = true }
bincode = { version = "^1.3.0", default-features = false } bincode = { version = "^1.3.0", default-features = false }

@ -120,12 +120,10 @@ impl AddressBook {
} }
} }
Err(err) => { Err(err) => {
crate::log( log::warn!(
format!( "Could not load mutt alias file {:?}: {}",
"Could not load mutt alias file {:?}: {}", mutt_alias_file,
mutt_alias_file, err err
),
crate::WARN,
); );
} }
} }
@ -139,10 +137,7 @@ impl AddressBook {
} }
} }
Err(err) => { Err(err) => {
crate::log( log::warn!("Could not load vcards from {:?}: {}", vcard_path, err);
format!("Could not load vcards from {:?}: {}", vcard_path, err),
crate::WARN,
);
} }
} }
} }

@ -305,10 +305,7 @@ pub fn load_cards(p: &std::path::Path) -> Result<Vec<Card>> {
} }
} }
Err(err) => { Err(err) => {
crate::log( log::warn!("Could not parse vcard from {}: {}", f.display(), err);
format!("Could not parse vcard from {}: {}", f.display(), err),
crate::WARN,
);
} }
} }
} }

@ -62,6 +62,7 @@ use super::email::{Envelope, EnvelopeHash, Flag};
use crate::{ use crate::{
conf::AccountSettings, conf::AccountSettings,
error::{Error, ErrorKind, Result}, error::{Error, ErrorKind, Result},
LogLevel,
}; };
#[macro_export] #[macro_export]
@ -261,7 +262,7 @@ pub enum BackendEvent {
Notice { Notice {
description: String, description: String,
content: Option<String>, content: Option<String>,
level: crate::LoggingLevel, level: LogLevel,
}, },
Refresh(RefreshEvent), Refresh(RefreshEvent),
AccountStateChange { AccountStateChange {
@ -275,7 +276,7 @@ impl From<Error> for BackendEvent {
BackendEvent::Notice { BackendEvent::Notice {
description: val.summary.to_string(), description: val.summary.to_string(),
content: Some(val.to_string()), content: Some(val.to_string()),
level: crate::LoggingLevel::ERROR, level: LogLevel::ERROR,
} }
} }
} }

@ -753,13 +753,10 @@ impl MailBackend for ImapType {
cmd.push_str("\\Draft "); cmd.push_str("\\Draft ");
} }
Ok(_) => { Ok(_) => {
crate::log( log::error!(
format!( "Application error: more than one flag bit set in set_flags: \
"Application error: more than one flag bit set in \ {:?}",
set_flags: {:?}", flags
flags
),
crate::ERROR,
); );
return Err(Error::new(format!( return Err(Error::new(format!(
"Application error: more than one flag bit set in set_flags: \ "Application error: more than one flag bit set in set_flags: \
@ -826,13 +823,10 @@ impl MailBackend for ImapType {
cmd.push_str("\\Draft "); cmd.push_str("\\Draft ");
} }
Ok(_) => { Ok(_) => {
crate::log( log::error!(
format!( "Application error: more than one flag bit set in set_flags: \
"Application error: more than one flag bit set in \ {:?}",
set_flags: {:?}", flags
flags
),
crate::ERROR,
); );
return Err(Error::new(format!( return Err(Error::new(format!(
"Application error: more than one flag bit set in set_flags: \ "Application error: more than one flag bit set in set_flags: \
@ -1716,23 +1710,18 @@ async fn fetch_hlpr(state: &mut FetchState) -> Result<Vec<Envelope>> {
FetchStage::InitialCache => { FetchStage::InitialCache => {
match cache::fetch_cached_envs(state).await { match cache::fetch_cached_envs(state).await {
Err(err) => { Err(err) => {
crate::log( log::error!(
format!( "IMAP cache error: could not fetch cache for {}. Reason: {}",
"IMAP cache error: could not fetch cache for {}. Reason: {}", state.uid_store.account_name,
state.uid_store.account_name, err err
),
crate::ERROR,
); );
/* Try resetting the database */ /* Try resetting the database */
if let Some(ref mut cache_handle) = state.cache_handle { if let Some(ref mut cache_handle) = state.cache_handle {
if let Err(err) = cache_handle.reset() { if let Err(err) = cache_handle.reset() {
crate::log( log::error!(
format!( "IMAP cache error: could not reset cache for {}. Reason: {}",
"IMAP cache error: could not reset cache for {}. Reason: \ state.uid_store.account_name,
{}", err
state.uid_store.account_name, err
),
crate::ERROR,
); );
} }
} }

@ -25,6 +25,7 @@ use crate::{
connections::{lookup_ipv4, timeout, Connection}, connections::{lookup_ipv4, timeout, Connection},
email::parser::BytesExt, email::parser::BytesExt,
error::*, error::*,
LogLevel,
}; };
extern crate native_tls; extern crate native_tls;
use std::{ use std::{
@ -260,10 +261,7 @@ impl ImapStream {
.get_ref() .get_ref()
.set_keepalive(Some(Duration::new(60 * 9, 0))) .set_keepalive(Some(Duration::new(60 * 9, 0)))
{ {
crate::log( log::warn!("Could not set TCP keepalive in IMAP connection: {}", err);
format!("Could not set TCP keepalive in IMAP connection: {}", err),
crate::LoggingLevel::WARN,
);
} }
let mut res = Vec::with_capacity(8 * 1024); let mut res = Vec::with_capacity(8 * 1024);
let mut ret = ImapStream { let mut ret = ImapStream {
@ -658,13 +656,11 @@ impl ImapConnection {
| ImapResponse::Bad(code) | ImapResponse::Bad(code)
| ImapResponse::Preauth(code) | ImapResponse::Preauth(code)
| ImapResponse::Bye(code) => { | ImapResponse::Bye(code) => {
crate::log( log::warn!(
format!( "Could not use COMPRESS=DEFLATE in account `{}`: server \
"Could not use COMPRESS=DEFLATE in account `{}`: server \ replied with `{}`",
replied with `{}`", self.uid_store.account_name,
self.uid_store.account_name, code code
),
crate::LoggingLevel::WARN,
); );
} }
ImapResponse::Ok(_) => { ImapResponse::Ok(_) => {
@ -737,7 +733,7 @@ impl ImapConnection {
crate::backends::BackendEvent::Notice { crate::backends::BackendEvent::Notice {
description: response_code.to_string(), description: response_code.to_string(),
content: None, content: None,
level: crate::logging::LoggingLevel::ERROR, level: LogLevel::ERROR,
}, },
); );
ret.extend_from_slice(&response); ret.extend_from_slice(&response);
@ -754,7 +750,7 @@ impl ImapConnection {
crate::backends::BackendEvent::Notice { crate::backends::BackendEvent::Notice {
description: response_code.to_string(), description: response_code.to_string(),
content: None, content: None,
level: crate::logging::LoggingLevel::ERROR, level: LogLevel::ERROR,
}, },
); );
ret.extend_from_slice(&response); ret.extend_from_slice(&response);

@ -287,7 +287,7 @@ impl ImapConnection {
) )
}) })
{ {
crate::log(err.to_string(), crate::INFO); log::info!("{err}");
} }
} }
for response in v { for response in v {
@ -391,7 +391,7 @@ impl ImapConnection {
) )
}) })
{ {
crate::log(err.to_string(), crate::INFO); log::info!("{err}");
} }
} }
for response in v { for response in v {

@ -24,6 +24,7 @@ use crate::{
connections::{lookup_ipv4, Connection}, connections::{lookup_ipv4, Connection},
email::parser::BytesExt, email::parser::BytesExt,
error::*, error::*,
log,
}; };
extern crate native_tls; extern crate native_tls;
use std::{collections::HashSet, future::Future, pin::Pin, sync::Arc, time::Instant}; use std::{collections::HashSet, future::Future, pin::Pin, sync::Arc, time::Instant};
@ -199,10 +200,7 @@ impl NntpStream {
.get_ref() .get_ref()
.set_keepalive(Some(std::time::Duration::new(60 * 9, 0))) .set_keepalive(Some(std::time::Duration::new(60 * 9, 0)))
{ {
crate::log( log::warn!("Could not set TCP keepalive in NNTP connection: {}", err);
format!("Could not set TCP keepalive in NNTP connection: {}", err),
crate::LoggingLevel::WARN,
);
} }
ret.read_response(&mut res, false, &["200 ", "201 "]) ret.read_response(&mut res, false, &["200 ", "201 "])

@ -43,41 +43,20 @@
//! - A `ShellExpandTrait` to expand paths like a shell. //! - A `ShellExpandTrait` to expand paths like a shell.
//! - A `debug` macro that works like `std::dbg` but for multiple threads. (see //! - A `debug` macro that works like `std::dbg` but for multiple threads. (see
//! [`debug` macro](./macro.debug.html)) //! [`debug` macro](./macro.debug.html))
#[macro_use] #[macro_use]
pub mod dbg { pub mod dbg {
#[macro_export]
macro_rules! log_tag {
() => {
eprint!(
"[{}][{:?}] {}:{}_{}: ",
$crate::datetime::timestamp_to_string(
$crate::datetime::now(),
Some("%Y-%m-%d %T"),
false
),
std::thread::current()
.name()
.map(std::string::ToString::to_string)
.unwrap_or_else(|| format!("{:?}", std::thread::current().id())),
file!(),
line!(),
column!()
);
};
}
#[allow(clippy::redundant_closure)] #[allow(clippy::redundant_closure)]
#[macro_export] #[macro_export]
macro_rules! debug { macro_rules! debug {
($val:literal) => { ($val:literal) => {
{ {
if cfg!(feature="debug-tracing") { if cfg!(feature="debug-tracing") {
log_tag!(); $crate::log::debug!($val);
eprintln!($val); }
$val
} }
$val
}
}; };
($val:expr) => { ($val:expr) => {
if cfg!(feature="debug-tracing") { if cfg!(feature="debug-tracing") {
@ -86,8 +65,7 @@ pub mod dbg {
// of temporaries - https://stackoverflow.com/a/48732525/1063961 // of temporaries - https://stackoverflow.com/a/48732525/1063961
match $val { match $val {
tmp => { tmp => {
log_tag!(); $crate::log::debug!("{} = {:?}", stringify, tmp);
eprintln!("{} = {:?}", stringify, tmp);
tmp tmp
} }
} }
@ -97,8 +75,7 @@ pub mod dbg {
}; };
($fmt:literal, $($arg:tt)*) => { ($fmt:literal, $($arg:tt)*) => {
if cfg!(feature="debug-tracing") { if cfg!(feature="debug-tracing") {
log_tag!(); $crate::log::debug!($fmt, $($arg)*);
eprintln!($fmt, $($arg)*);
} }
}; };
} }
@ -112,7 +89,7 @@ pub use datetime::UnixTimestamp;
#[macro_use] #[macro_use]
mod logging; mod logging;
pub use self::logging::{LoggingLevel::*, *}; pub use self::logging::{LogLevel, StderrLogger};
pub mod addressbook; pub mod addressbook;
pub use addressbook::*; pub use addressbook::*;
@ -142,6 +119,7 @@ pub mod sqlite3;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
pub extern crate log;
/* parser */ /* parser */
extern crate data_encoding; extern crate data_encoding;
extern crate encoding; extern crate encoding;

@ -23,30 +23,98 @@ use std::{
fs::OpenOptions, fs::OpenOptions,
io::{BufWriter, Write}, io::{BufWriter, Write},
path::PathBuf, path::PathBuf,
sync::{Arc, Mutex}, sync::{
atomic::{AtomicU8, Ordering},
Arc, Mutex,
},
}; };
use log::{Level, LevelFilter, Log, Metadata, Record};
use crate::shellexpand::ShellExpandTrait; use crate::shellexpand::ShellExpandTrait;
#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Debug, Serialize, Deserialize)] #[derive(Copy, Clone, Default, PartialEq, PartialOrd, Hash, Debug, Serialize, Deserialize)]
pub enum LoggingLevel { #[repr(u8)]
OFF, pub enum LogLevel {
FATAL, OFF = 0,
ERROR, ERROR,
WARN, WARN,
#[default]
INFO, INFO,
DEBUG, DEBUG,
TRACE, TRACE,
} }
impl std::fmt::Display for LoggingLevel { impl From<u8> for LogLevel {
fn from(verbosity: u8) -> Self {
match verbosity {
0 => LogLevel::OFF,
1 => LogLevel::ERROR,
2 => LogLevel::WARN,
3 => LogLevel::INFO,
4 => LogLevel::DEBUG,
_ => LogLevel::TRACE,
}
}
}
impl From<Level> for LogLevel {
fn from(l: Level) -> Self {
match l {
Level::Error => Self::ERROR,
Level::Warn => Self::WARN,
Level::Info => Self::INFO,
Level::Debug => Self::DEBUG,
Level::Trace => Self::TRACE,
}
}
}
impl From<LogLevel> for Level {
fn from(l: LogLevel) -> Self {
match l {
LogLevel::ERROR => Self::Error,
LogLevel::WARN => Self::Warn,
LogLevel::OFF | LogLevel::INFO => Self::Info,
LogLevel::DEBUG => Self::Debug,
LogLevel::TRACE => Self::Trace,
}
}
}
impl From<LevelFilter> for LogLevel {
fn from(l: LevelFilter) -> Self {
match l {
LevelFilter::Off => Self::OFF,
LevelFilter::Error => Self::ERROR,
LevelFilter::Warn => Self::WARN,
LevelFilter::Info => Self::INFO,
LevelFilter::Debug => Self::DEBUG,
LevelFilter::Trace => Self::TRACE,
}
}
}
impl From<LogLevel> for LevelFilter {
fn from(l: LogLevel) -> Self {
match l {
LogLevel::OFF => Self::Off,
LogLevel::ERROR => Self::Error,
LogLevel::WARN => Self::Warn,
LogLevel::INFO => Self::Info,
LogLevel::DEBUG => Self::Debug,
LogLevel::TRACE => Self::Trace,
}
}
}
impl std::fmt::Display for LogLevel {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!( write!(
f, f,
"{}", "{}",
match self { match self {
OFF => "OFF", OFF => "OFF",
FATAL => "FATAL",
ERROR => "ERROR", ERROR => "ERROR",
WARN => "WARN", WARN => "WARN",
INFO => "INFO", INFO => "INFO",
@ -57,73 +125,173 @@ impl std::fmt::Display for LoggingLevel {
} }
} }
impl Default for LoggingLevel { use LogLevel::*;
#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Hash, Debug, Serialize, Deserialize)]
pub enum Destination {
File,
#[default]
Stderr,
None,
}
#[derive(Clone)]
pub struct StderrLogger {
dest: Arc<Mutex<BufWriter<std::fs::File>>>,
level: Arc<AtomicU8>,
print_level: bool,
print_module_names: bool,
debug_dest: Destination,
}
impl std::fmt::Debug for StderrLogger {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct(stringify!(StderrLogger))
.field("level", &LogLevel::from(self.level.load(Ordering::SeqCst)))
.field("print_level", &self.print_level)
.field("print_module_names", &self.print_module_names)
.field("debug_dest", &self.debug_dest)
.finish()
}
}
impl Default for StderrLogger {
fn default() -> Self { fn default() -> Self {
LoggingLevel::INFO Self::new(LogLevel::default())
} }
} }
use LoggingLevel::*; impl StderrLogger {
pub fn new(level: LogLevel) -> Self {
let logger = {
let data_dir = xdg::BaseDirectories::with_prefix("meli").unwrap();
let log_file = OpenOptions::new().append(true) /* writes will append to a file instead of overwriting previous contents */
.create(true) /* a new file will be created if the file does not yet already exist.*/
.read(true)
.open(data_dir.place_data_file("meli.log").unwrap()).unwrap();
StderrLogger {
dest: Arc::new(Mutex::new(BufWriter::new(log_file).into())),
level: Arc::new(AtomicU8::new(level as u8)),
print_level: true,
print_module_names: true,
#[cfg(feature = "debug-tracing")]
debug_dest: Destination::Stderr,
#[cfg(not(feature = "debug-tracing"))]
debug_dest: Destination::None,
}
};
#[cfg(feature = "debug-tracing")]
log::set_max_level(
if matches!(LevelFilter::from(logger.log_level()), LevelFilter::Off) {
LevelFilter::Off
} else {
LevelFilter::Trace
},
);
#[cfg(not(feature = "debug-tracing"))]
log::set_max_level(LevelFilter::from(logger.log_level()));
log::set_boxed_logger(Box::new(logger.clone())).unwrap();
logger
}
struct LoggingBackend { pub fn log_level(&self) -> LogLevel {
dest: BufWriter<std::fs::File>, self.level.load(Ordering::SeqCst).into()
level: LoggingLevel, }
pub fn change_log_dest(&mut self, path: PathBuf) {
let path = path.expand(); // expand shell stuff
let mut dest = self.dest.lock().unwrap();
*dest = BufWriter::new(OpenOptions::new().append(true) /* writes will append to a file instead of overwriting previous contents */
.create(true) /* a new file will be created if the file does not yet already exist.*/
.read(true)
.open(path).unwrap()).into();
}
} }
thread_local!(static LOG: Arc<Mutex<LoggingBackend>> = Arc::new(Mutex::new({ impl Log for StderrLogger {
let data_dir = xdg::BaseDirectories::with_prefix("meli").unwrap(); fn enabled(&self, metadata: &Metadata) -> bool {
let log_file = OpenOptions::new().append(true) /* writes will append to a file instead of overwriting previous contents */ !["polling", "async_io"]
.create(true) /* a new file will be created if the file does not yet already exist.*/ .iter()
.read(true) .any(|t| metadata.target().starts_with(t))
.open(data_dir.place_data_file("meli.log").unwrap()).unwrap(); && (metadata.level() <= Level::from(self.log_level())
LoggingBackend { || !matches!(self.debug_dest, Destination::None))
dest: BufWriter::new(log_file), //metadata.level() <= self.log_level_filter() &&
level: LoggingLevel::default(), // self.includes_module(metadata.target())
}})) }
);
fn log(&self, record: &Record) {
pub fn log<S: AsRef<str>>(val: S, level: LoggingLevel) { if !self.enabled(record.metadata()) {
LOG.with(|f| { return;
let mut b = f.lock().unwrap(); }
if level <= b.level {
b.dest fn write(
writer: &mut impl Write,
record: &Record,
(print_level, print_module_names): (bool, bool),
) -> Option<()> {
writer
.write_all( .write_all(
crate::datetime::timestamp_to_string(crate::datetime::now(), None, false) crate::datetime::timestamp_to_string(crate::datetime::now(), None, false)
.as_bytes(), .as_bytes(),
) )
.unwrap(); .ok()?;
b.dest.write_all(b" [").unwrap(); writer.write_all(b" [").ok()?;
b.dest.write_all(level.to_string().as_bytes()).unwrap(); if print_level {
b.dest.write_all(b"]: ").unwrap(); writer
b.dest.write_all(val.as_ref().as_bytes()).unwrap(); .write_all(record.level().to_string().as_bytes())
b.dest.write_all(b"\n").unwrap(); .ok()?;
b.dest.flush().unwrap(); }
write!(writer, "]: ").ok()?;
if print_module_names {
write!(writer, "{}: ", record.metadata().target()).ok()?;
}
write!(writer, "{}", record.args()).ok()?;
writer.write_all(b"\n").ok()?;
writer.flush().ok()?;
Some(())
} }
});
}
pub fn get_log_level() -> LoggingLevel {
let mut level = INFO;
LOG.with(|f| {
level = f.lock().unwrap().level;
});
level
}
pub fn change_log_dest(path: PathBuf) { // if logging isn't enabled for this level do a quick out
LOG.with(|f| { match (
let path = path.expand(); // expand shell stuff self.debug_dest,
let mut backend = f.lock().unwrap(); record.metadata().level() <= Level::from(self.log_level()),
backend.dest = BufWriter::new(OpenOptions::new().append(true) /* writes will append to a file instead of overwriting previous contents */ ) {
.create(true) /* a new file will be created if the file does not yet already exist.*/ (Destination::None, false) => return,
.read(true) (Destination::None | Destination::File, _) => {
.open(path).unwrap()); _ = self.dest.lock().ok().and_then(|mut d| {
}); write(
} &mut (*d),
record,
(self.print_level, self.print_module_names),
)
});
}
(Destination::Stderr, true) => {
_ = self.dest.lock().ok().and_then(|mut d| {
write(
&mut (*d),
record,
(self.print_level, self.print_module_names),
)
});
_ = write(
&mut std::io::stderr(),
record,
(self.print_level, self.print_module_names),
);
}
(Destination::Stderr, false) => {
_ = write(
&mut std::io::stderr(),
record,
(self.print_level, self.print_module_names),
);
}
}
}
pub fn change_log_level(new_val: LoggingLevel) { fn flush(&self) {
LOG.with(|f| { self.dest.lock().ok().and_then(|mut w| w.flush().ok());
let mut backend = f.lock().unwrap(); }
backend.level = new_val;
});
} }

@ -24,7 +24,7 @@ use std::path::PathBuf;
use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput}; use rusqlite::types::{FromSql, FromSqlError, FromSqlResult, ToSql, ToSqlOutput};
pub use rusqlite::{self, params, Connection}; pub use rusqlite::{self, params, Connection};
use crate::{error::*, logging::log, Envelope}; use crate::{error::*, log, Envelope};
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct DatabaseDescription { pub struct DatabaseDescription {
@ -61,13 +61,10 @@ pub fn open_or_create_db(
}?; }?;
let mut set_mode = false; let mut set_mode = false;
if !db_path.exists() { if !db_path.exists() {
log( log::info!(
format!( "Creating {} database in {}",
"Creating {} database in {}", description.name,
description.name, db_path.display()
db_path.display()
),
crate::INFO,
); );
set_mode = true; set_mode = true;
} }
@ -83,12 +80,10 @@ pub fn open_or_create_db(
} }
let version: i32 = conn.pragma_query_value(None, "user_version", |row| row.get(0))?; let version: i32 = conn.pragma_query_value(None, "user_version", |row| row.get(0))?;
if version != 0_i32 && version as u32 != description.version { if version != 0_i32 && version as u32 != description.version {
log( log::info!(
format!( "Database version mismatch, is {} but expected {}",
"Database version mismatch, is {} but expected {}", version,
version, description.version description.version
),
crate::INFO,
); );
if second_try { if second_try {
return Err(Error::new(format!( return Err(Error::new(format!(
@ -124,13 +119,10 @@ pub fn reset_db(description: &DatabaseDescription, identifier: Option<&str>) ->
if !db_path.exists() { if !db_path.exists() {
return Ok(()); return Ok(());
} }
log( log::info!(
format!( "Resetting {} database in {}",
"Resetting {} database in {}", description.name,
description.name, db_path.display()
db_path.display()
),
crate::INFO,
); );
std::fs::remove_file(&db_path)?; std::fs::remove_file(&db_path)?;
Ok(()) Ok(())

@ -1748,12 +1748,9 @@ impl Component for Composer {
} }
let editor_command = format!("{} {}", editor, f.path().display()); let editor_command = format!("{} {}", editor, f.path().display());
log( log::debug!(
format!( "Executing: sh -c \"{}\"",
"Executing: sh -c \"{}\"", editor_command.replace('"', "\\\"")
editor_command.replace('"', "\\\"")
),
DEBUG,
); );
match Command::new("sh") match Command::new("sh")
.args(["-c", &editor_command]) .args(["-c", &editor_command])
@ -1893,10 +1890,7 @@ impl Component for Composer {
context.input_kill(); context.input_kill();
} }
log( log::debug!("Executing: sh -c \"{}\"", command.replace('"', "\\\""));
format!("Executing: sh -c \"{}\"", command.replace('"', "\\\"")),
DEBUG,
);
match Command::new("sh") match Command::new("sh")
.args(["-c", command]) .args(["-c", command])
.stdin(Stdio::inherit()) .stdin(Stdio::inherit())
@ -2170,13 +2164,9 @@ pub fn send_draft(
match output { match output {
Err(err) => { Err(err) => {
debug!("{:?} could not sign draft msg", err); debug!("{:?} could not sign draft msg", err);
log( log::error!(
format!( "Could not sign draft in account `{}`: {err}.",
"Could not sign draft in account `{}`: {}.",
context.accounts[&account_hash].name(), context.accounts[&account_hash].name(),
err.to_string()
),
ERROR,
); );
context.replies.push_back(UIEvent::Notification( context.replies.push_back(UIEvent::Notification(
Some(format!( Some(format!(
@ -2358,12 +2348,9 @@ pub fn send_draft_async(
.unwrap(); .unwrap();
} else if !store_sent_mail && is_ok { } else if !store_sent_mail && is_ok {
let f = create_temp_file(message.as_bytes(), None, None, false); let f = create_temp_file(message.as_bytes(), None, None, false);
log( log::info!(
format!( "store_sent_mail is false; stored sent mail to {}",
"store_sent_mail is false; stored sent mail to {}", f.path().display()
f.path().display()
),
INFO,
); );
} }
ret ret

@ -557,7 +557,7 @@ pub trait MailListingTrait: ListingTrait {
name: "message copying".into(), name: "message copying".into(),
handle, handle,
on_finish: None, on_finish: None,
logging_level: melib::LoggingLevel::INFO, log_level: LogLevel::INFO,
}, },
); );
} }
@ -594,7 +594,7 @@ pub trait MailListingTrait: ListingTrait {
name: "message moving".into(), name: "message moving".into(),
handle, handle,
on_finish: None, on_finish: None,
logging_level: melib::LoggingLevel::INFO, log_level: LogLevel::INFO,
}, },
); );
} }
@ -692,7 +692,7 @@ pub trait MailListingTrait: ListingTrait {
), ),
}); });
}))), }))),
logging_level: melib::LoggingLevel::INFO, log_level: LogLevel::INFO,
}, },
); );
} }

@ -1426,7 +1426,7 @@ impl CompactListing {
"Encountered an error while searching for `{}`: {}.", "Encountered an error while searching for `{}`: {}.",
search_term, &err search_term, &err
); );
log(message.clone(), ERROR); log::error!("{}", message);
context.replies.push_back(UIEvent::Notification( context.replies.push_back(UIEvent::Notification(
Some("Could not perform search".to_string()), Some("Could not perform search".to_string()),
message, message,

@ -1501,7 +1501,7 @@ impl Component for MailView {
err.to_string(), err.to_string(),
Some(NotificationType::Error(err.kind)), Some(NotificationType::Error(err.kind)),
)); ));
log(format!("Failed to open envelope: {}", err), ERROR); log::error!("Failed to open envelope: {err}");
self.init_futures(context); self.init_futures(context);
return; return;
} else { } else {
@ -2140,7 +2140,7 @@ impl Component for MailView {
.unwrap_or_else(|| "Not found".into()), .unwrap_or_else(|| "Not found".into()),
err err
); );
log(&err_string, ERROR); log::error!("{err_string}");
context.replies.push_back(UIEvent::Notification( context.replies.push_back(UIEvent::Notification(
Some("Failed to open e-mail".to_string()), Some("Failed to open e-mail".to_string()),
err_string, err_string,
@ -2151,7 +2151,7 @@ impl Component for MailView {
} }
} }
}))), }))),
logging_level: melib::LoggingLevel::DEBUG, log_level: LogLevel::DEBUG,
}, },
); );
return true; return true;
@ -2503,7 +2503,7 @@ impl Component for MailView {
err.to_string(), err.to_string(),
Some(NotificationType::Error(err.kind)), Some(NotificationType::Error(err.kind)),
)); ));
log(format!("Failed to open envelope: {}", err), ERROR); log::error!("Failed to open envelope: {err}");
self.init_futures(context); self.init_futures(context);
return true; return true;
} else { } else {
@ -2523,10 +2523,7 @@ impl Component for MailView {
err.to_string(), err.to_string(),
Some(NotificationType::Error(melib::ErrorKind::External)), Some(NotificationType::Error(melib::ErrorKind::External)),
)); ));
log( log::error!("Failed to create file at {}: {err}", path.display());
format!("Failed to create file at {}: {}", path.display(), err),
ERROR,
);
return true; return true;
} }
Ok(()) => { Ok(()) => {
@ -2557,7 +2554,7 @@ impl Component for MailView {
err.to_string(), err.to_string(),
Some(NotificationType::Error(err.kind)), Some(NotificationType::Error(err.kind)),
)); ));
log(format!("Failed to open envelope: {}", err), ERROR); log::error!("Failed to open envelope: {err}");
self.init_futures(context); self.init_futures(context);
return true; return true;
} else { } else {
@ -2582,10 +2579,7 @@ impl Component for MailView {
err.to_string(), err.to_string(),
Some(NotificationType::Error(melib::ErrorKind::External)), Some(NotificationType::Error(melib::ErrorKind::External)),
)); ));
log( log::error!("Failed to create file at {}: {err}", path.display());
format!("Failed to create file at {}: {}", path.display(), err),
ERROR,
);
} }
Ok(()) => { Ok(()) => {
context.replies.push_back(UIEvent::Notification( context.replies.push_back(UIEvent::Notification(
@ -2609,10 +2603,7 @@ impl Component for MailView {
err.to_string(), err.to_string(),
Some(NotificationType::Error(melib::ErrorKind::External)), Some(NotificationType::Error(melib::ErrorKind::External)),
)); ));
log( log::error!("Failed to create file at {}: {err}", path.display());
format!("Failed to create file at {}: {}", path.display(), err),
ERROR,
);
return true; return true;
} }
Ok(()) => { Ok(()) => {

@ -100,6 +100,7 @@ impl ThreadView {
view.new_cursor_pos = view.new_expanded_pos; view.new_cursor_pos = view.new_expanded_pos;
view view
} }
pub fn update(&mut self, context: &Context) { pub fn update(&mut self, context: &Context) {
if self.entries.is_empty() { if self.entries.is_empty() {
return; return;
@ -439,7 +440,6 @@ impl ThreadView {
copy_area(grid, &self.content, dest_area, src_area); copy_area(grid, &self.content, dest_area, src_area);
} }
/// draw the list
fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { fn draw_list(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
let (upper_left, bottom_right) = area; let (upper_left, bottom_right) = area;
let (width, height) = self.content.size(); let (width, height) = self.content.size();
@ -492,8 +492,7 @@ impl ThreadView {
let page_no = (self.new_cursor_pos).wrapping_div(rows); let page_no = (self.new_cursor_pos).wrapping_div(rows);
let top_idx = page_no * rows; let top_idx = page_no * rows;
/* This closure (written for code clarity, should be inlined by the compiler) /* returns the **line** of an entry in the ThreadView grid. */
* returns the **line** of an entry in the ThreadView grid. */
let get_entry_area = |idx: usize, entries: &[ThreadEntry]| { let get_entry_area = |idx: usize, entries: &[ThreadEntry]| {
let entries = &entries; let entries = &entries;
let visual_indentation = entries[idx].index.0 * 4; let visual_indentation = entries[idx].index.0 * 4;
@ -991,6 +990,7 @@ impl Component for ThreadView {
} }
self.dirty = false; self.dirty = false;
} }
fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool {
if let UIEvent::Action(Listing(OpenInNewTab)) = event { if let UIEvent::Action(Listing(OpenInNewTab)) = event {
/* Handle this before self.mailview does */ /* Handle this before self.mailview does */

@ -117,11 +117,8 @@ mod dbus {
} }
if let Err(err) = notification.show() { if let Err(err) = notification.show() {
debug!("Could not show dbus notification: {:?}", &err); log::debug!("Could not show dbus notification: {:?}", &err);
melib::log( log::error!("Could not show dbus notification: {err}");
format!("Could not show dbus notification: {}", err),
melib::ERROR,
);
} }
} }
false false
@ -194,8 +191,8 @@ impl Component for NotificationCommand {
if *kind == Some(NotificationType::NewMail) { if *kind == Some(NotificationType::NewMail) {
if let Some(ref path) = context.settings.notifications.xbiff_file_path { if let Some(ref path) = context.settings.notifications.xbiff_file_path {
if let Err(err) = update_xbiff(path) { if let Err(err) = update_xbiff(path) {
debug!("Could not update xbiff file: {:?}", &err); log::debug!("Could not update xbiff file: {:?}", &err);
melib::log(format!("Could not update xbiff file: {}.", err), ERROR); log::error!("Could not update xbiff file: {err}.");
} }
} }
} }
@ -220,11 +217,8 @@ impl Component for NotificationCommand {
context.children.push(child); context.children.push(child);
} }
Err(err) => { Err(err) => {
log( log::error!("Could not run notification script: {err}.");
format!("Could not run notification script: {}.", err), log::debug!("Could not run notification script: {:?}", err);
ERROR,
);
debug!("Could not run notification script: {:?}", err);
} }
} }
} else { } else {
@ -256,11 +250,8 @@ impl Component for NotificationCommand {
return false; return false;
} }
Err(err) => { Err(err) => {
log( log::error!("Could not run notification script: {err}.");
format!("Could not run notification script: {}.", err), log::debug!("Could not run notification script: {:?}", err);
ERROR,
);
debug!("Could not run notification script: {:?}", err);
} }
} }
} }

@ -32,7 +32,7 @@ use std::{
process::{Command, Stdio}, process::{Command, Stdio},
}; };
use melib::{backends::TagHash, search::Query}; use melib::{backends::TagHash, search::Query, StderrLogger};
use crate::{conf::deserializers::non_empty_string, terminal::Color}; use crate::{conf::deserializers::non_empty_string, terminal::Color};
@ -610,6 +610,8 @@ pub struct Settings {
pub pgp: PGPSettings, pub pgp: PGPSettings,
pub terminal: TerminalSettings, pub terminal: TerminalSettings,
pub log: LogSettings, pub log: LogSettings,
#[serde(skip)]
_logger: StderrLogger,
} }
impl Settings { impl Settings {
@ -624,11 +626,10 @@ impl Settings {
s.insert(id, ac); s.insert(id, ac);
} }
let mut _logger = StderrLogger::new(fs.log.maximum_level);
if let Some(ref log_path) = fs.log.log_file { if let Some(ref log_path) = fs.log.log_file {
melib::change_log_dest(log_path.into()); _logger.change_log_dest(log_path.into());
}
if fs.log.maximum_level != melib::LoggingLevel::default() {
melib::change_log_level(fs.log.maximum_level);
} }
Ok(Settings { Ok(Settings {
@ -642,16 +643,16 @@ impl Settings {
pgp: fs.pgp, pgp: fs.pgp,
terminal: fs.terminal, terminal: fs.terminal,
log: fs.log, log: fs.log,
_logger,
}) })
} }
pub fn without_accounts() -> Result<Settings> { pub fn without_accounts() -> Result<Settings> {
let fs = FileSettings::new()?; let fs = FileSettings::new()?;
let mut _logger = StderrLogger::new(fs.log.maximum_level);
if let Some(ref log_path) = fs.log.log_file { if let Some(ref log_path) = fs.log.log_file {
melib::change_log_dest(log_path.into()); _logger.change_log_dest(log_path.into());
}
if fs.log.maximum_level != melib::LoggingLevel::default() {
melib::change_log_level(fs.log.maximum_level);
} }
Ok(Settings { Ok(Settings {
@ -665,6 +666,7 @@ impl Settings {
pgp: fs.pgp, pgp: fs.pgp,
terminal: fs.terminal, terminal: fs.terminal,
log: fs.log, log: fs.log,
_logger,
}) })
} }
} }
@ -1015,7 +1017,7 @@ pub struct LogSettings {
#[serde(default)] #[serde(default)]
pub log_file: Option<PathBuf>, pub log_file: Option<PathBuf>,
#[serde(default)] #[serde(default)]
pub maximum_level: melib::LoggingLevel, pub maximum_level: melib::LogLevel,
} }
pub use dotaddressable::*; pub use dotaddressable::*;
@ -1047,7 +1049,7 @@ mod dotaddressable {
impl DotAddressable for crate::terminal::Key {} impl DotAddressable for crate::terminal::Key {}
impl DotAddressable for usize {} impl DotAddressable for usize {}
impl DotAddressable for Query {} impl DotAddressable for Query {}
impl DotAddressable for melib::LoggingLevel {} impl DotAddressable for melib::LogLevel {}
impl DotAddressable for PathBuf {} impl DotAddressable for PathBuf {}
impl DotAddressable for ToggleFlag {} impl DotAddressable for ToggleFlag {}
impl DotAddressable for SearchBackend {} impl DotAddressable for SearchBackend {}

@ -47,9 +47,10 @@ use melib::{
backends::*, backends::*,
email::*, email::*,
error::{Error, ErrorKind, Result}, error::{Error, ErrorKind, Result},
log,
text_processing::GlobMatch, text_processing::GlobMatch,
thread::{SortField, SortOrder, Threads}, thread::{SortField, SortOrder, Threads},
AddressBook, Collection, AddressBook, Collection, LogLevel,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
@ -127,12 +128,10 @@ impl MailboxEntry {
ret.path = melib::backends::utf7::decode_utf7_imap(&ret.path); ret.path = melib::backends::utf7::decode_utf7_imap(&ret.path);
} }
Some(other) => { Some(other) => {
melib::log( log::warn!(
format!( "mailbox `{}`: unrecognized mailbox name charset: {}",
"mailbox `{}`: unrecognized mailbox name charset: {}", &ret.name,
&ret.name, other other
),
melib::WARN,
); );
} }
} }
@ -199,7 +198,7 @@ pub enum JobRequest {
}, },
Generic { Generic {
name: Cow<'static, str>, name: Cow<'static, str>,
logging_level: melib::LoggingLevel, log_level: LogLevel,
handle: JoinHandle<Result<()>>, handle: JoinHandle<Result<()>>,
on_finish: Option<crate::types::CallbackFn>, on_finish: Option<crate::types::CallbackFn>,
}, },
@ -636,13 +635,11 @@ impl Account {
} }
for missing_mailbox in &mailbox_conf_hash_set { for missing_mailbox in &mailbox_conf_hash_set {
melib::log( log::warn!(
format!( "Account `{}` mailbox `{}` configured but not present in account's mailboxes. Is \
"Account `{}` mailbox `{}` configured but not present in account's mailboxes. \ it misspelled?",
Is it misspelled?", &self.name,
&self.name, missing_mailbox, missing_mailbox,
),
melib::WARN,
); );
self.sender self.sender
.send(ThreadEvent::UIEvent(UIEvent::StatusEvent( .send(ThreadEvent::UIEvent(UIEvent::StatusEvent(
@ -667,12 +664,10 @@ impl Account {
}); });
mailbox_comma_sep_list_string mailbox_comma_sep_list_string
.drain(mailbox_comma_sep_list_string.len().saturating_sub(2)..); .drain(mailbox_comma_sep_list_string.len().saturating_sub(2)..);
melib::log( log::warn!(
format!( "Account `{}` has the following mailboxes: [{}]",
"Account `{}` has the following mailboxes: [{}]", &self.name,
&self.name, mailbox_comma_sep_list_string, mailbox_comma_sep_list_string,
),
melib::WARN,
); );
self.sender self.sender
.send(ThreadEvent::UIEvent(UIEvent::StatusEvent( .send(ThreadEvent::UIEvent(UIEvent::StatusEvent(
@ -766,13 +761,10 @@ impl Account {
) )
}) { }) {
Err(err) => { Err(err) => {
melib::log( log::error!(
format!( "Failed to update envelope {} in cache: {}",
"Failed to update envelope {} in cache: {}", envelope.message_id_display(),
envelope.message_id_display(), err
err
),
melib::ERROR,
); );
} }
Ok(job) => { Ok(job) => {
@ -786,7 +778,7 @@ impl Account {
) )
.into(), .into(),
handle, handle,
logging_level: melib::LoggingLevel::TRACE, log_level: LogLevel::TRACE,
on_finish: None, on_finish: None,
}, },
); );
@ -833,20 +825,17 @@ impl Account {
) )
.into(), .into(),
handle, handle,
logging_level: melib::LoggingLevel::TRACE, log_level: LogLevel::TRACE,
on_finish: None, on_finish: None,
}, },
); );
} }
Err(err) => { Err(err) => {
melib::log( log::error!(
format!( "Failed to update envelope {} in cache: {}",
"Failed to update envelope {} in cache: {}", self.collection.envelopes.read().unwrap()[&env_hash]
self.collection.envelopes.read().unwrap()[&env_hash] .message_id_display(),
.message_id_display(), err
err
),
melib::ERROR,
); );
} }
} }
@ -869,14 +858,11 @@ impl Account {
) )
}) { }) {
Err(err) => { Err(err) => {
melib::log( log::error!(
format!( "Failed to update envelope {} in cache: {}",
"Failed to update envelope {} in cache: {}", &self.collection.envelopes.read().unwrap()[&new_hash]
&self.collection.envelopes.read().unwrap()[&new_hash] .message_id_display(),
.message_id_display(), err
err
),
melib::ERROR,
); );
} }
Ok(job) => { Ok(job) => {
@ -891,7 +877,7 @@ impl Account {
) )
.into(), .into(),
handle, handle,
logging_level: melib::LoggingLevel::TRACE, log_level: LogLevel::TRACE,
on_finish: None, on_finish: None,
}, },
); );
@ -934,7 +920,7 @@ impl Account {
) )
.into(), .into(),
handle, handle,
logging_level: melib::LoggingLevel::TRACE, log_level: LogLevel::TRACE,
on_finish: None, on_finish: None,
}, },
); );
@ -996,14 +982,11 @@ impl Account {
if self.settings.conf.search_backend == crate::conf::SearchBackend::Sqlite3 { if self.settings.conf.search_backend == crate::conf::SearchBackend::Sqlite3 {
if let Err(err) = crate::sqlite3::remove(env_hash) { if let Err(err) = crate::sqlite3::remove(env_hash) {
let envelopes = self.collection.envelopes.read().unwrap(); let envelopes = self.collection.envelopes.read().unwrap();
melib::log( log::error!(
format!( "Failed to remove envelope {} [{}] in cache: {}",
"Failed to remove envelope {} [{}] in cache: {}", &envelopes[&env_hash].message_id_display(),
&envelopes[&env_hash].message_id_display(), env_hash,
env_hash, err
err
),
melib::ERROR,
); );
} }
} }
@ -1235,10 +1218,7 @@ impl Account {
if let Some(mailbox_hash) = mailbox { if let Some(mailbox_hash) = mailbox {
if let Err(err) = self.save(bytes, *mailbox_hash, Some(flags)) { if let Err(err) = self.save(bytes, *mailbox_hash, Some(flags)) {
debug!("{:?} could not save msg", err); debug!("{:?} could not save msg", err);
melib::log( log::error!("Could not save in '{}' mailbox: {}.", *mailbox_hash, err);
format!("Could not save in '{}' mailbox: {}.", *mailbox_hash, err),
melib::ERROR,
);
} else { } else {
saved_at = Some(*mailbox_hash); saved_at = Some(*mailbox_hash);
break; break;
@ -1253,12 +1233,9 @@ impl Account {
} else { } else {
let file = crate::types::create_temp_file(bytes, None, None, false); let file = crate::types::create_temp_file(bytes, None, None, false);
debug!("message saved in {}", file.path.display()); debug!("message saved in {}", file.path.display());
melib::log( log::info!(
format!( "Message was stored in {} so that you can restore it manually.",
"Message was stored in {} so that you can restore it manually.", file.path.display()
file.path.display()
),
melib::INFO,
); );
Err(Error::new(format!( Err(Error::new(format!(
"Message was stored in {} so that you can restore it manually.", "Message was stored in {} so that you can restore it manually.",
@ -1336,7 +1313,7 @@ impl Account {
} }
let output = msmtp.wait().expect("Failed to wait on mailer"); let output = msmtp.wait().expect("Failed to wait on mailer");
if output.success() { if output.success() {
melib::log("Message sent.", melib::LoggingLevel::TRACE); log::trace!("Message sent.");
} else { } else {
let error_message = if let Some(exit_code) = output.code() { let error_message = if let Some(exit_code) = output.code() {
format!( format!(
@ -1349,7 +1326,7 @@ impl Account {
command command
) )
}; };
melib::log(&error_message, melib::LoggingLevel::ERROR); log::error!("{}", error_message);
return Err(Error::new(error_message).set_summary("Message not sent.")); return Err(Error::new(error_message).set_summary("Message not sent."));
} }
Ok(None) Ok(None)
@ -1426,7 +1403,7 @@ impl Account {
} }
let output = msmtp.wait().expect("Failed to wait on mailer"); let output = msmtp.wait().expect("Failed to wait on mailer");
if output.success() { if output.success() {
melib::log("Message sent.", melib::LoggingLevel::TRACE); log::trace!("Message sent.");
} else { } else {
let error_message = if let Some(exit_code) = output.code() { let error_message = if let Some(exit_code) = output.code() {
format!( format!(
@ -1440,7 +1417,7 @@ impl Account {
command command
) )
}; };
melib::log(&error_message, melib::LoggingLevel::ERROR); log::error!("{}", error_message);
return Err(Error::new(error_message).set_summary("Message not sent.")); return Err(Error::new(error_message).set_summary("Message not sent."));
} }
Ok(()) Ok(())
@ -1895,15 +1872,12 @@ impl Account {
.. ..
} => { } => {
if let Ok(Some(Err(err))) = handle.chan.try_recv() { if let Ok(Some(Err(err))) = handle.chan.try_recv() {
melib::log(format!("Could not save message: {}", err), melib::ERROR); log::error!("Could not save message: {err}");
let file = crate::types::create_temp_file(bytes, None, None, false); let file = crate::types::create_temp_file(bytes, None, None, false);
debug!("message saved in {}", file.path.display()); log::debug!("message saved in {}", file.path.display());
melib::log( log::info!(
format!( "Message was stored in {} so that you can restore it manually.",
"Message was stored in {} so that you can restore it manually.", file.path.display()
file.path.display()
),
melib::INFO,
); );
self.sender self.sender
.send(ThreadEvent::UIEvent(UIEvent::Notification( .send(ThreadEvent::UIEvent(UIEvent::Notification(
@ -2199,7 +2173,7 @@ impl Account {
ref name, ref name,
ref mut handle, ref mut handle,
ref mut on_finish, ref mut on_finish,
logging_level, log_level,
} => { } => {
match handle.chan.try_recv() { match handle.chan.try_recv() {
Ok(Some(Err(err))) => { Ok(Some(Err(err))) => {
@ -2212,7 +2186,7 @@ impl Account {
.expect("Could not send event on main channel"); .expect("Could not send event on main channel");
} }
Ok(Some(Ok(()))) if on_finish.is_none() => { Ok(Some(Ok(()))) if on_finish.is_none() => {
if logging_level <= melib::LoggingLevel::INFO { if log_level <= LogLevel::INFO {
self.sender self.sender
.send(ThreadEvent::UIEvent(UIEvent::Notification( .send(ThreadEvent::UIEvent(UIEvent::Notification(
Some(format!("{}: {} succeeded", &self.name, name,)), Some(format!("{}: {} succeeded", &self.name, name,)),

@ -30,7 +30,7 @@ use std::{
process::{Command, Stdio}, process::{Command, Stdio},
}; };
use melib::{email::Attachment, text_processing::GlobMatch, Error, Result}; use melib::{email::Attachment, log, text_processing::GlobMatch, Error, Result};
use crate::{ use crate::{
state::Context, state::Context,
@ -186,10 +186,7 @@ impl MailcapEntry {
}) })
.collect::<Vec<String>>(); .collect::<Vec<String>>();
let cmd_string = format!("{} {}", cmd, args.join(" ")); let cmd_string = format!("{} {}", cmd, args.join(" "));
melib::log( log::debug!("Executing: sh -c \"{}\"", cmd_string.replace('"', "\\\""));
format!("Executing: sh -c \"{}\"", cmd_string.replace('"', "\\\"")),
melib::DEBUG,
);
if copiousoutput { if copiousoutput {
let out = if needs_stdin { let out = if needs_stdin {
let mut child = Command::new("sh") let mut child = Command::new("sh")

@ -36,7 +36,7 @@ use melib::{
}, },
sqlite3::{self as melib_sqlite3, rusqlite::params, DatabaseDescription}, sqlite3::{self as melib_sqlite3, rusqlite::params, DatabaseDescription},
thread::{SortField, SortOrder}, thread::{SortField, SortOrder},
Error, Result, ERROR, Error, Result,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
@ -174,13 +174,9 @@ pub async fn insert(
err err
) )
); );
log( log::error!(
format!( "Failed to open envelope {}: {err}",
"Failed to open envelope {}: {}", envelope.message_id_display(),
envelope.message_id_display(),
err
),
ERROR,
); );
return Err(err); return Err(err);
} }
@ -195,13 +191,9 @@ pub async fn insert(
envelope.message_id_display(), envelope.message_id_display(),
err err
); );
log( log::error!(
format!( "Failed to insert envelope {}: {err}",
"Failed to insert envelope {}: {}", envelope.message_id_display(),
envelope.message_id_display(),
err
),
ERROR,
); );
return Err(Error::new(err.to_string())); return Err(Error::new(err.to_string()));
} }
@ -246,18 +238,13 @@ pub async fn insert(
) )
.map_err(|e| Error::new(e.to_string())) .map_err(|e| Error::new(e.to_string()))
{ {
debug!( log::debug!(
"Failed to insert envelope {}: {}", "Failed to insert envelope {}: {err}",
envelope.message_id_display(), envelope.message_id_display(),
err
); );
log( log::error!(
format!( "Failed to insert envelope {}: {err}",
"Failed to insert envelope {}: {}", envelope.message_id_display(),
envelope.message_id_display(),
err
),
ERROR,
); );
} }
Ok(()) Ok(())
@ -279,11 +266,8 @@ pub fn remove(env_hash: EnvelopeHash) -> Result<()> {
) )
.map_err(|e| Error::new(e.to_string())) .map_err(|e| Error::new(e.to_string()))
{ {
debug!("Failed to remove envelope {}: {}", env_hash, err); log::debug!("Failed to remove envelope {env_hash}: {err}");
log( log::error!("Failed to remove envelope {env_hash}: {err}");
format!("Failed to remove envelope {}: {}", env_hash, err),
ERROR,
);
return Err(err); return Err(err);
} }
Ok(()) Ok(())

@ -881,7 +881,7 @@ impl State {
name: "Message index rebuild".into(), name: "Message index rebuild".into(),
handle, handle,
on_finish: None, on_finish: None,
logging_level: melib::LoggingLevel::INFO, log_level: LogLevel::INFO,
}, },
); );
self.context.replies.push_back(UIEvent::Notification( self.context.replies.push_back(UIEvent::Notification(
@ -1080,15 +1080,13 @@ impl State {
level, level,
}, },
) => { ) => {
log( log::log!(
format!( level.into(),
"{}: {}{}{}", "{}: {}{}{}",
self.context.accounts[&account_hash].name(), self.context.accounts[&account_hash].name(),
description.as_str(), description.as_str(),
if content.is_some() { ": " } else { "" }, if content.is_some() { ": " } else { "" },
content.as_ref().map(|s| s.as_str()).unwrap_or("") content.as_ref().map(|s| s.as_str()).unwrap_or("")
),
level,
); );
self.rcv_event(UIEvent::StatusEvent(StatusEvent::DisplayMessage( self.rcv_event(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
description.to_string(), description.to_string(),
@ -1208,7 +1206,7 @@ impl State {
Ok(Some(_)) => true, Ok(Some(_)) => true,
Ok(None) => false, Ok(None) => false,
Err(err) => { Err(err) => {
log(format!("Failed to wait on editor process: {}", err), ERROR); log::error!("Failed to wait on editor process: {err}");
return None; return None;
} }
} }
@ -1219,7 +1217,7 @@ impl State {
Ok(Some(_)) => true, Ok(Some(_)) => true,
Ok(None) => false, Ok(None) => false,
Err(err) => { Err(err) => {
log(format!("Failed to wait on child process: {}", err), ERROR); log::error!("Failed to wait on child process: {err}");
return None; return None;
} }
} }

@ -27,7 +27,7 @@ use std::{
}, },
}; };
use melib::{error::*, log, ERROR}; use melib::{error::*, log};
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
use nix::{ use nix::{
fcntl::{open, OFlag}, fcntl::{open, OFlag},
@ -123,23 +123,15 @@ pub fn create_pty(
nix::unistd::setsid().unwrap(); nix::unistd::setsid().unwrap();
match unsafe { set_controlling_terminal(slave_fd) } { match unsafe { set_controlling_terminal(slave_fd) } {
Ok(c) if c < 0 => { Ok(c) if c < 0 => {
log( log::error!(
format!( "Could not execute `{command}`: ioctl(fd, TIOCSCTTY, NULL) returned {c}",
"Could not execute `{}`: ioctl(fd, TIOCSCTTY, NULL) returned {}",
command, c,
),
ERROR,
); );
std::process::exit(c); std::process::exit(c);
} }
Ok(_) => {} Ok(_) => {}
Err(err) => { Err(err) => {
log( log::error!(
format!( "Could not execute `{command}`: ioctl(fd, TIOCSCTTY, NULL) returned {err}",
"Could not execute `{}`: ioctl(fd, TIOCSCTTY, NULL) returned {}",
command, err,
),
ERROR,
); );
std::process::exit(-1); std::process::exit(-1);
} }
@ -160,18 +152,15 @@ pub fn create_pty(
&CString::new(command.as_bytes()).unwrap(), &CString::new(command.as_bytes()).unwrap(),
], ],
) { ) {
log(format!("Could not execute `{}`: {}", command, e,), ERROR); log::error!("Could not execute `{command}`: {e}");
std::process::exit(-1); std::process::exit(-1);
} }
} }
} }
log( log::error!(
format!( "Could not execute `{command}`: did not find the standard POSIX sh shell in PATH \
"Could not execute `{}`: did not find the standard POSIX sh shell in PATH = {}", = {}",
command, String::from_utf8_lossy(&path_var),
String::from_utf8_lossy(&path_var),
),
ERROR,
); );
std::process::exit(-1); std::process::exit(-1);
} }

Loading…
Cancel
Save