Upgrade which to 4.4.0 am: a065455574 am: 26caf7138b am: 67111d64eb am: bcfaaa4c96

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

Change-Id: If7934d479e3c0924f7c7ec893e6c20fedd2d129d
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index d0e4fff..0dcc2ff 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "492df704947be42c30f3bc7947e75244f26a0a45"
+    "sha1": "13722854453a50002d72faa1d0960f70b68ceea4"
   },
   "path_in_vcs": ""
 }
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index bc8bec7..e4167ea 100644
--- a/Android.bp
+++ b/Android.bp
@@ -20,10 +20,11 @@
 
 rust_library {
     name: "libwhich",
+    // has rustc warnings
     host_supported: true,
     crate_name: "which",
     cargo_env_compat: true,
-    cargo_pkg_version: "4.3.0",
+    cargo_pkg_version: "4.4.0",
     srcs: ["src/lib.rs"],
     edition: "2018",
     rustlibs: [
diff --git a/Cargo.toml b/Cargo.toml
index 84d671a..ff6894a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,7 @@
 [package]
 edition = "2018"
 name = "which"
-version = "4.3.0"
+version = "4.4.0"
 authors = ["Harry Fei <[email protected]>"]
 description = "A Rust equivalent of Unix command \"which\". Locate installed executable in cross platforms."
 documentation = "https://docs.rs/which/"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index d8251f8..e05adb3 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
 [package]
 name = "which"
-version = "4.3.0"
+version = "4.4.0"
 edition = "2018"
 authors = ["Harry Fei <[email protected]>"]
 repository = "https://github.com/harryfei/which-rs.git"
diff --git a/METADATA b/METADATA
index 36e9b3e..d2123d9 100644
--- a/METADATA
+++ b/METADATA
@@ -11,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/which/which-4.3.0.crate"
+    value: "https://static.crates.io/crates/which/which-4.4.0.crate"
   }
-  version: "4.3.0"
+  version: "4.4.0"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2022
-    month: 12
-    day: 19
+    year: 2023
+    month: 2
+    day: 17
   }
 }
diff --git a/src/lib.rs b/src/lib.rs
index b9026ff..3e556eb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -21,14 +21,12 @@
 mod helper;
 
 #[cfg(feature = "regex")]
-use regex::Regex;
-#[cfg(feature = "regex")]
 use std::borrow::Borrow;
 use std::env;
 use std::fmt;
 use std::path;
 
-use std::ffi::OsStr;
+use std::ffi::{OsStr, OsString};
 
 use crate::checker::{CompositeChecker, ExecutableChecker, ExistedChecker};
 pub use crate::error::*;
@@ -59,7 +57,31 @@
     which_all(binary_name).and_then(|mut i| i.next().ok_or(Error::CannotFindBinaryPath))
 }
 
-/// Find all binaries with `binary_name` in the path list `paths`, using `cwd` to resolve relative paths.
+/// Find an executable binary's path by name, ignoring `cwd`.
+///
+/// If given an absolute path, returns it if the file exists and is executable.
+///
+/// Does not resolve relative paths.
+///
+/// If given a string without path separators, looks for a file named
+/// `binary_name` at each directory in `$PATH` and if it finds an executable
+/// file there, returns it.
+///
+/// # Example
+///
+/// ```no_run
+/// use which::which;
+/// use std::path::PathBuf;
+///
+/// let result = which::which_global("rustc").unwrap();
+/// assert_eq!(result, PathBuf::from("/usr/bin/rustc"));
+///
+/// ```
+pub fn which_global<T: AsRef<OsStr>>(binary_name: T) -> Result<path::PathBuf> {
+    which_all_global(binary_name).and_then(|mut i| i.next().ok_or(Error::CannotFindBinaryPath))
+}
+
+/// Find all binaries with `binary_name` 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().ok();
 
@@ -70,6 +92,22 @@
     finder.find(binary_name, env::var_os("PATH"), cwd, binary_checker)
 }
 
