Skip to content

Commit

Permalink
implement windows extension test
Browse files Browse the repository at this point in the history
  • Loading branch information
WLBF committed Mar 17, 2018
1 parent 78e0291 commit a197fb4
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 75 deletions.
3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,5 @@ keywords = ["which", "which-rs", "unix", "command"]
failure = "0.1.1"
libc = "0.2.10"

[target.'cfg(windows)'.dependencies]
lazy_static = "1.0"

[dev-dependencies]
tempdir = "0.3.4"
79 changes: 38 additions & 41 deletions src/finder.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
use std::env;
use std::ffi::OsStr;
#[cfg(windows)]
use std::ffi::OsString;
use std::path::{Path, PathBuf};
use error::*;
use helper::check_extension;

#[cfg(windows)]
lazy_static! {
static ref EXE_EXTENSION_VEC: Vec<String> = {
// 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));
env::split_paths(&path_exts)
.map(|e| e.to_str().map(|e| e.to_owned()))
.filter_map(|e| e).collect::<Vec<_>>()
};
}
use helper::has_executable_extension;

pub trait Checker {
fn is_valid(&self, path: &Path) -> bool;
Expand Down Expand Up @@ -43,13 +34,13 @@ impl Finder {
// Does it have a path separator?
if path.components().count() > 1 {
if path.is_absolute() {
check_with_exe_extension(path, binary_checker)
self.check_with_exe_extension(path, binary_checker)
.ok_or(ErrorKind::BadAbsolutePath.into())
} else {
// Try to make it absolute.
let mut new_path = PathBuf::from(cwd.as_ref());
new_path.push(path);
check_with_exe_extension(new_path, binary_checker)
self.check_with_exe_extension(new_path, binary_checker)
.ok_or(ErrorKind::BadRelativePath.into())
}
} else {
Expand All @@ -58,46 +49,52 @@ impl Finder {
.and_then(|paths| {
env::split_paths(&paths)
.map(|p| p.join(binary_name.as_ref()))
.map(|p| check_with_exe_extension(p, binary_checker))
.map(|p| self.check_with_exe_extension(p, binary_checker))
.skip_while(|res| res.is_none())
.next()
})
.map(|res| res.unwrap())
.ok_or(ErrorKind::CannotFindBinaryPath.into())
}
}
}

#[cfg(unix)]
/// Check if given path with platform specification is valid
pub fn check_with_exe_extension<T: AsRef<Path>>(path: T, binary_checker: &Checker) -> Option<PathBuf> {
if binary_checker.is_valid(&path) {
Some(path)
} else {
None
}
}

#[cfg(windows)]
/// Check if given path with platform specification is valid
pub fn check_with_exe_extension<T: AsRef<Path>>(path: T, binary_checker: &Checker) -> Option<PathBuf> {
// Check if path already have executable extension
if check_extension(&path, &EXE_EXTENSION_VEC) {
#[cfg(unix)]
/// Check if given path with platform specification is valid
pub fn check_with_exe_extension<T: AsRef<Path>>(&self, path: T, binary_checker: &Checker) -> Option<PathBuf> {
if binary_checker.is_valid(path.as_ref()) {
Some(path.as_ref().to_path_buf())
} else {
None
}
} else {
// Check paths with windows executable extensions
EXE_EXTENSION_VEC.iter()
.map(|e| {
// Append the extension.
let mut s = path.as_ref().to_path_buf().into_os_string();
s.push(e);
PathBuf::from(s)
})
.skip_while(|p| !(binary_checker.is_valid(p)))
.next()
}

#[cfg(windows)]
/// Check if given path with platform specification is valid
pub fn check_with_exe_extension<T: AsRef<Path>>(&self, path: T, binary_checker: &Checker) -> Option<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<_>>();

// Check if path already have executable extension
if has_executable_extension(&path, &exe_extension_vec) {
if binary_checker.is_valid(path.as_ref()) {
Some(path.as_ref().to_path_buf())
} else {
None
}
} else {
// Check paths appended with windows executable extensions
exe_extension_vec.iter()
.map(|e| {
// Append the extension.
let mut s = path.as_ref().to_path_buf().into_os_string();
s.push(e);
PathBuf::from(s)
})
.skip_while(|p| !(binary_checker.is_valid(p)))
.next()
}
}
}
8 changes: 4 additions & 4 deletions src/helper.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::Path;

/// Check if given path has extension which in the given vector.
pub fn check_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, exts_vec: &Vec<S>) -> bool {
match path.as_ref()
.extension()
.and_then(|e| e.to_str())
Expand All @@ -21,14 +21,14 @@ mod test {
fn test_extension_in_extension_vector() {
// Case insensitive
assert!(
check_extension(
has_executable_extension(
PathBuf::from("foo.exe"),
&vec![".COM", ".EXE", ".CMD"]
)
);

assert!(
check_extension(
has_executable_extension(
PathBuf::from("foo.CMD"),
&vec![".COM", ".EXE", ".CMD"]
)
Expand All @@ -38,7 +38,7 @@ mod test {
#[test]
fn test_extension_not_in_extension_vector() {
assert!(
!check_extension(
!has_executable_extension(
PathBuf::from("foo.bar"),
&vec![".COM", ".EXE", ".CMD"]
)
Expand Down
Loading

0 comments on commit a197fb4

Please sign in to comment.