浏览代码

Refact(api) Add error chain to Tauri_api. (#311)

* add error chain

* remove verson error

* update file error

* update dir

* fix file_system

* add command error type.

* fix minor inconsistency

* add command tests

* add other tests for cmd.

* add more testing for cmd

* add documentation.

* add walk_dir tests and documentation.

* add list_dir_contents test

* test for with_temp_dir

* add read_string tests and file error type.

* add test_binary and update tests.

* add check_read_binary_fail test

* add os codes for unix based systems.

* add core-tauri-test gh action

* update test-on-pr

* fix test to test all libs.

* fix unix/windows errors
Tensor-Programming 5 年之前
父节点
当前提交
667d5905f6

+ 6 - 0
.github/workflows/test-on-pr.yml

@@ -29,6 +29,12 @@ jobs:
         env:
           TAURI_DIST_DIR: ../../test/fixture/dist
           TAURI_DIR: ../test/fixture/src-tauri
+      - name: test
+        run: |
+          cargo test --features all-api
+        env:
+          TAURI_DIST_DIR: ../../test/fixture/dist
+          TAURI_DIR: ../test/fixture/src-tauri
 
   build-tauri-bundler:
     runs-on: ${{ matrix.platform }}

+ 3 - 1
tauri-api/Cargo.toml

@@ -20,7 +20,9 @@ tempfile = "3"
 either = "1.5.3"
 tar = "0.4"
 flate2 = "1"
+error-chain = "0.12"
 
 [dev-dependencies]
 quickcheck = "0.8.5"
-quickcheck_macros = "0.8.0"
+quickcheck_macros = "0.8.0"
+totems = "0.2.7"

+ 114 - 15
tauri-api/src/command.rs

@@ -1,16 +1,16 @@
 use std::process::{Child, Command, Stdio};
 
-pub fn get_output(cmd: String, args: Vec<String>, stdout: Stdio) -> Result<String, String> {
+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| err.to_string())
+    .map_err(|err| crate::Error::with_chain(err, "Command: get output failed"))
     .and_then(|output| {
       if output.status.success() {
-        Result::Ok(String::from_utf8_lossy(&output.stdout).to_string())
+        Ok(String::from_utf8_lossy(&output.stdout).to_string())
       } else {
-        Result::Err(String::from_utf8_lossy(&output.stderr).to_string())
+        Err(crate::ErrorKind::Command(String::from_utf8_lossy(&output.stderr).to_string()).into())
       }
     })
 }
@@ -23,28 +23,22 @@ pub fn format_command(path: String, command: String) -> String {
   }
 }
 
