Skip to content

Commit

Permalink
refactor(tauri) update error handling crate to anyhow+thiserror, close
Browse files Browse the repository at this point in the history
…#613 (#621)

* Replace error-chain with thiserror in util crate

* Replace errorchain with anyhow/thiserror in api

* Replace with anyhow/thiserror in updater

* Replace with anyhow/thiserror in tauri

* Fix error handling on windows
  • Loading branch information
Wu Yu Wei authored May 29, 2020
1 parent 974cd3d commit c23675b
Show file tree
Hide file tree
Showing 28 changed files with 255 additions and 320 deletions.
3 changes: 2 additions & 1 deletion tauri-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ tempfile = "3"
either = "1.5.3"
tar = "0.4"
flate2 = "1"
error-chain = "0.12"
anyhow = "1.0.31"
thiserror = "1.0.19"
rand = "0.7"
nfd = "0.0.4"
attohttpc = {version = "0.13.0", features=["json", "form" ]}
Expand Down
50 changes: 22 additions & 28 deletions tauri-api/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,28 @@ use tauri_utils::platform;

#[cfg(not(windows))]
pub fn get_output(cmd: String, args: Vec<String>, stdout: Stdio) -> crate::Result<String> {
Command::new(cmd)
.args(args)
.stdout(stdout)
.output()
.map_err(|err| crate::Error::with_chain(err, "Command: get output failed"))
.and_then(|output| {
if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).to_string())
} else {
Err(crate::ErrorKind::Command(String::from_utf8_lossy(&output.stderr).to_string()).into())
}
})
let output = Command::new(cmd).args(args).stdout(stdout).output()?;

if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).to_string())
} else {
Err(crate::Error::Command(String::from_utf8_lossy(&output.stderr).to_string()).into())
}
}

#[cfg(windows)]
pub fn get_output(cmd: String, args: Vec<String>, stdout: Stdio) -> crate::Result<String> {
Command::new(cmd)
let output = Command::new(cmd)
.args(args)
.stdout(stdout)
.creation_flags(CREATE_NO_WINDOW)
.output()
.map_err(|err| crate::Error::with_chain(err, "Command: get output failed"))
.and_then(|output| {
if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).to_string())
} else {
Err(crate::ErrorKind::Command(String::from_utf8_lossy(&output.stderr).to_string()).into())
}
})
.output()?;

if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).to_string())
} else {
Err(crate::Error::Command(String::from_utf8_lossy(&output.stderr).to_string()).into())
}
}