+/// Find all binaries with `binary_name` ignoring `cwd`.
+pub fn which_all_global<T: AsRef<OsStr>>(
+    binary_name: T,
+) -> Result<impl Iterator<Item = path::PathBuf>> {
+    let binary_checker = build_binary_checker();
+
+    let finder = Finder::new();
+
+    finder.find(
+        binary_name,
+        env::var_os("PATH"),
+        Option::<&Path>::None,
+        binary_checker,
+    )
+}
+
 /// Find all binaries matching a regular expression in a the system PATH.
 ///
 /// Only available when feature `regex` is enabled.
@@ -174,12 +212,183 @@
     finder.find(binary_name, paths, Some(cwd), binary_checker)
 }
 
+/// Find all binaries with `binary_name` in the path list `paths`, ignoring `cwd`.
+pub fn which_in_global<T, U>(
+    binary_name: T,
+    paths: Option<U>,
+) -> Result<impl Iterator<Item = path::PathBuf>>
+where
+    T: AsRef<OsStr>,
+    U: AsRef<OsStr>,
+{
+    let binary_checker = build_binary_checker();
+
+    let finder = Finder::new();
+
+    finder.find(binary_name, paths, Option::<&Path>::None, binary_checker)
+}
+
 fn build_binary_checker() -> CompositeChecker {
     CompositeChecker::new()
         .add_checker(Box::new(ExistedChecker::new()))
         .add_checker(Box::new(ExecutableChecker::new()))
 }
 