-pub fn relative_command(command: String) -> Result<String, std::io::Error> {
+pub fn relative_command(command: String) -> crate::Result<String> {
   match std::env::current_exe()?.parent() {
     Some(exe_dir) => return Ok(format_command(exe_dir.display().to_string(), command)),
     None => {
-      return Err(std::io::Error::new(
-        std::io::ErrorKind::Other,
-        "Could not evaluate executable dir".to_string(),
-      ))
+      return Err(crate::ErrorKind::Command("Could not evaluate executable dir".to_string()).into())
     }
   }
 }
 
-pub fn command_path(command: String) -> Result<String, std::io::Error> {
+pub fn command_path(command: String) -> crate::Result<String> {
   match std::env::current_exe()?.parent() {
     #[cfg(not(windows))]
     Some(exe_dir) => Ok(format!("{}/{}", exe_dir.display().to_string(), command)),
     #[cfg(windows)]
     Some(exe_dir) => Ok(format!("{}/{}.exe", exe_dir.display().to_string(), command)),
-    None => Err(std::io::Error::new(
-      std::io::ErrorKind::Other,
-      "Could not evaluate executable dir".to_string(),
-    )),
+    None => Err(crate::ErrorKind::Command("Could not evaluate executable dir".to_string()).into()),
   }
 }
 
@@ -52,7 +46,112 @@ pub fn spawn_relative_command(
   command: String,
   args: Vec<String>,
   stdout: Stdio,
-) -> Result<Child, std::io::Error> {
+) -> crate::Result<Child> {
   let cmd = relative_command(command)?;
   Ok(Command::new(cmd).args(args).stdout(stdout).spawn()?)
 }
+
+// tests for the commands functions.
+#[cfg(test)]
+mod test {
+  use super::*;
+  use crate::{Error, ErrorKind};
+  use totems::{assert_err, assert_ok};
+
+  #[test]
+  // test the get_output function with a unix cat command.
+  fn test_cmd_output() {
+    // create a string with cat in it.
+    let cmd = String::from("cat");
+
+    // call get_output with cat and the argument test/test.txt on the stdio.
+    let res = get_output(cmd, vec!["test/test.txt".to_string()], Stdio::piped());
+
+    // assert that the result is an Ok() type
+    assert_ok!(&res);
+
+    // if the assertion passes, assert the incoming data.
+    if let Ok(s) = &res {
+      // assert that cat returns the string in the test.txt document.
+      assert_eq!(*s, "This is a test doc!".to_string());
+    }
+  }
+
+  #[test]
+  // test the failure case for get_output
+  fn test_cmd_fail() {
+    // queue up a string with cat in it.
+    let cmd = String::from("cat");
+
+    // call get output with test/ as an argument on the stdio.
+    let res = get_output(cmd, vec!["test/".to_string()], Stdio::piped());
+
+    // assert that the result is an Error type.
+    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 {
+      // assert that the message in the error matches this string.
+      assert_eq!(*e, "cat: test/: Is a directory\n".to_string());
+    }
+  }
+
+  #[test]
+  // test the relative_command function
+  fn check_relateive_cmd() {
+    // generate a cat string
+    let cmd = String::from("cat");
+
+    // call relative command on the cat string
+    let res = relative_command(cmd.clone());
+
+    // assert that the result comes back with Ok()
+    assert_ok!(res);
+
+    // get the parent directory of the current executable.
+    let current_exe = std::env::current_exe()
+      .unwrap()
+      .parent()
+      .unwrap()
+      .display()
+      .to_string();
+
+    // check the string inside of the Ok
+    if let Ok(s) = &res {
+      // match the string against the call to format command with the current_exe.
+      assert_eq!(*s, format_command(current_exe, cmd));
+    }
+  }
+
+  #[test]
+  // test the command_path function
+  fn check_command_path() {
+    // generate a string for cat
+    let cmd = String::from("cat");
+
+    // call command_path on cat
+    let res = command_path(cmd);
+
+    // assert that the result is an OK() type.
+    assert_ok!(res);
+  }
+
+  #[test]
+  // check the spawn_relative_command function
+  fn check_spawn_cmd() {
+    // generate a cat string
+    let cmd = String::from("cat");
+
+    // call spawn_relative_command with cat and the argument test/test.txt on the Stdio.
+    let res = spawn_relative_command(cmd, vec!["test/test.txt".to_string()], Stdio::piped());
+
+    // this fails because there is no cat binary in the relative parent folder of this current executing command.
+    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 {
+      // assert that the ErrorKind inside of the ErrorKind Io is ErrorKind::NotFound
+      assert_eq!(s.kind(), std::io::ErrorKind::NotFound);
+    }
+  }
+}

+ 125 - 10
tauri-api/src/dir.rs

@@ -9,21 +9,21 @@ use utils::get_dir_name_from_path;
 
 use tempfile::tempdir;
 
-#[derive(Serialize)]
+#[derive(Debug, Serialize)]
 pub struct DiskEntry {
   pub path: String,
   pub is_dir: bool,
   pub name: String,
 }
 
-fn is_dir(file_name: String) -> Result<bool, String> {
+fn is_dir(file_name: String) -> crate::Result<bool> {
   match metadata(file_name.to_string()) {
     Ok(md) => return Result::Ok(md.is_dir()),
-    Err(err) => return Result::Err(err.to_string()),
+    Err(err) => return Result::Err(err.to_string().into()),
   };
 }
 
-pub fn walk_dir(path_copy: String) -> Result<Vec<DiskEntry>, String> {
+pub fn walk_dir(path_copy: String) -> crate::Result<Vec<DiskEntry>> {
   println!("Trying to walk: {}", path_copy.as_str());
   let mut files_and_dirs: Vec<DiskEntry> = vec![];
   for result in Walk::new(path_copy) {
@@ -49,9 +49,9 @@ pub fn walk_dir(path_copy: String) -> Result<Vec<DiskEntry>, String> {
   return Result::Ok(files_and_dirs);
 }
 
-pub fn list_dir_contents(dir_path: &String) -> Result<Vec<DiskEntry>, String> {
+pub fn list_dir_contents(dir_path: &String) -> crate::Result<Vec<DiskEntry>> {
   fs::read_dir(dir_path)
-    .map_err(|err| err.to_string())
+    .map_err(|err| crate::Error::with_chain(err, "read string failed"))
     .and_then(|paths| {
       let mut dirs: Vec<DiskEntry> = vec![];
       for path in paths {
@@ -67,9 +67,7 @@ pub fn list_dir_contents(dir_path: &String) -> Result<Vec<DiskEntry>, String> {
     })
 }
 
-pub fn with_temp_dir<F: FnOnce(&tempfile::TempDir) -> ()>(
-  callback: F,
-) -> Result<(), std::io::Error> {
+pub fn with_temp_dir<F: FnOnce(&tempfile::TempDir) -> ()>(callback: F) -> crate::Result<()> {
   let dir = tempdir()?;
   callback(&dir);
   dir.close()?;
@@ -78,7 +76,8 @@ pub fn with_temp_dir<F: FnOnce(&tempfile::TempDir) -> ()>(
 
 #[cfg(test)]
 mod test {
-  use crate::dir::*;
+  use super::*;
+  use totems::assert_ok;
 
   // check is dir function by passing in arbitrary strings
   #[quickcheck]
@@ -91,4 +90,120 @@ mod test {
       Err(_) => true,
     }
   }
+
+  #[test]
+  // check the walk_dir function
+  fn check_walk_dir() {
+    // define a relative directory string test/
+    let dir = String::from("test/");
+    // add the files to this directory
+    let file_one = format!("{}test.txt", &dir).to_string();
+    let file_two = format!("{}test_binary", &dir).to_string();
+
+    // call walk_dir on the directory
+    let res = walk_dir(dir.clone());
+
+    // assert that the result is Ok()
+    assert_ok!(&res);
+
+    // destruct the OK into a vector of DiskEntry Structs
+    if let Ok(vec) = res {
+      // assert that the vector length is only 3
+      assert_eq!(vec.len(), 3);
+
+      // get the first DiskEntry
+      let first = &vec[0];
+      // get the second DiskEntry
+      let second = &vec[1];
+      // get the third DiskEntry
+      let third = &vec[2];
+
+      // check the fields for the first DiskEntry
+      assert_eq!(first.path, dir);
+      assert_eq!(first.is_dir, true);
+      assert_eq!(first.name, dir);
+
+      if second.path.contains(".txt") {
+        // check the fields for the second DiskEntry
+        assert_eq!(second.path, file_one);
+        assert_eq!(second.is_dir, false);
+        assert_eq!(second.name, file_one);
+
+        // check the fields for the third DiskEntry
+        assert_eq!(third.path, file_two);
+        assert_eq!(third.is_dir, false);
+        assert_eq!(third.name, file_two);
+      } else {
+        // check the fields for the second DiskEntry
+        assert_eq!(second.path, file_two);
+        assert_eq!(second.is_dir, false);
+        assert_eq!(second.name, file_two);
+
+        // check the fields for the third DiskEntry
+        assert_eq!(third.path, file_one);
+        assert_eq!(third.is_dir, false);
+        assert_eq!(third.name, file_one);
+      }
+    }
+  }
+
+  #[test]
+  // check the list_dir_contents function
+  fn check_list_dir_contents() {
+    // define a relative directory string test/
+    let dir = String::from("test/");
+
+    // call list_dir_contents on the dir string
+    let res = list_dir_contents(&dir);
+
+    // assert that the result is Ok()
+    assert_ok!(&res);
+
+    // destruct the vector from the Ok()
+    if let Ok(vec) = res {
+      // assert the length of the vector is 2
+      assert_eq!(vec.len(), 2);
+
+      // get the two DiskEntry structs in this vector
+      let first = &vec[0];
+      let second = &vec[1];
+
+      if first.path.contains(".txt") {
+        // check the fields for the first DiskEntry
+        assert_eq!(first.path, "test/test.txt".to_string());
+        assert_eq!(first.is_dir, true);
+        assert_eq!(first.name, "test.txt".to_string());
+
+        // check the fields for the second DiskEntry
+        assert_eq!(second.path, "test/test_binary".to_string());
+        assert_eq!(second.is_dir, true);
+        assert_eq!(second.name, "test_binary".to_string());
+      } else {
+        // check the fields for the first DiskEntry
+        assert_eq!(second.path, "test/test.txt".to_string());
+        assert_eq!(second.is_dir, true);
+        assert_eq!(second.name, "test.txt".to_string());
+
+        // check the fields for the second DiskEntry
+        assert_eq!(first.path, "test/test_binary".to_string());
+        assert_eq!(first.is_dir, true);
+        assert_eq!(first.name, "test_binary".to_string());
+      }
+    }
+  }
+
+  #[test]
+  // test the with_temp_dir function
+  fn check_test_dir() {
+    // create a callback closure that takes in a TempDir type and prints it.
+    let callback = |td: &tempfile::TempDir| {
+      println!("{:?}", td);
+    };
+
+    // execute the with_temp_dir function on the callback
+    let res = with_temp_dir(callback);
+
+    // assert that the result is an OK type.
+    assert_ok!(res);
+  }
 }

+ 95 - 6
tauri-api/src/file.rs

@@ -1,19 +1,108 @@
 use std::fs;
 
-mod error;
 mod extract;
 mod file_move;
 
-pub use error::Error;
+use crate::{Error, ErrorKind};
 pub use extract::*;
 pub use file_move::*;
 
-pub fn read_string(file: String) -> Result<String, String> {
+pub fn read_string(file: String) -> crate::Result<String> {
   fs::read_to_string(file)
-    .map_err(|err| err.to_string())
+    .map_err(|err| Error::from(ErrorKind::File(format!("Read_string failed: {}", err))))
     .map(|c| c)
 }
 
-pub fn read_binary(file: String) -> Result<Vec<u8>, String> {
-  fs::read(file).map_err(|err| err.to_string()).map(|b| b)
+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(|b| b)
+}
+
+#[cfg(test)]
+mod test {
+  use super::*;
+  use crate::{Error, ErrorKind};
+  use totems::{assert_err, assert_ok};
+
+  #[test]
+  fn check_read_string() {
+    let file = String::from("test/test.txt");
+
+    let res = read_string(file);
+
+    assert_ok!(res);
+
+    if let Ok(s) = res {
+      assert_eq!(s, "This is a test doc!".to_string());
+    }
+  }
+
+  #[test]
+  fn check_read_string_fail() {
+    let file = String::from("test/");
+
+    let res = read_string(file);
+
+    assert_err!(res);
+
+    if let Err(Error(ErrorKind::File(e), _)) = res {
+      #[cfg(windows)]
+      assert_eq!(
+        e,
+        "Read_string failed: Access is denied. (os error 5)".to_string()
+      );
+      #[cfg(not(windows))]
+      assert_eq!(
+        e,
+        "Read_string failed: Is a directory (os error 21)".to_string()
+      );
+    }
+  }
+
+  #[test]
+  fn check_read_binary() {
+    let file = String::from("test/test_binary");
+
+    #[cfg(windows)]
+    let expected_vec = vec![
+      35, 33, 47, 98, 105, 110, 47, 98, 97, 115, 104, 13, 10, 13, 10, 101, 99, 104, 111, 32, 34,
+      72, 101, 108, 108, 111, 32, 116, 104, 101, 114, 101, 34,
+    ];
+    #[cfg(not(windows))]
+    let expected_vec = vec![
+      35, 33, 47, 98, 105, 110, 47, 98, 97, 115, 104, 10, 10, 101, 99, 104, 111, 32, 34, 72, 101,
+      108, 108, 111, 32, 116, 104, 101, 114, 101, 34,
+    ];
+
+    let res = read_binary(file);
+
+    assert_ok!(res);
+
+    if let Ok(vec) = res {
+      assert_eq!(vec, expected_vec);
+    }
+  }
+
+  #[test]
+  fn check_read_binary_fail() {
+    let file = String::from("test/");
+
+    let res = read_binary(file);
+
+    assert_err!(res);
+
+    if let Err(Error(ErrorKind::File(e), _)) = res {
+      #[cfg(windows)]
+      assert_eq!(
+        e,
+        "Read_binary failed: Access is denied. (os error 5)".to_string()
+      );
+      #[cfg(not(windows))]
+      assert_eq!(
+        e,
+        "Read_binary failed: Is a directory (os error 21)".to_string()
+      );
+    }
+  }
 }

+ 0 - 46
tauri-api/src/file/error.rs

@@ -1,46 +0,0 @@
-use std;
-use zip::result::ZipError;
-
-#[derive(Debug)]
-pub enum Error {
-  Extract(String),
-  Io(std::io::Error),
-  Zip(ZipError),
-}
-
-impl std::fmt::Display for Error {
-  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-    use Error::*;
-    match *self {
-      Extract(ref s) => write!(f, "ExtractError: {}", s),
-      Io(ref e) => write!(f, "IoError: {}", e),
-      Zip(ref e) => write!(f, "ZipError: {}", e),
-    }
-  }
-}
-
-impl std::error::Error for Error {
-  fn description(&self) -> &str {
-    "File Error"
-  }
-
-  fn cause(&self) -> Option<&dyn std::error::Error> {
-    use Error::*;
-    Some(match *self {
-      Io(ref e) => e,
-      _ => return None,
-    })
-  }
-}
-
-impl From<std::io::Error> for Error {
-  fn from(e: std::io::Error) -> Self {
-    Error::Io(e)
-  }
-}
-
-impl From<ZipError> for Error {
-  fn from(e: ZipError) -> Self {
-    Error::Zip(e)
-  }
-}

+ 11 - 13
tauri-api/src/file/extract.rs

@@ -3,7 +3,6 @@ use flate2;
 use tar;
 use zip;
 
-use crate::file::error::*;
 use either::Either;
 use std::fs;
 use std::io;
@@ -74,7 +73,7 @@ impl<'a> Extract<'a> {
   /// Extract an entire source archive into a specified path. If the source is a single compressed
   /// file and not an archive, it will be extracted into a file with the same name inside of
   /// `into_dir`.
-  pub fn extract_into(&self, into_dir: &path::Path) -> Result<(), Error> {
+  pub fn extract_into(&self, into_dir: &path::Path) -> crate::Result<()> {
     let source = fs::File::open(self.source)?;
     let archive = self
       .archive_format
@@ -90,14 +89,13 @@ impl<'a> Extract<'a> {
               Ok(_) => (),
               Err(e) => {
                 if e.kind() != io::ErrorKind::AlreadyExists {
-                  return Err(Error::Io(e));
+                  return Err(e.into());
                 }
               }
             }
-            let file_name = self
-              .source
-              .file_name()
-              .ok_or_else(|| Error::Extract("Extractor source has no file-name".into()))?;
+            let file_name = self.source.file_name().ok_or_else(|| {
+              crate::ErrorKind::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)?;
@@ -130,7 +128,7 @@ impl<'a> Extract<'a> {
     &self,
     into_dir: &path::Path,
     file_to_extract: T,
-  ) -> Result<(), Error> {
+  ) -> crate::Result<()> {
     let file_to_extract = file_to_extract.as_ref();
     let source = fs::File::open(self.source)?;
     let archive = self
@@ -147,13 +145,13 @@ impl<'a> Extract<'a> {
               Ok(_) => (),
               Err(e) => {
                 if e.kind() != io::ErrorKind::AlreadyExists {
-                  return Err(Error::Io(e));
+                  return Err(e.into());
                 }
               }
             }
-            let file_name = file_to_extract
-              .file_name()
-              .ok_or_else(|| Error::Extract("Extractor source has no file-name".into()))?;
+            let file_name = file_to_extract.file_name().ok_or_else(|| {
+              crate::ErrorKind::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)?;
@@ -165,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(|| {
-                Error::Extract(format!(
+                crate::ErrorKind::Extract(format!(
                   "Could not find the required path in the archive: {:?}",
                   file_to_extract
                 ))

+ 2 - 4
tauri-api/src/file/file_move.rs

@@ -1,8 +1,6 @@
 use std::fs;
 use std::path;
 
-use crate::file::error::*;
-
 /// Moves a file from the given path to the specified destination.
 ///
 /// `source` and `dest` must be on the same filesystem.
@@ -37,7 +35,7 @@ impl<'a> Move<'a> {
   }
 
   /// Move source file to specified destination
-  pub fn to_dest(&self, dest: &path::Path) -> Result<(), Error> {
+  pub fn to_dest(&self, dest: &path::Path) -> crate::Result<()> {
     match self.temp {
       None => {
         fs::rename(self.source, dest)?;
@@ -50,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(Error::from(e));
+            return Err(crate::Error::from(e));
           }
         } else {
           fs::rename(self.source, dest)?;

+ 24 - 0
tauri-api/src/lib.rs

@@ -10,3 +10,27 @@ pub mod file;
 pub mod rpc;
 
 pub mod version;
+
+use error_chain::error_chain;
+
+error_chain! {
+    foreign_links {
+        Io(::std::io::Error);
+        ZipError(::zip::result::ZipError);
+        SemVer(semver::SemVerError);
+    }
+    errors {
+        Extract(t: String) {
+            description("Extract Error")
+            display("Extract Error: '{}'", t)
+        }
+        Command(t: String) {
+            description("Command Execution Error")
+            display("Command Error: '{}'", t)
+        }
+        File(t: String) {
+            description("File function Error")
+            display("File Error: {}", t)
+        }
+    }
+}

+ 5 - 8
tauri-api/src/version.rs

@@ -1,10 +1,7 @@
 use semver::Version;
 
-mod error;
-pub use self::error::Error;
-
 /// Compare two semver versions
-pub fn compare(first: &str, second: &str) -> Result<i32, Error> {
+pub fn compare(first: &str, second: &str) -> crate::Result<i32> {
   let v1 = Version::parse(first)?;
   let v2 = Version::parse(second)?;
   if v1 > v2 {
@@ -17,7 +14,7 @@ pub fn compare(first: &str, second: &str) -> Result<i32, Error> {
 }
 
 /// Check if the "second" semver is compatible with the "first"
-pub fn is_compatible(first: &str, second: &str) -> Result<bool, Error> {
+pub fn is_compatible(first: &str, second: &str) -> crate::Result<bool> {
   let first = Version::parse(first)?;
   let second = Version::parse(second)?;
   Ok(if second.major == 0 && first.major == 0 {
@@ -32,21 +29,21 @@ pub fn is_compatible(first: &str, second: &str) -> Result<bool, Error> {
 }
 
 /// Check if a the "other" version is a major bump from the "current"
-pub fn is_major(current: &str, other: &str) -> Result<bool, Error> {
+pub fn is_major(current: &str, other: &str) -> crate::Result<bool> {
   let current = Version::parse(current)?;
   let other = Version::parse(other)?;
   Ok(other.major > current.major)
 }
 
 /// Check if a the "other" version is a minor bump from the "current"
-pub fn is_minor(current: &str, other: &str) -> Result<bool, Error> {
+pub fn is_minor(current: &str, other: &str) -> crate::Result<bool> {
   let current = Version::parse(current)?;
   let other = Version::parse(other)?;
   Ok(current.major == other.major && other.minor > current.minor)
 }
 
 /// Check if a the "other" version is a patch bump from the "current"
-pub fn is_patch(current: &str, other: &str) -> Result<bool, Error> {
+pub fn is_patch(current: &str, other: &str) -> crate::Result<bool> {
   let current = Version::parse(current)?;
   let other = Version::parse(other)?;
   Ok(current.major == other.major && current.minor == other.minor && other.patch > current.patch)

+ 0 - 35
tauri-api/src/version/error.rs

@@ -1,35 +0,0 @@
-use semver;
-use std;
-
-#[derive(Debug)]
-pub enum Error {
-  SemVer(semver::SemVerError),
-}
-
-impl std::fmt::Display for Error {
-  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-    use Error::*;
-    match *self {
-      SemVer(ref e) => write!(f, "SemVerError: {}", e),
-    }
-  }
-}
-
-impl std::error::Error for Error {
-  fn description(&self) -> &str {
-    "Version Error"
-  }
-
-  fn cause(&self) -> Option<&dyn std::error::Error> {
-    use Error::*;
-    Some(match *self {
-      SemVer(ref e) => e,
-    })
-  }
-}
-
-impl From<semver::SemVerError> for Error {
-  fn from(e: semver::SemVerError) -> Self {
-    Error::SemVer(e)
-  }
-}

+ 1 - 0
tauri-api/test/test.txt

@@ -0,0 +1 @@
+This is a test doc!

+ 3 - 0
tauri-api/test/test_binary

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+echo "Hello there"

+ 23 - 14
tauri-updater/src/updater/error.rs

@@ -1,8 +1,9 @@
 use crate::http;
 use reqwest;
 use std;
-use tauri_api::file;
-use tauri_api::version;
+use tauri_api;
+// use tauri_api::file;
+// use tauri_api::version;
 use zip::result::ZipError;
 
 #[derive(Debug)]
@@ -13,8 +14,9 @@ pub enum Error {
   Config(String),
   Io(std::io::Error),
   Zip(ZipError),
-  File(file::Error),
-  Version(version::Error),
+  API(tauri_api::Error),
+  // File(file::Error),
+  // Version(version::Error),
 }
 
 impl std::fmt::Display for Error {
@@ -27,8 +29,9 @@ impl std::fmt::Display for Error {
       Config(ref s) => write!(f, "ConfigError: {}", s),
       Io(ref e) => write!(f, "IoError: {}", e),
       Zip(ref e) => write!(f, "ZipError: {}", e),
-      File(ref e) => write!(f, "FileError: {}", e),
-      Version(ref e) => write!(f, "VersionError: {}", e),
+      API(ref e) => write!(f, "APIError: {}", e),
+      // File(ref e) => write!(f, "FileError: {}", e),
+      // Version(ref e) => write!(f, "VersionError: {}", e),
     }
   }
 }
@@ -53,11 +56,11 @@ impl From<std::io::Error> for Error {
   }
 }
 
-impl From<file::Error> for Error {
-  fn from(e: file::Error) -> Self {
-    Error::File(e)
-  }
-}
+// impl From<file::Error> for Error {
+//   fn from(e: file::Error) -> Self {
+//     Error::File(e)
+//   }
+// }
 
 impl From<http::Error> for Error {
   fn from(e: http::Error) -> Self {
@@ -71,8 +74,14 @@ impl From<reqwest::Error> for Error {
   }
 }
 
-impl From<version::Error> for Error {
-  fn from(e: version::Error) -> Self {
-    Error::Version(e)
+impl From<tauri_api::Error> for Error {
+  fn from(e: tauri_api::Error) -> Self {
+    Error::API(e)
   }
 }
+
+// impl From<version::Error> for Error {
+//   fn from(e: version::Error) -> Self {
+//     Error::Version(e)
+//   }
+// }

+ 16 - 10
tauri/src/file_system.rs

@@ -16,6 +16,7 @@ pub fn list<T: 'static>(
     webview,
     move || {
       dir::walk_dir(path.to_string())
+        .map_err(|e| e.to_string())
         .and_then(|f| serde_json::to_string(&f).map_err(|err| err.to_string()))
     },
     callback,
@@ -33,6 +34,7 @@ pub fn list_dirs<T: 'static>(
     webview,
     move || {
       dir::list_dir_contents(&path)
+        .map_err(|e| e.to_string())
         .and_then(|f| serde_json::to_string(&f).map_err(|err| err.to_string()))
     },
     callback,
@@ -72,11 +74,13 @@ pub fn read_text_file<T: 'static>(
   crate::execute_promise(
     webview,
     move || {
-      file::read_string(path).and_then(|f| {
-        serde_json::to_string(&f)
-          .map_err(|err| err.to_string())
-          .map(|s| s.to_string())
-      })
+      file::read_string(path)
+        .map_err(|e| e.to_string())
+        .and_then(|f| {
+          serde_json::to_string(&f)
+            .map_err(|err| err.to_string())
+            .map(|s| s.to_string())
+        })
     },
     callback,
     error,
@@ -92,11 +96,13 @@ pub fn read_binary_file<T: 'static>(
   crate::execute_promise(
     webview,
     move || {
-      file::read_binary(path).and_then(|f| {
-        serde_json::to_string(&f)
-          .map_err(|err| err.to_string())
-          .map(|s| s.to_string())
-      })
+      file::read_binary(path)
+        .map_err(|e| e.to_string())
+        .and_then(|f| {
+          serde_json::to_string(&f)
+            .map_err(|err| err.to_string())
+            .map(|s| s.to_string())
+        })
     },
     callback,
     error,