pub fn format_command(path: String, command: String) -> String {
Expand All @@ -52,23 +45,23 @@ pub fn format_command(path: String, command: String) -> String {
pub fn relative_command(command: String) -> crate::Result<String> {
match std::env::current_exe()?.parent() {
Some(exe_dir) => Ok(format_command(exe_dir.display().to_string(), command)),
None => Err(crate::ErrorKind::Command("Could not evaluate executable dir".to_string()).into()),
None => Err(crate::Error::Command("Could not evaluate executable dir".to_string()).into()),
}
}

#[cfg(not(windows))]
pub fn command_path(command: String) -> crate::Result<String> {
match std::env::current_exe()?.parent() {
Some(exe_dir) => Ok(format!("{}/{}", exe_dir.display().to_string(), command)),
None => Err(crate::ErrorKind::Command("Could not evaluate executable dir".to_string()).into()),
None => Err(crate::Error::Command("Could not evaluate executable dir".to_string()).into()),
}
}

#[cfg(windows)]
pub fn command_path(command: String) -> crate::Result<String> {
match std::env::current_exe()?.parent() {
Some(exe_dir) => Ok(format!("{}/{}.exe", exe_dir.display().to_string(), command)),
None => Err(crate::ErrorKind::Command("Could not evaluate executable dir".to_string()).into()),
None => Err(crate::Error::Command("Could not evaluate executable dir".to_string()).into()),
}
}

Expand Down Expand Up @@ -106,7 +99,8 @@ pub fn binary_command(binary_name: String) -> crate::Result<String> {
#[cfg(test)]
mod test {
use super::*;
use crate::{Error, ErrorKind};
use crate::Error;
use std::io;
use totems::{assert_err, assert_ok};

#[test]
Expand Down Expand Up @@ -141,7 +135,7 @@ mod test {
assert_err!(&res);

// destruct the Error to check the ErrorKind and test that it is a Command type.
if let Err(Error(ErrorKind::Command(e), _)) = &res {
if let Some(Error::Command(e)) = res.unwrap_err().downcast_ref::<Error>() {
// assert that the message in the error matches this string.
assert_eq!(*e, "cat: test/: Is a directory\n".to_string());
}
Expand Down Expand Up @@ -200,7 +194,7 @@ mod test {
assert_err!(&res);

// after asserting that the result is an error, check that the error kind is ErrorKind::Io
if let Err(Error(ErrorKind::Io(s), _)) = &res {
if let Some(s) = res.unwrap_err().downcast_ref::<io::Error>() {
// assert that the ErrorKind inside of the ErrorKind Io is ErrorKind::NotFound
assert_eq!(s.kind(), std::io::ErrorKind::NotFound);
}
Expand Down
44 changes: 27 additions & 17 deletions tauri-api/src/dialog.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,43 @@
use nfd::{DialogType, open_dialog};
pub use nfd::Response;
use nfd::{open_dialog, DialogType};

fn open_dialog_internal(dialog_type: DialogType, filter: Option<String>, default_path: Option<String>) -> crate::Result<Response> {
open_dialog(filter.as_deref(), default_path.as_deref(), dialog_type)
.map_err(|err| crate::Error::with_chain(err, "open dialog failed"))
.and_then(|response| {
match response {
Response::Cancel => Err(crate::Error::from("user cancelled")),
_ => Ok(response)
}
})
fn open_dialog_internal(
dialog_type: DialogType,
filter: Option<String>,
default_path: Option<String>,
) -> crate::Result<Response> {
let response = open_dialog(filter.as_deref(), default_path.as_deref(), dialog_type)?;
match response {
Response::Cancel => Err(crate::Error::Dialog("user cancelled".into()).into()),
_ => Ok(response),
}
}

/// Open single select file dialog
pub fn select(filter_list: Option<String>, default_path: Option<String>) -> crate::Result<Response> {
open_dialog_internal(DialogType::SingleFile, filter_list, default_path)
pub fn select(
filter_list: Option<String>,
default_path: Option<String>,
) -> crate::Result<Response> {
open_dialog_internal(DialogType::SingleFile, filter_list, default_path)
}

/// Open mulitple select file dialog
pub fn select_multiple(filter_list: Option<String>, default_path: Option<String>) -> crate::Result<Response> {
open_dialog_internal(DialogType::MultipleFiles, filter_list, default_path)
pub fn select_multiple(
filter_list: Option<String>,
default_path: Option<String>,
) -> crate::Result<Response> {
open_dialog_internal(DialogType::MultipleFiles, filter_list, default_path)
}

/// Open save dialog
pub fn save_file(filter_list: Option<String>, default_path: Option<String>) -> crate::Result<Response> {
open_dialog_internal(DialogType::SaveFile, filter_list, default_path)
pub fn save_file(
filter_list: Option<String>,
default_path: Option<String>,
) -> crate::Result<Response> {
open_dialog_internal(DialogType::SaveFile, filter_list, default_path)
}

/// Open pick folder dialog
pub fn pick_folder(default_path: Option<String>) -> crate::Result<Response> {
open_dialog_internal(DialogType::PickFolder, None, default_path)
open_dialog_internal(DialogType::PickFolder, None, default_path)
}
29 changes: 13 additions & 16 deletions tauri-api/src/dir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub struct DiskEntry {
fn is_dir(file_name: String) -> crate::Result<bool> {
match metadata(file_name) {
Ok(md) => Result::Ok(md.is_dir()),
Err(err) => Result::Err(err.to_string().into()),
Err(err) => Result::Err(err.into()),
}
}

Expand All @@ -43,21 +43,18 @@ pub fn walk_dir(path_copy: String) -> crate::Result<Vec<DiskEntry>> {
}

pub fn list_dir_contents(dir_path: String) -> crate::Result<Vec<DiskEntry>> {
fs::read_dir(dir_path)
.map_err(|err| crate::Error::with_chain(err, "read dir failed"))
.and_then(|paths| {
let mut dirs: Vec<DiskEntry> = vec![];
for path in paths {
let dir_path = path.expect("dirpath error").path();
let _dir_name = dir_path.display();
dirs.push(DiskEntry {
path: format!("{}", _dir_name),
is_dir: true,
name: get_dir_name_from_path(_dir_name.to_string()),
});
}
Ok(dirs)
})
let paths = fs::read_dir(dir_path)?;
let mut dirs: Vec<DiskEntry> = vec![];
for path in paths {
let dir_path = path.expect("dirpath error").path();
let _dir_name = dir_path.display();
dirs.push(DiskEntry {
path: format!("{}", _dir_name),
is_dir: true,
name: get_dir_name_from_path(_dir_name.to_string()),
});
}
Ok(dirs)
}

pub fn with_temp_dir<F: FnOnce(&tempfile::TempDir) -> ()>(callback: F) -> crate::Result<()> {
Expand Down
20 changes: 10 additions & 10 deletions tauri-api/src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@ mod file_move;

use std::fs;

use crate::{Error, ErrorKind};
use crate::Error;

pub use extract::*;
pub use file_move::*;

pub fn read_string(file: String) -> crate::Result<String> {
fs::read_to_string(file)
.map_err(|err| Error::from(ErrorKind::File(format!("Read_string failed: {}", err))))
.map_err(|err| Error::File(format!("Read_string failed: {}", err)).into())
.map(|c| c)
}

pub fn read_binary(file: String) -> crate::Result<Vec<u8>> {
fs::read(file)
.map_err(|err| Error::from(ErrorKind::File(format!("Read_binary failed: {}", err))))
.map_err(|err| Error::File(format!("Read_binary failed: {}", err)).into())
.map(|b| b)
}

#[cfg(test)]
mod test {
use super::*;
use crate::{Error, ErrorKind};
use crate::Error;
use totems::{assert_err, assert_ok};

#[test]
Expand All @@ -47,15 +47,15 @@ mod test {

assert_err!(res);

if let Err(Error(ErrorKind::File(e), _)) = res {
if let Some(Error::File(e)) = res.unwrap_err().downcast_ref::<Error>() {
#[cfg(windows)]
assert_eq!(
e,
*e,
"Read_string failed: Access is denied. (os error 5)".to_string()
);
#[cfg(not(windows))]
assert_eq!(
e,
*e,
"Read_string failed: Is a directory (os error 21)".to_string()
);
}
Expand Down Expand Up @@ -93,15 +93,15 @@ mod test {

assert_err!(res);

if let Err(Error(ErrorKind::File(e), _)) = res {
if let Some(Error::File(e)) = res.unwrap_err().downcast_ref::<Error>() {
#[cfg(windows)]
assert_eq!(
e,
*e,
"Read_binary failed: Access is denied. (os error 5)".to_string()
);
#[cfg(not(windows))]
assert_eq!(
e,
*e,
"Read_binary failed: Is a directory (os error 21)".to_string()
);
}
Expand Down
15 changes: 8 additions & 7 deletions tauri-api/src/file/extract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,10 @@ impl<'a> Extract<'a> {
}
}
}
let file_name = self.source.file_name().ok_or_else(|| {
crate::ErrorKind::Extract("Extractor source has no file-name".into())
})?;
let file_name = self
.source
.file_name()
.ok_or_else(|| crate::Error::Extract("Extractor source has no file-name".into()))?;
let mut out_path = into_dir.join(file_name);
out_path.set_extension("");
let mut out_file = fs::File::create(&out_path)?;
Expand Down Expand Up @@ -148,9 +149,9 @@ impl<'a> Extract<'a> {
}
}
}
let file_name = file_to_extract.file_name().ok_or_else(|| {
crate::ErrorKind::Extract("Extractor source has no file-name".into())
})?;
let file_name = file_to_extract
.file_name()
.ok_or_else(|| crate::Error::Extract("Extractor source has no file-name".into()))?;
let out_path = into_dir.join(file_name);
let mut out_file = fs::File::create(&out_path)?;
io::copy(&mut reader, &mut out_file)?;
Expand All @@ -162,7 +163,7 @@ impl<'a> Extract<'a> {
.filter_map(|e| e.ok())
.find(|e| e.path().ok().filter(|p| p == file_to_extract).is_some())
.ok_or_else(|| {
crate::ErrorKind::Extract(format!(
crate::Error::Extract(format!(
"Could not find the required path in the archive: {:?}",
file_to_extract
))
Expand Down
2 changes: 1 addition & 1 deletion tauri-api/src/file/file_move.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl<'a> Move<'a> {
fs::rename(dest, temp)?;
if let Err(e) = fs::rename(self.source, dest) {
fs::rename(temp, dest)?;
return Err(crate::Error::from(e));
return Err(e.into());
}
} else {
fs::rename(self.source, dest)?;
Expand Down
Loading

0 comments on commit c23675b

Please sign in to comment.