Update which to 4.2.4 am: 413469211c am: d4a8e3fb8d am: 8bc650c94f am: 90fdb407fc

Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/which/+/2004691

Change-Id: I3651ff13e3ffa938b9f97760a4bb3b363e536d65
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 26fe28d..692ca11 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "bdd46e52931db0b693e30bc08c4edfa499392903"
-  }
-}
+    "sha1": "8fbe34239c16af9cd253e36e9c2d3384f9b55f83"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 5ac490b..dd380d3 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -1,23 +1,93 @@
-name: Rust
-
-on: [push, pull_request]
-
-env:
-  CARGO_TERM_COLOR: always
+name: Main workflow
+on:
+  push:
+  pull_request:
 
 jobs:
-  test:
-    name: Build and test
+  # Run the `rustfmt` code formatter
+  rustfmt:
+    name: Rustfmt [Formatter]
+    runs-on: ubuntu-latest
+    steps:
+      - name: Setup | Checkout
+        uses: actions/checkout@v2
+
+      - name: Setup | Rust
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: stable
+          override: true
+          profile: minimal
+          components: rustfmt
+
+      - name: Build | Format
+        run: cargo fmt --all -- --check
+
+  # Run the `clippy` linting tool
+  clippy:
+    name: Clippy [Linter]
+    strategy:
+      matrix:
+        os: [ubuntu-latest]
     runs-on: ${{ matrix.os }}
+    steps:
+      - name: Setup | Checkout
+        uses: actions/checkout@v2
+
+      - name: Setup | Rust
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: stable
+          override: true
+          profile: minimal
+          components: clippy
+
+      - name: Build | Lint
+        uses: actions-rs/cargo@v1
+        with:
+          command: clippy
+          args: --workspace --all-targets --all-features
+
+  # Ensure that the project could be successfully compiled
+  cargo_check:
+    name: Compile
+    runs-on: ubuntu-latest
+    steps:
+      - name: Setup | Checkout
+        uses: actions/checkout@v2
+
+      - name: Setup | Rust
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: stable
+          profile: minimal
+          override: true
+
+      - name: Build | Check
+        run: cargo check --workspace
+
+  # Run tests on Linux, macOS, and Windows
+  # On both Rust stable and Rust nightly
+  test:
+    name: Test Suite
+    runs-on: ${{ matrix.os }}
+    needs: cargo_check # First check then run expansive tests
     strategy:
       fail-fast: false
       matrix:
-        os:
-          - ubuntu-latest
-          - windows-latest
-          - macos-latest
-
+        os: [ubuntu-latest, windows-latest]
+        rust: [stable, nightly]
     steps:
-      - uses: actions/checkout@v2
-      - run: cargo build --verbose
-      - run: cargo test --verbose
+      - name: Setup | Checkout
+        uses: actions/checkout@v2
+
+      - name: Setup | Rust
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: ${{ matrix.rust }}
+          profile: minimal
+          override: true
+
+      # Run the ignored tests that expect the above setup
+      - name: Build | Test
+        run: cargo test --workspace --all-features -- -Z unstable-options --include-ignored
diff --git a/Android.bp b/Android.bp
index 9ab98c9..3d469f9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -23,7 +23,7 @@
     host_supported: true,
     crate_name: "which",
     cargo_env_compat: true,
-    cargo_pkg_version: "4.2.2",
+    cargo_pkg_version: "4.2.4",
     srcs: ["src/lib.rs"],
     edition: "2018",
     rustlibs: [
diff --git a/Cargo.toml b/Cargo.toml
index 7814b7b..850a29c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,17 +3,16 @@
 # When uploading crates to the registry Cargo will automatically
 # "normalize" Cargo.toml files for maximal compatibility
 # with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
 #
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
 
 [package]
 edition = "2018"
 name = "which"
-version = "4.2.2"
+version = "4.2.4"
 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/"
@@ -22,6 +21,8 @@
 categories = ["os", "filesystem"]
 license = "MIT"
 repository = "https://github.com/harryfei/which-rs.git"
+[package.metadata.docs.rs]
+all-features = true
 [dependencies.either]
 version = "1.6"
 
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 12b29d3..ec31c55 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "which"
-version = "4.2.2"
+version = "4.2.4"
 edition = "2018"
 authors = ["Harry Fei <tiziyuanfang@gmail.com>"]
 repository = "https://github.com/harryfei/which-rs.git"
@@ -21,3 +21,6 @@
 
 [dev-dependencies]
 tempdir = "0.3.7"
+
+[package.metadata.docs.rs]
+all-features = true
diff --git a/METADATA b/METADATA
index ea19f37..6a034c4 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/which/which-4.2.2.crate"
+    value: "https://static.crates.io/crates/which/which-4.2.4.crate"
   }
-  version: "4.2.2"
+  version: "4.2.4"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2021
-    month: 8
-    day: 9
+    year: 2022
+    month: 3
+    day: 1
   }
 }
