aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-10 07:09:40 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-10 07:09:40 +0000
commiteff391acbff9edacbab8cd712c4a221ff01a66bd (patch)
tree0ee35a94c440d4b17b59f4adbc625f2cee3fb7f3
parente19c8c561565fcf1fec05e94aefa07728f69409a (diff)
parent6f0fadcda199702a28974afba6e4b75bf6a20b2a (diff)
downloadwhich-android13-mainline-conscrypt-release.tar.gz
Snap for 8564071 from 6f0fadcda199702a28974afba6e4b75bf6a20b2a to mainline-conscrypt-releaseaml_con_331413000aml_con_331411000aml_con_331312000aml_con_331115000aml_con_331011010android13-mainline-conscrypt-release
Change-Id: Id6430a75fb9c5106f582365efd387024cd49e773
-rw-r--r--.cargo_vcs_info.json7
-rw-r--r--.github/workflows/rust.yml97
-rw-r--r--.gitignore1
-rw-r--r--Android.bp8
-rw-r--r--Cargo.toml19
-rw-r--r--Cargo.toml.orig9
-rw-r--r--METADATA10
-rw-r--r--README.md23
-rw-r--r--TEST_MAPPING14
-rw-r--r--cargo2android.json5
-rw-r--r--src/finder.rs104
-rw-r--r--src/helper.rs10
-rw-r--r--src/lib.rs105
-rw-r--r--tests/basic.rs48
14 files changed, 376 insertions, 84 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index fb1169d..692ca11 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
{
"git": {
- "sha1": "2c54067bab846e96f07be60e78250f385825f09f"
- }
-}
+ "sha1": "8fbe34239c16af9cd253e36e9c2d3384f9b55f83"
+ },
+ "path_in_vcs": ""
+} \ No newline at end of file
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 288ccaf..dd380d3 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -1,28 +1,93 @@
-name: Rust
-
+name: Main workflow
on:
push:
- branches: [ master ]
pull_request:
- branches: [ master ]
-
-env:
- CARGO_TERM_COLOR: always
jobs:
+ # 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: Build and 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/.gitignore b/.gitignore
index a9d37c5..865d4a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
target
Cargo.lock
+.vscode/
diff --git a/Android.bp b/Android.bp
index 141bf34..3d469f9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,4 @@
-// This file is generated by cargo2android.py --run --dependencies --device --features=.
+// This file is generated by cargo2android.py --config cargo2android.json.
// Do not modify this file as changes will be overridden on upgrade.
package {
@@ -22,6 +22,8 @@ rust_library {
name: "libwhich",
host_supported: true,
crate_name: "which",
+ cargo_env_compat: true,
+ cargo_pkg_version: "4.2.4",
srcs: ["src/lib.rs"],
edition: "2018",
rustlibs: [
@@ -29,7 +31,3 @@ rust_library {
"liblibc",
],
}
-
-// dependent_library ["feature_list"]
-// either-1.6.1 "default,use_std"
-// libc-0.2.92 "default,std"
diff --git a/Cargo.toml b/Cargo.toml
index f6e0a43..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.1.0"
+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,10 +21,18 @@ keywords = ["which", "which-rs", "unix", "command"]
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"
[dependencies.libc]
version = "0.2.65"
+
+[dependencies.regex]
+version = "1.5.4"
+optional = true
[dev-dependencies.tempdir]
version = "0.3.7"
+[target."cfg(windows)".dependencies.lazy_static]
+version = "1"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index c3c472e..ec31c55 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "which"
-version = "4.1.0"
+version = "4.2.4"
edition = "2018"
authors = ["Harry Fei <tiziyuanfang@gmail.com>"]
repository = "https://github.com/harryfei/which-rs.git"
@@ -14,6 +14,13 @@ keywords = ["which", "which-rs", "unix", "command"]
[dependencies]
either = "1.6"
libc = "0.2.65"
+regex = { version = "1.5.4", optional = true }
+
+[target.'cfg(windows)'.dependencies]
+lazy_static = "1"
[dev-dependencies]
tempdir = "0.3.7"
+
+[package.metadata.docs.rs]
+all-features = true
diff --git a/METADATA b/METADATA
index 27de0e1..6a034c4 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/which/which-4.1.0.crate"
+ value: "https://static.crates.io/crates/which/which-4.2.4.crate"
}
- version: "4.1.0"
+ version: "4.2.4"
license_type: NOTICE
last_upgrade_date {
- year: 2021
- month: 4
- day: 2
+ 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 @@ A Rust equivalent of Unix command "which". Locate installed executable in cross
* 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/TEST_MAPPING b/TEST_MAPPING
index df48c8d..e4ec3b3 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,14 +1,24 @@
// Generated by update_crate_tests.py for tests that depend on this crate.
{
+ "imports": [
+ {
+ "path": "external/rust/crates/libsqlite3-sys"
+ }
+ ],
"presubmit": [
{
- "name": "libsqlite3-sys_device_test_src_lib"
+ "name": "keystore2_test"
},
{
+ "name": "legacykeystore_test"
+ }
+ ],
+ "presubmit-rust": [
+ {
"name": "keystore2_test"
},
{
- "name": "vpnprofilestore_test"
+ "name": "legacykeystore_test"
}
]
}
diff --git a/cargo2android.json b/cargo2android.json
new file mode 100644
index 0000000..5fd6c55
--- /dev/null
+++ b/cargo2android.json
@@ -0,0 +1,5 @@
+{
+ "device": true,
+ "features": "",
+ "run": true
+} \ No newline at end of file
diff --git a/src/finder.rs b/src/finder.rs
index 91c6cab..43b659d 100644
--- a/src/finder.rs
+++ b/src/finder.rs
@@ -1,12 +1,16 @@
use crate::checker::CompositeChecker;
use crate::error::*;
-use either::Either;
#[cfg(windows)]
use crate::helper::has_executable_extension;
+use either::Either;
+#[cfg(feature = "regex")]
+use regex::Regex;
+#[cfg(feature = "regex")]
+use std::borrow::Borrow;
use std::env;
use std::ffi::OsStr;
-#[cfg(windows)]
-use std::ffi::OsString;
+#[cfg(feature = "regex")]
+use std::fs;
use std::iter;
use std::path::{Path, PathBuf};
@@ -52,7 +56,7 @@ impl Finder {
&self,
binary_name: T,
paths: Option<U>,
- cwd: V,
+ cwd: Option<V>,
binary_checker: CompositeChecker,
) -> Result<impl Iterator<Item = PathBuf>>
where
@@ -62,20 +66,54 @@ impl Finder {
{
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();
-
- Either::Right(Self::path_search_candidates(path, paths).into_iter())
+ 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())
+ }
};
Ok(binary_path_candidates.filter(move |p| binary_checker.is_valid(p)))
}
+ #[cfg(feature = "regex")]
+ pub fn find_re<T>(
+ &self,
+ binary_regex: impl Borrow<Regex>,
+ paths: Option<T>,
+ binary_checker: CompositeChecker,
+ ) -> Result<impl Iterator<Item = PathBuf>>
+ where
+ T: AsRef<OsStr>,
+ {
+ let p = paths.ok_or(Error::CannotFindBinaryPath)?;
+ let paths: Vec<_> = env::split_paths(&p).collect();
+
+ let matching_re = paths
+ .into_iter()
+ .flat_map(fs::read_dir)
+ .flatten()
+ .flatten()
+ .map(|e| e.path())
+ .filter(move |p| {
+ if let Some(unicode_file_name) = p.file_name().unwrap().to_str() {
+ binary_regex.borrow().is_match(unicode_file_name)
+ } else {
+ false
+ }
+ })
+ .filter(move |p| binary_checker.is_valid(p));
+
+ Ok(matching_re)
+ }
+
fn cwd_search_candidates<C>(binary_name: PathBuf, cwd: C) -> impl IntoIterator<Item = PathBuf>
where
C: AsRef<Path>,
@@ -110,19 +148,35 @@ impl Finder {
where
P: IntoIterator<Item = PathBuf>,
{
- // Read PATHEXT env variable and split it into vector of String
- let path_exts =
- env::var_os("PATHEXT").unwrap_or(OsString::from(env::consts::EXE_EXTENSION));
-
- let exe_extension_vec = env::split_paths(&path_exts)
- .filter_map(|e| e.to_str().map(|e| e.to_owned()))
- .collect::<Vec<_>>();
+ // Sample %PATHEXT%: .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
+ // PATH_EXTENSIONS is then [".COM", ".EXE", ".BAT", …].
+ // (In one use of PATH_EXTENSIONS we skip the dot, but in the other we need it;
+ // hence its retention.)
+ lazy_static! {
+ static ref PATH_EXTENSIONS: Vec<String> =
+ env::var("PATHEXT")
+ .map(|pathext| {
+ pathext.split(';')
+ .filter_map(|s| {
+ if s.as_bytes().first() == Some(&b'.') {
+ Some(s.to_owned())
+ } else {
+ // Invalid segment; just ignore it.
+ None
+ }
+ })
+ .collect()
+ })
+ // PATHEXT not being set or not being a proper Unicode string is exceedingly
+ // improbable and would probably break Windows badly. Still, don't crash:
+ .unwrap_or(vec![]);
+ }
paths
.into_iter()
.flat_map(move |p| -> Box<dyn Iterator<Item = _>> {
// Check if path already have executable extension
- if has_executable_extension(&p, &exe_extension_vec) {
+ if has_executable_extension(&p, &PATH_EXTENSIONS) {
Box::new(iter::once(p))
} else {
// Appended paths with windows executable extensions.
@@ -131,15 +185,13 @@ impl Finder {
// c:/windows/bin.EXE
// c:/windows/bin.CMD
// ...
- let ps = exe_extension_vec.clone().into_iter().map(move |e| {
+ Box::new(PATH_EXTENSIONS.iter().map(move |e| {
// Append the extension.
- let mut p = p.clone().to_path_buf().into_os_string();
+ let mut p = p.clone().into_os_string();
p.push(e);
PathBuf::from(p)
- });
-
- Box::new(ps)
+ }))
}
})
}
diff --git a/src/helper.rs b/src/helper.rs
index 71658a0..eb96891 100644
--- a/src/helper.rs
+++ b/src/helper.rs
@@ -1,10 +1,10 @@
use std::path::Path;
/// Check if given path has extension which in the given vector.
-pub fn has_executable_extension<T: AsRef<Path>, S: AsRef<str>>(path: T, exts_vec: &Vec<S>) -> bool {
+pub fn has_executable_extension<T: AsRef<Path>, S: AsRef<str>>(path: T, pathext: &[S]) -> bool {
let ext = path.as_ref().extension().and_then(|e| e.to_str());
match ext {
- Some(ext) => exts_vec
+ Some(ext) => pathext
.iter()
.any(|e| ext.eq_ignore_ascii_case(&e.as_ref()[1..])),
_ => false,
@@ -21,12 +21,12 @@ mod test {
// Case insensitive
assert!(has_executable_extension(
PathBuf::from("foo.exe"),
- &vec![".COM", ".EXE", ".CMD"]
+ &[".COM", ".EXE", ".CMD"]
));
assert!(has_executable_extension(
PathBuf::from("foo.CMD"),
- &vec![".COM", ".EXE", ".CMD"]
+ &[".COM", ".EXE", ".CMD"]
));
}
@@ -34,7 +34,7 @@ mod test {
fn test_extension_not_in_extension_vector() {
assert!(!has_executable_extension(
PathBuf::from("foo.bar"),
- &vec![".COM", ".EXE", ".CMD"]
+ &[".COM", ".EXE", ".CMD"]
));
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 4aea3e6..2b27094 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,17 +9,25 @@
//! 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"));
//!
//! ```
+#[cfg(windows)]
+#[macro_use]
+extern crate lazy_static;
+
mod checker;
mod error;
mod finder;
#[cfg(windows)]
mod helper;
+#[cfg(feature = "regex")]
+use regex::Regex;
+#[cfg(feature = "regex")]
+use std::borrow::Borrow;
use std::env;
use std::fmt;
use std::path;
@@ -57,9 +65,50 @@ pub fn which<T: AsRef<OsStr>>(binary_name: T) -> Result<path::PathBuf> {
/// 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();
+
+ let binary_checker = build_binary_checker();
+
+ let finder = Finder::new();
+
+ finder.find(binary_name, env::var_os("PATH"), cwd, binary_checker)
+}
- which_in_all(binary_name, env::var_os("PATH"), cwd)
+/// 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;
+/// use std::path::PathBuf;
+///
+/// let re = Regex::new(r"python\d$").unwrap();
+/// let binaries: Vec<PathBuf> = which::which_re(re).unwrap().collect();
+/// 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: impl Borrow<Regex>) -> Result<impl Iterator<Item = path::PathBuf>> {
+ which_re_in(regex, env::var_os("PATH"))
}
/// Find `binary_name` in the path list `paths`, using `cwd` to resolve relative paths.
@@ -73,6 +122,44 @@ where
.and_then(|mut i| i.next().ok_or(Error::CannotFindBinaryPath))
}
+/// 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
+/// * `paths` - A string containing the paths to search
+/// (separated in the same way as the PATH environment variable)
+///
+/// # Examples
+///
+/// ```no_run
+/// use regex::Regex;
+/// use which::which;
+/// use std::path::PathBuf;
+///
+/// let re = Regex::new(r"python\d$").unwrap();
+/// let paths = Some("/usr/bin:/usr/local/bin");
+/// let binaries: Vec<PathBuf> = which::which_re_in(re, paths).unwrap().collect();
+/// let python_paths = vec![PathBuf::from("/usr/bin/python2"), PathBuf::from("/usr/bin/python3")];
+/// assert_eq!(binaries, python_paths);
+/// ```
+#[cfg(feature = "regex")]
+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 = build_binary_checker();
+
+ let finder = Finder::new();
+
+ finder.find_re(regex, paths, binary_checker)
+}
+
/// Find all binaries with `binary_name` in the path list `paths`, using `cwd` to resolve relative paths.
pub fn which_in_all<T, U, V>(
binary_name: T,
@@ -84,13 +171,17 @@ where
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 7cb7a08..897e912 100644
--- a/tests/basic.rs
+++ b/tests/basic.rs
@@ -1,11 +1,13 @@
extern crate tempdir;
extern crate which;
-use std::env;
+#[cfg(feature = "regex")]
+use regex::Regex;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::io;
use std::path::{Path, PathBuf};
+use std::{env, vec};
use tempdir::TempDir;
struct TestFixture {
@@ -126,6 +128,50 @@ fn test_which() {
}
#[test]
+#[cfg(all(unix, feature = "regex"))]
+fn test_which_re_in_with_matches() {
+ let f = TestFixture::new();
+ f.mk_bin("a/bin_0", "").unwrap();
+ f.mk_bin("b/bin_1", "").unwrap();
+ let re = Regex::new(r"bin_\d").unwrap();
+
+ let result: Vec<PathBuf> = which::which_re_in(re, Some(f.paths))
+ .unwrap()
+ .into_iter()
+ .collect();
+
+ let temp = f.tempdir;
+
+ assert_eq!(
+ result,
+ vec![temp.path().join("a/bin_0"), temp.path().join("b/bin_1")]
+ )
+}
+
+#[test]
+#[cfg(all(unix, feature = "regex"))]
+fn test_which_re_in_without_matches() {
+ let f = TestFixture::new();
+ let re = Regex::new(r"bi[^n]").unwrap();
+
+ let result: Vec<PathBuf> = which::which_re_in(re, Some(f.paths))
+ .unwrap()
+ .into_iter()
+ .collect();
+
+ assert_eq!(result, Vec::<PathBuf>::new())
+}
+
+#[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();