Skip to content

Commit 64620af

Browse files
WLBFHarry Fei
authored andcommitted
implement windows extension test
1 parent 0bac25a commit 64620af

File tree

4 files changed

+165
-78
lines changed

4 files changed

+165
-78
lines changed

Cargo.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,5 @@ keywords = ["which", "which-rs", "unix", "command"]
1414
failure = "0.1.1"
1515
libc = "0.2.10"
1616

17-
[target.'cfg(windows)'.dependencies]
18-
lazy_static = "1.0"
19-
2017
[dev-dependencies]
2118
tempdir = "0.3.4"

src/finder.rs

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
11
use std::env;
22
use std::ffi::OsStr;
3+
#[cfg(windows)]
34
use std::ffi::OsString;
45
use std::path::{Path, PathBuf};
56
use error::*;
6-
use helper::check_extension;
7-
87
#[cfg(windows)]
9-
lazy_static! {
10-
static ref EXE_EXTENSION_VEC: Vec<String> = {
11-
// Read PATHEXT env variable and split it into vector of String
12-
let path_exts = env::var_os("PATHEXT").unwrap_or(OsString::from(env::consts::EXE_EXTENSION));
13-
env::split_paths(&path_exts)
14-
.map(|e| e.to_str().map(|e| e.to_owned()))
15-
.filter_map(|e| e).collect::<Vec<_>>()
16-
};
17-
}
8+
use helper::has_executable_extension;
189

1910
pub trait Checker {
2011
fn is_valid(&self, path: &Path) -> bool;
@@ -43,13 +34,13 @@ impl Finder {
4334
// Does it have a path separator?
4435
if path.components().count() > 1 {
4536
if path.is_absolute() {
46-
check_with_exe_extension(path, binary_checker)
37+
self.check_with_exe_extension(path, binary_checker)
4738
.ok_or(ErrorKind::BadAbsolutePath.into())
4839
} else {
4940
// Try to make it absolute.
5041
let mut new_path = PathBuf::from(cwd.as_ref());
5142
new_path.push(path);
52-
check_with_exe_extension(new_path, binary_checker)
43+
self.check_with_exe_extension(new_path, binary_checker)
5344
.ok_or(ErrorKind::BadRelativePath.into())
5445
}
5546
} else {
@@ -58,46 +49,57 @@ impl Finder {
5849
.and_then(|paths| {
5950
env::split_paths(&paths)
6051
.map(|p| p.join(binary_name.as_ref()))
61-
.map(|p| check_with_exe_extension(p, binary_checker))
52+
.map(|p| self.check_with_exe_extension(p, binary_checker))
6253
.skip_while(|res| res.is_none())
6354
.next()
6455
})
6556
.map(|res| res.unwrap())
6657
.ok_or(ErrorKind::CannotFindBinaryPath.into())
6758
}
6859
}
69-
}
7060

71-
#[cfg(unix)]
72-
/// Check if given path with platform specification is valid
73-
pub fn check_with_exe_extension<T: AsRef<Path>>(path: T, binary_checker: &Checker) -> Option<PathBuf> {
74-
if binary_checker.is_valid(&path) {
75-
Some(path)
76-
} else {
77-
None
78-
}
79-
}
80-
81-
#[cfg(windows)]
82-
/// Check if given path with platform specification is valid
83-
pub fn check_with_exe_extension<T: AsRef<Path>>(path: T, binary_checker: &Checker) -> Option<PathBuf> {
84-
// Check if path already have executable extension
85-
if check_extension(&path, &EXE_EXTENSION_VEC) {
61+
#[cfg(unix)]
62+
/// Check if given path with platform specification is valid
63+
pub fn check_with_exe_extension<T: AsRef<Path>>(&self, path: T, binary_checker: &Checker) -> Option<PathBuf> {
8664
if binary_checker.is_valid(path.as_ref()) {
8765
Some(path.as_ref().to_path_buf())
8866
} else {
8967
None
9068
}
91-
} else {
92-
// Check paths with windows executable extensions
93-
EXE_EXTENSION_VEC.iter()
94-
.map(|e| {
95-
// Append the extension.
96-
let mut s = path.as_ref().to_path_buf().into_os_string();
97-
s.push(e);
98-
PathBuf::from(s)
99-
})
100-
.skip_while(|p| !(binary_checker.is_valid(p)))
101-
.next()
69+
}
70+
71+
#[cfg(windows)]
72+
/// Check if given path with platform specification is valid
73+
pub fn check_with_exe_extension<T: AsRef<Path>>(&self, path: T, binary_checker: &Checker) -> Option<PathBuf> {
74+
// Read PATHEXT env variable and split it into vector of String
75+
let path_exts = env::var_os("PATHEXT").unwrap_or(OsString::from(env::consts::EXE_EXTENSION));
76+
let exe_extension_vec = env::split_paths(&path_exts)
77+
.filter_map(|e| e.to_str().map(|e| e.to_owned()))
78+
.collect::<Vec<_>>();
79+
80+
// Check if path already have executable extension
81+
if has_executable_extension(&path, &exe_extension_vec) {
82+
if binary_checker.is_valid(path.as_ref()) {
83+
Some(path.as_ref().to_path_buf())
84+
} else {
85+
None
86+
}
87+
} else {
88+
// Check paths appended with windows executable extensions
89+
// e.g. path `c:/windows/bin` will expend to:
90+
// c:/windows/bin.COM
91+
// c:/windows/bin.EXE
92+
// c:/windows/bin.CMD
93+
// ...
94+
exe_extension_vec.iter()
95+
.map(|e| {
96+
// Append the extension.
97+
let mut s = path.as_ref().to_path_buf().into_os_string();
98+
s.push(e);
99+
PathBuf::from(s)
100+
})
101+
.skip_while(|p| !(binary_checker.is_valid(p)))
102+
.next()
103+
}
102104
}
103105
}

src/helper.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::path::Path;
22

33
/// Check if given path has extension which in the given vector.
4-
pub fn check_extension<T: AsRef<Path>, S: AsRef<str>>(path: T, exts_vec: &Vec<S>) -> bool {
4+
pub fn has_executable_extension<T: AsRef<Path>, S: AsRef<str>>(path: T, exts_vec: &Vec<S>) -> bool {
55
match path.as_ref()
66
.extension()
77
.and_then(|e| e.to_str())
@@ -21,14 +21,14 @@ mod test {
2121
fn test_extension_in_extension_vector() {
2222
// Case insensitive
2323
assert!(
24-
check_extension(
24+
has_executable_extension(
2525
PathBuf::from("foo.exe"),
2626
&vec![".COM", ".EXE", ".CMD"]
2727
)
2828
);
2929

3030
assert!(
31-
check_extension(
31+
has_executable_extension(
3232
PathBuf::from("foo.CMD"),
3333
&vec![".COM", ".EXE", ".CMD"]
3434
)
@@ -38,7 +38,7 @@ mod test {
3838
#[test]
3939
fn test_extension_not_in_extension_vector() {
4040
assert!(
41-
!check_extension(
41+
!has_executable_extension(
4242
PathBuf::from("foo.bar"),
4343
&vec![".COM", ".EXE", ".CMD"]
4444
)

0 commit comments

Comments
 (0)