diff --git a/README.md b/README.md
index f20f929..5615c36 100644
--- a/README.md
+++ b/README.md
@@ -10,16 +10,25 @@
 * Windows
 * macOS
 
-## Example
+## Examples
 
-To find which rustc exectable binary is using.
+1) To find which rustc executable binary is using.
 
-``` rust
-use which::which;
+    ``` rust
+    use which::which;
 
-let result = which::which("rustc").unwrap();
-assert_eq!(result, PathBuf::from("/usr/bin/rustc"));
-```
+    let result = which("rustc").unwrap();
+    assert_eq!(result, PathBuf::from("/usr/bin/rustc"));
+    ```
+
+2. After enabling the `regex` feature, find all cargo subcommand executables on the path:
+
+    ``` rust
+    use which::which_re;
+
+    which_re(Regex::new("^cargo-.*").unwrap()).unwrap()
+        .for_each(|pth| println!("{}", pth.to_string_lossy()));
+    ```
 
 ## Documentation
 
diff --git a/src/finder.rs b/src/finder.rs
index 416ee3c..43b659d 100644
--- a/src/finder.rs
+++ b/src/finder.rs
@@ -5,6 +5,8 @@
 use either::Either;
 #[cfg(feature = "regex")]
 use regex::Regex;
+#[cfg(feature = "regex")]
+use std::borrow::Borrow;
 use std::env;
 use std::ffi::OsStr;
 #[cfg(feature = "regex")]
@@ -54,7 +56,7 @@
         &self,
         binary_name: T,
         paths: Option<U>,
-        cwd: V,
+        cwd: Option<V>,
         binary_checker: CompositeChecker,
     ) -> Result<impl Iterator<Item = PathBuf>>
     where
