mirror of
https://gitee.com/openharmony/third_party_rust_which-rs
synced 2024-11-27 09:40:44 +00:00
Merge pull request #40 from marier-nico/master
Allow searching with regular expressions
This commit is contained in:
commit
32c08ce671
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
target
|
||||
Cargo.lock
|
||||
.vscode/
|
||||
|
@ -14,6 +14,7 @@ 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"
|
||||
|
@ -1,10 +1,13 @@
|
||||
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;
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs;
|
||||
use std::iter;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@ -74,6 +77,37 @@ impl Finder {
|
||||
Ok(binary_path_candidates.filter(move |p| binary_checker.is_valid(p)))
|
||||
}
|
||||
|
||||
#[cfg(feature = "regex")]
|
||||
pub fn find_re<T>(
|
||||
&self,
|
||||
binary_regex: 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.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>,
|
||||
|
60
src/lib.rs
60
src/lib.rs
@ -24,6 +24,8 @@ mod finder;
|
||||
#[cfg(windows)]
|
||||
mod helper;
|
||||
|
||||
#[cfg(feature = "regex")]
|
||||
use regex::Regex;
|
||||
use std::env;
|
||||
use std::fmt;
|
||||
use std::path;
|
||||
@ -66,6 +68,29 @@ pub fn which_all<T: AsRef<OsStr>>(binary_name: T) -> Result<impl Iterator<Item =
|
||||
which_in_all(binary_name, env::var_os("PATH"), cwd)
|
||||
}
|
||||
|
||||
/// Find all binaries matching a regular expression in a the system PATH.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `regex` - A regular expression to match binaries with
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```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);
|
||||
/// ```
|
||||
#[cfg(feature = "regex")]
|
||||
pub fn which_re(regex: 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.
|
||||
pub fn which_in<T, U, V>(binary_name: T, paths: Option<U>, cwd: V) -> Result<path::PathBuf>
|
||||
where
|
||||
@ -77,6 +102,41 @@ where
|
||||
.and_then(|mut i| i.next().ok_or(Error::CannotFindBinaryPath))
|
||||
}
|
||||
|
||||
/// Find all binaries matching a regular expression in a list of paths.
|
||||
///
|
||||
/// # 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: 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 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,
|
||||
|
@ -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 {
|
||||
@ -125,6 +127,38 @@ fn test_which() {
|
||||
assert_eq!(_which(&f, &BIN_NAME).unwrap(), f.bins[1])
|
||||
}
|
||||
|
||||
#[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(unix)]
|
||||
fn test_which_extension() {
|
||||
|
Loading…
Reference in New Issue
Block a user