Upgrade rust/crates/which to 4.0.1

Test: make
Change-Id: Ib1b3363614d4c215d826a75dfebb2fa8517f1067
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 98aa420..eb684ab 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
 {
   "git": {
-    "sha1": "1ffb2479652982ab8aaa1706bba6de5281a7ba22"
+    "sha1": "e5039c15d1202a59b9e35d628263134cf92514fe"
   }
 }
diff --git a/Android.bp b/Android.bp
index 5313564..827b994 100644
--- a/Android.bp
+++ b/Android.bp
@@ -8,8 +8,15 @@
     edition: "2015",
     rustlibs: [
         "liblibc",
+        "libthiserror",
     ],
 }
 
 // dependent_library ["feature_list"]
 //   libc-0.2.72 "default,std"
+//   proc-macro2-1.0.18 "default,proc-macro"
+//   quote-1.0.7 "default,proc-macro"
+//   syn-1.0.34 "clone-impls,default,derive,parsing,printing,proc-macro,quote"
+//   thiserror-1.0.20
+//   thiserror-impl-1.0.20
+//   unicode-xid-0.2.1 "default"
diff --git a/Cargo.toml b/Cargo.toml
index 567792b..d5f14ac 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,7 @@
 
 [package]
 name = "which"
-version = "3.1.1"
+version = "4.0.1"
 authors = ["Harry Fei <tiziyuanfang@gmail.com>"]
 description = "A Rust equivalent of Unix command \"which\". Locate installed executable in cross platforms."
 documentation = "https://docs.rs/which/"
@@ -21,16 +21,10 @@
 categories = ["os", "filesystem"]
 license = "MIT"
 repository = "https://github.com/harryfei/which-rs.git"
-[dependencies.failure]
-version = "0.1.7"
-features = ["std"]
-optional = true
-default-features = false
-
 [dependencies.libc]
 version = "0.2.65"
+
+[dependencies.thiserror]
+version = "1.0"
 [dev-dependencies.tempdir]
 version = "0.3.7"
-
-[features]
-default = ["failure"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 2c353c8..34399d6 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "which"
-version = "3.1.1"
+version = "4.0.1"
 authors = ["Harry Fei <tiziyuanfang@gmail.com>"]
 repository = "https://github.com/harryfei/which-rs.git"
 documentation = "https://docs.rs/which/"
@@ -12,15 +12,7 @@
 
 [dependencies]
 libc = "0.2.65"
-
-[dependencies.failure]
-version = "0.1.7"
-default-features = false
-features = ["std"]
-optional = true
+thiserror = "1.0"
 
 [dev-dependencies]
 tempdir = "0.3.7"
-
-[features]
-default = ["failure"]
diff --git a/METADATA b/METADATA
index 9595f0d..6c5876e 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@
     type: GIT
     value: "https://github.com/harryfei/which-rs.git"
   }
-  version: "3.1.1"
+  version: "4.0.1"
   license_type: NOTICE
   last_upgrade_date {
     year: 2020
-    month: 3
-    day: 31
+    month: 7
+    day: 10
   }
 }