@@ -64,15 +66,18 @@
     {
         let path = PathBuf::from(&binary_name);
 
-        let binary_path_candidates = if path.has_separator() {
-            // Search binary in cwd if the path have a path separator.
-            Either::Left(Self::cwd_search_candidates(path, cwd).into_iter())
-        } else {
-            // Search binary in PATHs(defined in environment variable).
-            let p = paths.ok_or(Error::CannotFindBinaryPath)?;
-            let paths: Vec<_> = env::split_paths(&p).collect();
+        let binary_path_candidates = match cwd {
+            Some(cwd) if path.has_separator() => {
+                // Search binary in cwd if the path have a path separator.
+                Either::Left(Self::cwd_search_candidates(path, cwd).into_iter())
+            }
+            _ => {
+                // Search binary in PATHs(defined in environment variable).
+                let p = paths.ok_or(Error::CannotFindBinaryPath)?;
+                let paths: Vec<_> = env::split_paths(&p).collect();
 
-            Either::Right(Self::path_search_candidates(path, paths).into_iter())
+                Either::Right(Self::path_search_candidates(path, paths).into_iter())
+            }
         };
 
         Ok(binary_path_candidates.filter(move |p| binary_checker.is_valid(p)))
@@ -81,7 +86,7 @@
     #[cfg(feature = "regex")]
     pub fn find_re<T>(
         &self,
-        binary_regex: Regex,
+        binary_regex: impl Borrow<Regex>,
         paths: Option<T>,
         binary_checker: CompositeChecker,
     ) -> Result<impl Iterator<Item = PathBuf>>
@@ -99,7 +104,7 @@
             .map(|e| e.path())
             .filter(move |p| {
                 if let Some(unicode_file_name) = p.file_name().unwrap().to_str() {
-                    binary_regex.is_match(unicode_file_name)
+                    binary_regex.borrow().is_match(unicode_file_name)
                 } else {
                     false
                 }
@@ -153,7 +158,7 @@
                     .map(|pathext| {
                         pathext.split(';')
                             .filter_map(|s| {
-                                if s.as_bytes()[0] == b'.' {
+                                if s.as_bytes().first() == Some(&b'.') {
                                     Some(s.to_owned())
                                 } else {
                                     // Invalid segment; just ignore it.
diff --git a/src/lib.rs b/src/lib.rs
index d9377f5..2b27094 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,7 +9,7 @@
 //! use which::which;
 //! use std::path::PathBuf;
 //!
-//! let result = which::which("rustc").unwrap();
+//! let result = which("rustc").unwrap();
 //! assert_eq!(result, PathBuf::from("/usr/bin/rustc"));
 //!
 //! ```
@@ -26,6 +26,8 @@
 
 #[cfg(feature = "regex")]
 use regex::Regex;
+#[cfg(feature = "regex")]
+use std::borrow::Borrow;
 use std::env;
 use std::fmt;
 use std::path;
@@ -63,19 +65,27 @@
 
 /// Find all binaries with `binary_name` in the path list `paths`, using `cwd` to resolve relative paths.
 pub fn which_all<T: AsRef<OsStr>>(binary_name: T) -> Result<impl Iterator<Item = path::PathBuf>> {
-    let cwd = env::current_dir().map_err(|_| Error::CannotGetCurrentDir)?;
+    let cwd = env::current_dir().ok();
 
-    which_in_all(binary_name, env::var_os("PATH"), cwd)
+    let binary_checker = build_binary_checker();
+
+    let finder = Finder::new();
+
+    finder.find(binary_name, env::var_os("PATH"), cwd, binary_checker)
 }
 
 /// Find all binaries matching a regular expression in a the system PATH.
 ///
+/// Only available when feature `regex` is enabled.
+///
 /// # Arguments
 ///
 /// * `regex` - A regular expression to match binaries with
 ///
 /// # Examples
 ///
+/// Find Python executables:
+///
 /// ```no_run
 /// use regex::Regex;
 /// use which::which;
@@ -86,8 +96,18 @@
 /// let python_paths = vec![PathBuf::from("/usr/bin/python2"), PathBuf::from("/usr/bin/python3")];
 /// assert_eq!(binaries, python_paths);
 /// ```
+///
+/// Find all cargo subcommand executables on the path:
+///
+/// ```
+/// use which::which_re;
+/// use regex::Regex;
+///
+/// which_re(Regex::new("^cargo-.*").unwrap()).unwrap()
+///     .for_each(|pth| println!("{}", pth.to_string_lossy()));
+/// ```
 #[cfg(feature = "regex")]
-pub fn which_re(regex: Regex) -> Result<impl Iterator<Item = path::PathBuf>> {
+pub fn which_re(regex: impl Borrow<Regex>) -> Result<impl Iterator<Item = path::PathBuf>> {
     which_re_in(regex, env::var_os("PATH"))
 }
 
@@ -104,6 +124,8 @@
 
 /// Find all binaries matching a regular expression in a list of paths.
 ///
+/// Only available when feature `regex` is enabled.
+///
 /// # Arguments
 ///
 /// * `regex` - A regular expression to match binaries with
@@ -124,13 +146,14 @@
 /// assert_eq!(binaries, python_paths);
 /// ```
 #[cfg(feature = "regex")]
-pub fn which_re_in<T>(regex: Regex, paths: Option<T>) -> Result<impl Iterator<Item = path::PathBuf>>
+pub fn which_re_in<T>(
+    regex: impl Borrow<Regex>,
+    paths: Option<T>,
+) -> Result<impl Iterator<Item = path::PathBuf>>
 where
     T: AsRef<OsStr>,
 {
-    let binary_checker = CompositeChecker::new()
-        .add_checker(Box::new(ExistedChecker::new()))
-        .add_checker(Box::new(ExecutableChecker::new()));
+    let binary_checker = build_binary_checker();
 
     let finder = Finder::new();
 
@@ -148,13 +171,17 @@
     U: AsRef<OsStr>,
     V: AsRef<path::Path>,
 {
-    let binary_checker = CompositeChecker::new()
-        .add_checker(Box::new(ExistedChecker::new()))
-        .add_checker(Box::new(ExecutableChecker::new()));
+    let binary_checker = build_binary_checker();
 
     let finder = Finder::new();
 
-    finder.find(binary_name, paths, cwd, binary_checker)
+    finder.find(binary_name, paths, Some(cwd), binary_checker)
+}
+
+fn build_binary_checker() -> CompositeChecker {
+    CompositeChecker::new()
+        .add_checker(Box::new(ExistedChecker::new()))
+        .add_checker(Box::new(ExecutableChecker::new()))
 }
 
 /// An owned, immutable wrapper around a `PathBuf` containing the path of an executable.
diff --git a/tests/basic.rs b/tests/basic.rs
index e3bc73c..897e912 100644
--- a/tests/basic.rs
+++ b/tests/basic.rs
@@ -141,8 +141,11 @@
         .collect();
 
     let temp = f.tempdir;
-    
-    assert_eq!(result, vec![temp.path().join("a/bin_0"), temp.path().join("b/bin_1")])
+
+    assert_eq!(
+        result,
+        vec![temp.path().join("a/bin_0"), temp.path().join("b/bin_1")]
+    )
 }
 
 #[test]
@@ -160,6 +163,15 @@
 }
 
 #[test]
+#[cfg(all(unix, feature = "regex"))]
+fn test_which_re_accepts_owned_and_borrow() {
+    which::which_re(Regex::new(r".").unwrap());
+    which::which_re(&Regex::new(r".").unwrap());
+    which::which_re_in(Regex::new(r".").unwrap(), Some("pth"));
+    which::which_re_in(&Regex::new(r".").unwrap(), Some("pth"));
+}
+
+#[test]
 #[cfg(unix)]
 fn test_which_extension() {
     let f = TestFixture::new();