mirror of
https://github.com/denoland/deno.git
synced 2025-08-04 10:59:13 +00:00
190 lines
4.1 KiB
Rust
190 lines
4.1 KiB
Rust
// Copyright 2018-2025 the Deno authors. MIT license.
|
|
|
|
use std::ffi::OsStr;
|
|
use std::ffi::OsString;
|
|
use std::path::PathBuf;
|
|
|
|
pub use which::Error;
|
|
use which::sys::Sys;
|
|
|
|
pub fn which_in(
|
|
sys: impl WhichSys,
|
|
binary_name: &str,
|
|
path: Option<OsString>,
|
|
cwd: PathBuf,
|
|
) -> Result<PathBuf, Error> {
|
|
let sys = WhichSysAdapter(sys);
|
|
let config = which::WhichConfig::new_with_sys(sys)
|
|
.custom_cwd(cwd)
|
|
.binary_name(OsString::from(binary_name));
|
|
let config = match path {
|
|
Some(path) => config.custom_path_list(path),
|
|
None => config,
|
|
};
|
|
config.first_result()
|
|
}
|
|
|
|
#[sys_traits::auto_impl]
|
|
pub trait WhichSys:
|
|
sys_traits::EnvHomeDir
|
|
+ sys_traits::EnvCurrentDir
|
|
+ sys_traits::EnvVar
|
|
+ sys_traits::FsReadDir
|
|
+ sys_traits::FsMetadata
|
|
+ Clone
|
|
+ 'static
|
|
{
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct WhichSysAdapter<TSys: WhichSys>(TSys);
|
|
|
|
impl<TSys: WhichSys> Sys for WhichSysAdapter<TSys> {
|
|
type ReadDirEntry = WhichReadDirEntrySysAdapter<TSys::ReadDirEntry>;
|
|
|
|
type Metadata = WhichMetadataSysAdapter<TSys::Metadata>;
|
|
|
|
fn is_windows(&self) -> bool {
|
|
sys_traits::impls::is_windows()
|
|
}
|
|
|
|
fn current_dir(&self) -> std::io::Result<std::path::PathBuf> {
|
|
self.0.env_current_dir()
|
|
}
|
|
|
|
fn home_dir(&self) -> Option<std::path::PathBuf> {
|
|
self.0.env_home_dir()
|
|
}
|
|
|
|
fn env_split_paths(&self, paths: &OsStr) -> Vec<std::path::PathBuf> {
|
|
if cfg!(target_arch = "wasm32") && self.is_windows() {
|
|
// not perfect, but good enough
|
|
paths
|
|
.to_string_lossy()
|
|
.split(";")
|
|
.map(PathBuf::from)
|
|
.collect()
|
|
} else {
|
|
std::env::split_paths(paths).collect()
|
|
}
|
|
}
|
|
|
|
fn env_path(&self) -> Option<OsString> {
|
|
self.0.env_var_os("PATH")
|
|
}
|
|
|
|
fn env_path_ext(&self) -> Option<OsString> {
|
|
self.0.env_var_os("PATHEXT")
|
|
}
|
|
|
|
fn metadata(
|
|
&self,
|
|
path: &std::path::Path,
|
|
) -> std::io::Result<Self::Metadata> {
|
|
self.0.fs_metadata(path).map(WhichMetadataSysAdapter)
|
|
}
|
|
|
|
fn symlink_metadata(
|
|
&self,
|
|
path: &std::path::Path,
|
|
) -> std::io::Result<Self::Metadata> {
|
|
self
|
|
.0
|
|
.fs_symlink_metadata(path)
|
|
.map(WhichMetadataSysAdapter)
|
|
}
|
|
|
|
fn read_dir(
|
|
&self,
|
|
path: &std::path::Path,
|
|
) -> std::io::Result<
|
|
Box<dyn Iterator<Item = std::io::Result<Self::ReadDirEntry>>>,
|
|
> {
|
|
let iter = self.0.fs_read_dir(path)?;
|
|
let iter = Box::new(
|
|
iter
|
|
.into_iter()
|
|
.map(|value| value.map(WhichReadDirEntrySysAdapter)),
|
|
);
|
|
Ok(iter)
|
|
}
|
|
|
|
#[cfg(unix)]
|
|
fn is_valid_executable(
|
|
&self,
|
|
path: &std::path::Path,
|
|
) -> std::io::Result<bool> {
|
|
use nix::unistd::AccessFlags;
|
|
use nix::unistd::access;
|
|
|
|
match access(path, AccessFlags::X_OK) {
|
|
Ok(()) => Ok(true),
|
|
Err(nix::errno::Errno::ENOENT) => Ok(false),
|
|
Err(e) => Err(std::io::Error::from_raw_os_error(e as i32)),
|
|
}
|
|
}
|
|
|
|
#[cfg(target_arch = "wasm32")]
|
|
fn is_valid_executable(
|
|
&self,
|
|
_path: &std::path::Path,
|
|
) -> std::io::Result<bool> {
|
|
Ok(true)
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
fn is_valid_executable(
|
|
&self,
|
|
path: &std::path::Path,
|
|
) -> std::io::Result<bool> {
|
|
use std::os::windows::ffi::OsStrExt;
|
|
|
|
let name = path
|
|
.as_os_str()
|
|
.encode_wide()
|
|
.chain(Some(0))
|
|
.collect::<Vec<u16>>();
|
|
let mut bt: u32 = 0;
|
|
// SAFETY: winapi call
|
|
unsafe {
|
|
Ok(
|
|
windows_sys::Win32::Storage::FileSystem::GetBinaryTypeW(
|
|
name.as_ptr(),
|
|
&mut bt,
|
|
) != 0,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct WhichReadDirEntrySysAdapter<TFsDirEntry: sys_traits::FsDirEntry>(
|
|
TFsDirEntry,
|
|
);
|
|
|
|
impl<TFsDirEntry: sys_traits::FsDirEntry> which::sys::SysReadDirEntry
|
|
for WhichReadDirEntrySysAdapter<TFsDirEntry>
|
|
{
|
|
fn file_name(&self) -> std::ffi::OsString {
|
|
self.0.file_name().into_owned()
|
|
}
|
|
|
|
fn path(&self) -> std::path::PathBuf {
|
|
self.0.path().into_owned()
|
|
}
|
|
}
|
|
|
|
pub struct WhichMetadataSysAdapter<TMetadata: sys_traits::FsMetadataValue>(
|
|
TMetadata,
|
|
);
|
|
|
|
impl<TMetadata: sys_traits::FsMetadataValue> which::sys::SysMetadata
|
|
for WhichMetadataSysAdapter<TMetadata>
|
|
{
|
|
fn is_symlink(&self) -> bool {
|
|
self.0.file_type().is_symlink()
|
|
}
|
|
|
|
fn is_file(&self) -> bool {
|
|
self.0.file_type().is_file()
|
|
}
|
|
}
|