more specific errors for some IO errors

This commit is contained in:
Abraham Toriz 2021-07-21 19:06:49 -05:00
parent cd6fc35ce4
commit 9c306d55ce
No known key found for this signature in database
GPG Key ID: D5B4A746DB5DD42A
5 changed files with 70 additions and 19 deletions

View File

@ -97,7 +97,12 @@ impl Config {
if config_filename.is_file() { if config_filename.is_file() {
Self::read_from_toml(config_filename) Self::read_from_toml(config_filename)
} else { } else {
create_dir_all(project_dirs.config_dir())?; let config_dir = project_dirs.config_dir();
create_dir_all(config_dir).map_err(|e| CouldntCreateConfigDir {
path: config_dir.to_owned(),
error: e.to_string(),
})?;
Self::create_and_return_config(project_dirs.config_dir(), &config_filename) Self::create_and_return_config(project_dirs.config_dir(), &config_filename)
} }
} else { } else {
@ -160,8 +165,15 @@ impl Config {
..Default::default() ..Default::default()
}; };
let mut config_file = File::create(config_filename)?; let mut config_file = File::create(config_filename).map_err(|e| CouldntEditConfigFile {
config_file.write_all(to_string(&config).unwrap().as_bytes())?; path: config_filename.to_owned(),
error: e.to_string(),
})?;
config_file.write_all(to_string(&config).unwrap().as_bytes()).map_err(|e| CouldntEditConfigFile {
path: config_filename.to_owned(),
error: e.to_string(),
})?;
Ok(config) Ok(config)
} }

View File

@ -3,19 +3,19 @@ use std::io::Read;
use tempfile::NamedTempFile; use tempfile::NamedTempFile;
use crate::error::{Error, Result}; use crate::error::{Error::*, Result};
pub fn get_string(note_editor: Option<&String>) -> Result<String> { pub fn get_string(note_editor: Option<&String>) -> Result<String> {
let note_editor = if let Some(note_editor) = note_editor { let note_editor = if let Some(note_editor) = note_editor {
note_editor note_editor
} else { } else {
return Err(Error::EditorIsEmpty); return Err(EditorIsEmpty);
}; };
let parts: Vec<_> = note_editor.split(" ").filter(|p| p.len() > 0).collect(); let parts: Vec<_> = note_editor.split(" ").filter(|p| p.len() > 0).collect();
let editor = if let Some(name) = parts.get(0) { let editor = if let Some(name) = parts.get(0) {
name.to_owned() name.to_owned()
} else { } else {
return Err(Error::EditorIsEmpty); return Err(EditorIsEmpty);
}; };
let mut c = Command::new(editor); let mut c = Command::new(editor);
@ -26,7 +26,7 @@ pub fn get_string(note_editor: Option<&String>) -> Result<String> {
} }
} }
let mut tmpfile = NamedTempFile::new()?; let mut tmpfile = NamedTempFile::new().map_err(|e| NoTmpFile(e.to_string()))?;
c.arg(tmpfile.as_ref()); c.arg(tmpfile.as_ref());
@ -34,16 +34,19 @@ pub fn get_string(note_editor: Option<&String>) -> Result<String> {
.stdin(Stdio::inherit()) .stdin(Stdio::inherit())
.stdout(Stdio::inherit()) .stdout(Stdio::inherit())
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
.output()? .output().map_err(|e| EditorFailed {
editor: note_editor.clone(),
error: e.to_string(),
})?
.status; .status;
if status.success() { if status.success() {
let mut note = String::new(); let mut note = String::new();
tmpfile.read_to_string(&mut note)?; tmpfile.read_to_string(&mut note).map_err(|e| CouldntReadTmpFile(e.to_string()))?;
Ok(note) Ok(note)
} else { } else {
Err(Error::EditorFailed { editor: note_editor.clone(), error: status.to_string() }) Err(EditorFailed { editor: note_editor.clone(), error: status.to_string() })
} }
} }

View File