diff --git a/README.md b/README.md
index 2c8d7e1..eb2a562 100644
--- a/README.md
+++ b/README.md
@@ -22,13 +22,6 @@
 assert_eq!(result, PathBuf::from("/usr/bin/rustc"));
 ```
 
-## Errors
-
-By default this crate exposes a [`failure`] based error. This is optional, disable the default
-features to get an error type implementing the standard library `Error` trait.
-
-[`failure`]: https://crates.io/crates/failure
-
 ## Documentation
 
 The documentation is [available online](https://docs.rs/which/).
diff --git a/src/checker.rs b/src/checker.rs
index 6021711..817ae2f 100644
--- a/src/checker.rs
+++ b/src/checker.rs
@@ -39,6 +39,14 @@
 }
 
 impl Checker for ExistedChecker {
+    #[cfg(target_os="windows")]
+    fn is_valid(&self, path: &Path) -> bool {
+        fs::symlink_metadata(path)
+            .map(|metadata| metadata.is_file())
+            .unwrap_or(false)
+    }
+
+    #[cfg(not(target_os="windows"))]
     fn is_valid(&self, path: &Path) -> bool {
         fs::metadata(path)
             .map(|metadata| metadata.is_file())
diff --git a/src/error.rs b/src/error.rs
index c75fe4c..708c884 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,92 +1,17 @@
-#[cfg(feature = "failure")]
-use failure::{Backtrace, Context, Fail};
-use std;
-use std::fmt::{self, Display};
-
-#[derive(Debug)]
-pub struct Error {
-    #[cfg(feature = "failure")]
-    inner: Context<ErrorKind>,
-    #[cfg(not(feature = "failure"))]
-    inner: ErrorKind,
-}
-
-// To suppress false positives from cargo-clippy
-#[cfg_attr(feature = "cargo-clippy", allow(empty_line_after_outer_attr))]
-#[derive(Copy, Clone, Eq, PartialEq, Debug)]
-pub enum ErrorKind {
-    BadAbsolutePath,
-    BadRelativePath,
-    CannotFindBinaryPath,
-    CannotGetCurrentDir,
-    CannotCanonicalize,
-}
-
-#[cfg(feature = "failure")]
-impl Fail for ErrorKind {}
-
-impl Display for ErrorKind {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let display = match *self {
-            ErrorKind::BadAbsolutePath => "Bad absolute path",
-            ErrorKind::BadRelativePath => "Bad relative path",
-            ErrorKind::CannotFindBinaryPath => "Cannot find binary path",
-            ErrorKind::CannotGetCurrentDir => "Cannot get current directory",
-            ErrorKind::CannotCanonicalize => "Cannot canonicalize path",
-        };
-        f.write_str(display)
-    }
-}
-
-#[cfg(feature = "failure")]
-impl Fail for Error {
-    fn cause(&self) -> Option<&dyn Fail> {
-        self.inner.cause()
-    }
-
-    fn backtrace(&self) -> Option<&Backtrace> {
-        self.inner.backtrace()
-    }
-}
-
-#[cfg(not(feature = "failure"))]
-impl std::error::Error for Error {}
-
-impl Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        Display::fmt(&self.inner, f)
-    }
-}
-
-impl Error {
-    pub fn kind(&self) -> ErrorKind {
-        #[cfg(feature = "failure")]
-        {
-            *self.inner.get_context()
-        }
-        #[cfg(not(feature = "failure"))]
-        {
-            self.inner
-        }
-    }
-}
-
-impl From<ErrorKind> for Error {
-    fn from(kind: ErrorKind) -> Error {
-        Error {
-            #[cfg(feature = "failure")]
-            inner: Context::new(kind),
-            #[cfg(not(feature = "failure"))]
-            inner: kind,
-        }
-    }
-}
-
-#[cfg(feature = "failure")]
-impl From<Context<ErrorKind>> for Error {
-    fn from(inner: Context<ErrorKind>) -> Error {
-        Error { inner }
-    }
-}
+use thiserror;
 
 pub type Result<T> = std::result::Result<T, Error>;
+
+#[derive(thiserror::Error, Copy, Clone, Eq, PartialEq, Debug)]
+pub enum Error {
+    #[error("bad absolute path")]
+    BadAbsolutePath,
+    #[error("bad relative path")]
+    BadRelativePath,
+    #[error("cannot find binary path")]
+    CannotFindBinaryPath,
+    #[error("cannot get current directory")]
+    CannotGetCurrentDir,
+    #[error("cannot canonicalize path")]
+    CannotCanonicalize,
+}
diff --git a/src/finder.rs b/src/finder.rs
index 2519aa8..d23cbaa 100644
--- a/src/finder.rs
+++ b/src/finder.rs
@@ -66,7 +66,7 @@
             Box::new(candidates)
         } else {
             // Search binary in PATHs(defined in environment variable).
-            let p = paths.ok_or(ErrorKind::CannotFindBinaryPath)?;
+            let p = paths.ok_or(Error::CannotFindBinaryPath)?;
             let paths: Vec<_> = env::split_paths(&p).collect();
 
             let candidates = Self::path_search_candidates(path, paths).into_iter();
@@ -82,7 +82,7 @@
         }
 
         // can't find any binary
-        return Err(ErrorKind::CannotFindBinaryPath.into());
+        Err(Error::CannotFindBinaryPath)
     }
 
     fn cwd_search_candidates<C>(binary_name: PathBuf, cwd: C) -> impl IntoIterator<Item = PathBuf>
diff --git a/src/lib.rs b/src/lib.rs
index 42a6963..8ea0e7e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -13,12 +13,9 @@
 //!
 //! ```
 
-#[cfg(feature = "failure")]
-extern crate failure;
 extern crate libc;
+extern crate thiserror;
 
-#[cfg(feature = "failure")]
-use failure::ResultExt;
 mod checker;
 mod error;
 mod finder;
@@ -59,10 +56,7 @@
 ///
 /// ```
 pub fn which<T: AsRef<OsStr>>(binary_name: T) -> Result<path::PathBuf> {
-    #[cfg(feature = "failure")]
-    let cwd = env::current_dir().context(ErrorKind::CannotGetCurrentDir)?;
-    #[cfg(not(feature = "failure"))]
-    let cwd = env::current_dir().map_err(|_| ErrorKind::CannotGetCurrentDir)?;
+    let cwd = env::current_dir().map_err(|_| Error::CannotGetCurrentDir)?;
 
     which_in(binary_name, env::var_os("PATH"), &cwd)
 }
@@ -194,10 +188,7 @@
     /// This calls `which` and `Path::canonicalize` and maps the result into a `CanonicalPath`.
     pub fn new<T: AsRef<OsStr>>(binary_name: T) -> Result<CanonicalPath> {
         which(binary_name)
-            .and_then(|p| {
-                p.canonicalize()
-                    .map_err(|_| ErrorKind::CannotCanonicalize.into())
-            })
+            .and_then(|p| p.canonicalize().map_err(|_| Error::CannotCanonicalize))
             .map(|inner| CanonicalPath { inner })
     }
 
@@ -212,10 +203,7 @@
         V: AsRef<path::Path>,
     {
         which_in(binary_name, paths, cwd)
-            .and_then(|p| {
-                p.canonicalize()
-                    .map_err(|_| ErrorKind::CannotCanonicalize.into())
-            })
+            .and_then(|p| p.canonicalize().map_err(|_| Error::CannotCanonicalize))
             .map(|inner| CanonicalPath { inner })
     }
 
diff --git a/tests/basic.rs b/tests/basic.rs
index b6ba30d..24a700d 100644
--- a/tests/basic.rs
+++ b/tests/basic.rs
@@ -293,12 +293,10 @@
 }
 
 #[test]
-#[cfg(feature = "failure")]
 fn test_failure() {
     let f = TestFixture::new();
 
-    let run = || -> std::result::Result<PathBuf, failure::Error> {
-        // Test the conversion to failure
+    let run = || -> which::Result<PathBuf> {
         let p = _which(&f, "./b/bin")?;
         Ok(p.into_path_buf())
     };