+/// A wrapper containing all functionality in this crate.
+pub struct WhichConfig {
+    cwd: Option<either::Either<bool, path::PathBuf>>,
+    custom_path_list: Option<OsString>,
+    binary_name: Option<OsString>,
+    #[cfg(feature = "regex")]
+    regex: Option<Regex>,
+}
+
+impl Default for WhichConfig {
+    fn default() -> Self {
+        Self {
+            cwd: Some(either::Either::Left(true)),
+            custom_path_list: None,
+            binary_name: None,
+            #[cfg(feature = "regex")]
+            regex: None,
+        }
+    }
+}
+
+#[cfg(feature = "regex")]
+type Regex = regex::Regex;
+
+#[cfg(not(feature = "regex"))]
+type Regex = ();
+
+impl WhichConfig {
+    pub fn new() -> Self {
+        Self::default()
+    }
+
+    /// Whether or not to use the current working directory. `true` by default.
+    ///
+    /// # Panics
+    ///
+    /// If regex was set previously, and you've just passed in `use_cwd: true`, this will panic.
+    pub fn system_cwd(mut self, use_cwd: bool) -> Self {
+        #[cfg(feature = "regex")]
+        if self.regex.is_some() && use_cwd {
+            panic!("which can't use regex and cwd at the same time!")
+        }
+        self.cwd = Some(either::Either::Left(use_cwd));
+        self
+    }
+
+    /// Sets a custom path for resolving relative paths.
+    ///
+    /// # Panics
+    ///
+    /// If regex was set previously, this will panic.
+    pub fn custom_cwd(mut self, cwd: path::PathBuf) -> Self {
+        #[cfg(feature = "regex")]
+        if self.regex.is_some() {
+            panic!("which can't use regex and cwd at the same time!")
+        }
+        self.cwd = Some(either::Either::Right(cwd));
+        self
+    }
+
+    /// Sets the path name regex to search for. You ***MUST*** call this, or [`Self::binary_name`] prior to searching.
+    ///
+    /// When `Regex` is disabled this function takes the unit type as a stand in. The parameter will change when
+    /// `Regex` is enabled.
+    ///
+    /// # Panics
+    ///
+    /// If the `regex` feature wasn't turned on for this crate this will always panic. Additionally if a
+    /// `cwd` (aka current working directory) or `binary_name` was set previously, this will panic, as those options
+    /// are incompatible with `regex`.
+    #[allow(unused_variables)]
+    pub fn regex(mut self, regex: Regex) -> Self {
+        #[cfg(not(feature = "regex"))]
+        {
+            panic!("which's regex feature was not enabled in your Cargo.toml!")
+        }
+        #[cfg(feature = "regex")]
+        {
+            if self.cwd != Some(either::Either::Left(false)) && self.cwd.is_some() {
+                panic!("which can't use regex and cwd at the same time!")
+            }
+            if self.binary_name.is_some() {
+                panic!("which can't use `binary_name` and `regex` at the same time!");
+            }
+            self.regex = Some(regex);
+            self
+        }
+    }
+
+    /// Sets the path name to search for. You ***MUST*** call this, or [`Self::regex`] prior to searching.
+    ///
+    /// # Panics
+    ///
+    /// If a `regex` was set previously this will panic as this is not compatible with `regex`.
+    pub fn binary_name(mut self, name: OsString) -> Self {
+        #[cfg(feature = "regex")]
+        if self.regex.is_some() {
+            panic!("which can't use `binary_name` and `regex` at the same time!");
+        }
+        self.binary_name = Some(name);
+        self
+    }
+
+    /// Uses the given string instead of the `PATH` env variable.
+    pub fn custom_path_list(mut self, custom_path_list: OsString) -> Self {
+        self.custom_path_list = Some(custom_path_list);
+        self
+    }
+
+    /// Uses the `PATH` env variable. Enabled by default.
+    pub fn system_path_list(mut self) -> Self {
+        self.custom_path_list = None;
+        self
+    }
+
+    /// Finishes configuring, runs the query and returns the first result.
+    pub fn first_result(self) -> Result<path::PathBuf> {
+        self.all_results()
+            .and_then(|mut i| i.next().ok_or(Error::CannotFindBinaryPath))
+    }
+
+    /// Finishes configuring, runs the query and returns all results.
+    pub fn all_results(self) -> Result<impl Iterator<Item = path::PathBuf>> {
+        let binary_checker = build_binary_checker();
+
+        let finder = Finder::new();
+
+        let paths = self.custom_path_list.or_else(|| env::var_os("PATH"));
+
+        #[cfg(feature = "regex")]
+        if let Some(regex) = self.regex {
+            return finder
+                .find_re(regex, paths, binary_checker)
+                .map(|i| Box::new(i) as Box<dyn Iterator<Item = path::PathBuf>>);
+        }
+
+        let cwd = match self.cwd {
+            Some(either::Either::Left(false)) => None,
+            Some(either::Either::Right(custom)) => Some(custom),
+            None | Some(either::Either::Left(true)) => env::current_dir().ok(),
+        };
+
+        finder
+            .find(
+                self.binary_name.expect(
+                    "binary_name not set! You must set binary_name or regex before searching!",
+                ),
+                paths,
+                cwd,
+                binary_checker,
+            )
+            .map(|i| Box::new(i) as Box<dyn Iterator<Item = path::PathBuf>>)
+    }
+}
+
 /// An owned, immutable wrapper around a `PathBuf` containing the path of an executable.
 ///
 /// The constructed `PathBuf` is the output of `which` or `which_in`, but `which::Path` has the
@@ -190,7 +399,7 @@
 ///
 /// Since `which::Path` implements `Deref` for `std::path::Path`, all methods on `&std::path::Path`
 /// are also available to `&which::Path` values.
-#[derive(Clone, PartialEq)]
+#[derive(Clone, PartialEq, Eq)]
 pub struct Path {
     inner: path::PathBuf,
 }
@@ -277,8 +486,6 @@
     }
 }
 
-impl Eq for Path {}
-
 impl PartialEq<path::PathBuf> for Path {
     fn eq(&self, other: &path::PathBuf) -> bool {
         self.inner == *other
@@ -304,7 +511,7 @@
 ///
 /// Since `CanonicalPath` implements `Deref` for `std::path::Path`, all methods on
 /// `&std::path::Path` are also available to `&CanonicalPath` values.
-#[derive(Clone, PartialEq)]
+#[derive(Clone, PartialEq, Eq)]
 pub struct CanonicalPath {
     inner: path::PathBuf,
 }
@@ -411,8 +618,6 @@
     }
 }
 
-impl Eq for CanonicalPath {}
-
 impl PartialEq<path::PathBuf> for CanonicalPath {
     fn eq(&self, other: &path::PathBuf) -> bool {
         self.inner == *other