@ -108,7 +108,45 @@ t config --help for more options.")]
EditorFailed { EditorFailed {
editor: String, editor: String,
error: String, error: String,
} },
#[error("A temporary file couldn't be created for you to edit. This is very
weird, but might have something to do with yout OS.
Here's the underlaying error:
{0}
If you think this is an issue with this program report it at:
https://gitlab.com/categulario/tiempo")]
NoTmpFile(String),
#[error("The temporary file you just created couldn't be read. This is the
underlaying error:
{0}
I didn't imagine this could ever happen, but now I'm curious. Do you mind
reporging the issue at https://gitlab.com/categulario/tiempo ?")]
CouldntReadTmpFile(String),
#[error("The ")]
CouldntCreateConfigDir {
path: PathBuf,
error: String,
},
#[error("A problem ocurred while trying to edit/create the config file at
{path}
Is there a permissions issue? Here's the underlaying error:
{error}")]
CouldntEditConfigFile {
path: PathBuf,
error: String,
},
} }
pub type Result<T> = result::Result<T, Error>; pub type Result<T> = result::Result<T, Error>;

View File

@ -3,7 +3,7 @@ use std::io::Write;
use csv::Writer; use csv::Writer;
use chrono::SecondsFormat; use chrono::SecondsFormat;
use crate::error::Result; use crate::error::{Result, Error::*};
use crate::models::Entry; use crate::models::Entry;
pub fn print_formatted<W: Write>(entries: Vec<Entry>, out: &mut W, ids: bool) -> Result<()> { pub fn print_formatted<W: Write>(entries: Vec<Entry>, out: &mut W, ids: bool) -> Result<()> {
@ -34,9 +34,7 @@ pub fn print_formatted<W: Write>(entries: Vec<Entry>, out: &mut W, ids: bool) ->
} }
} }
wtr.flush()?; wtr.flush().map_err(|e| IOError(e))
Ok(())
} }
#[cfg(test)] #[cfg(test)]

View File

@ -3,7 +3,7 @@ use std::io::Write;
use chrono::{DateTime, Utc, Local, LocalResult, TimeZone}; use chrono::{DateTime, Utc, Local, LocalResult, TimeZone};
use ansi_term::Color::Yellow; use ansi_term::Color::Yellow;
use crate::error::{Error, Result}; use crate::error::{Error::*, Result};
use crate::models::Entry; use crate::models::Entry;
use crate::database::{Database, DBVersion}; use crate::database::{Database, DBVersion};
@ -13,9 +13,9 @@ use crate::database::{Database, DBVersion};
/// Used to convert times from the old database version. /// Used to convert times from the old database version.
fn local_to_utc(t: DateTime<Utc>) -> Result<DateTime<Utc>> { fn local_to_utc(t: DateTime<Utc>) -> Result<DateTime<Utc>> {
let local_time = match Local.from_local_datetime(&t.naive_utc()) { let local_time = match Local.from_local_datetime(&t.naive_utc()) {
LocalResult::None => return Err(Error::NoneLocalTime(t.naive_utc().to_string())), LocalResult::None => return Err(NoneLocalTime(t.naive_utc().to_string())),
LocalResult::Single(t) => t, LocalResult::Single(t) => t,
LocalResult::Ambiguous(t1, t2) => return Err(Error::AmbiguousLocalTime { LocalResult::Ambiguous(t1, t2) => return Err(AmbiguousLocalTime {
orig: t.naive_utc().to_string(), orig: t.naive_utc().to_string(),
t1: t1.naive_local(), t1: t1.naive_local(),
t2: t2.naive_local(), t2: t2.naive_local(),
@ -77,7 +77,7 @@ pub fn warn_if_needed<E: Write>(err: &mut E, needs_warning: bool) -> Result<()>
"{} You are using the old timetrap format, it is advised that \ "{} You are using the old timetrap format, it is advised that \
you update your database using t migrate", you update your database using t migrate",
Yellow.bold().paint("[WARNING]"), Yellow.bold().paint("[WARNING]"),
)?; ).map_err(|e| IOError(e))?;
} }
Ok(()) Ok(())