1
1
mirror of https://github.com/casey/just.git synced 2024-11-22 02:09:44 +03:00

Use internal implementation of which()

This commit is contained in:
0xzhzh 2024-11-03 23:28:42 -08:00
parent f1980b5150
commit 0c6f5e8376
4 changed files with 70 additions and 10 deletions

11
Cargo.lock generated
View File

@ -498,6 +498,15 @@ dependencies = [
"cc", "cc",
] ]
[[package]]
name = "is_executable"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4a1b5bad6f9072935961dfbf1cced2f3d129963d091b6f69f007fe04e758ae2"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "is_terminal_polyfill" name = "is_terminal_polyfill"
version = "1.70.1" version = "1.70.1"
@ -535,8 +544,10 @@ dependencies = [
"dirs", "dirs",
"dotenvy", "dotenvy",
"edit-distance", "edit-distance",
"either",
"executable-path", "executable-path",
"heck", "heck",
"is_executable",
"lexiclean", "lexiclean",
"libc", "libc",
"num_cpus", "num_cpus",

View File

@ -30,7 +30,9 @@ derivative = "2.0.0"
dirs = "5.0.1" dirs = "5.0.1"
dotenvy = "0.15" dotenvy = "0.15"
edit-distance = "2.0.0" edit-distance = "2.0.0"
either = "1.13.0"
heck = "0.5.0" heck = "0.5.0"
is_executable = "1.0.4"
lexiclean = "0.0.1" lexiclean = "0.0.1"
libc = "0.2.0" libc = "0.2.0"
num_cpus = "1.15.0" num_cpus = "1.15.0"
@ -51,7 +53,6 @@ tempfile = "3.0.0"
typed-arena = "2.0.1" typed-arena = "2.0.1"
unicode-width = "0.2.0" unicode-width = "0.2.0"
uuid = { version = "1.0.0", features = ["v4"] } uuid = { version = "1.0.0", features = ["v4"] }
which = "6.0.0"
[dev-dependencies] [dev-dependencies]
executable-path = "1.0.0" executable-path = "1.0.0"

View File

@ -6,6 +6,8 @@ alias t := test
log := "warn" log := "warn"
bingus := which("bash")
export JUST_LOG := log export JUST_LOG := log
[group: 'dev'] [group: 'dev']

View File

@ -1,5 +1,6 @@
use { use {
super::*, super::*,
either::Either,
heck::{ heck::{
ToKebabCase, ToLowerCamelCase, ToShoutyKebabCase, ToShoutySnakeCase, ToSnakeCase, ToTitleCase, ToKebabCase, ToLowerCamelCase, ToShoutyKebabCase, ToShoutySnakeCase, ToSnakeCase, ToTitleCase,
ToUpperCamelCase, ToUpperCamelCase,
@ -110,7 +111,7 @@ pub(crate) fn get(name: &str) -> Option<Function> {
"uppercase" => Unary(uppercase), "uppercase" => Unary(uppercase),
"uuid" => Nullary(uuid), "uuid" => Nullary(uuid),
"without_extension" => Unary(without_extension), "without_extension" => Unary(without_extension),
"which" => Unary(which_exec), "which" => Unary(which),
_ => return None, _ => return None,
}; };
Some(function) Some(function)
@ -668,14 +669,59 @@ fn uuid(_context: Context) -> FunctionResult {
Ok(uuid::Uuid::new_v4().to_string()) Ok(uuid::Uuid::new_v4().to_string())
} }
fn which_exec(_context: Context, s: &str) -> FunctionResult { fn which(context: Context, s: &str) -> FunctionResult {
let path = which::which(s).unwrap_or_default(); use is_executable::IsExecutable;
path.to_str().map(str::to_string).ok_or_else(|| {
format!( let cmd = PathBuf::from(s);
"unable to convert which executable path to string: {}",
path.display() let path_var;
) let candidates = match cmd.components().count() {
}) 0 => Err("empty command string".to_string())?,
1 => {
// cmd is a regular command
path_var = env::var_os("PATH").ok_or("Environment variable `PATH` is not set")?;
Either::Left(env::split_paths(&path_var).map(|path| path.join(cmd.clone())))
}
_ => {
// cmd contains a path separator, treat it as a path
Either::Right(iter::once(cmd))
}
};
for mut candidate in candidates.into_iter() {
if candidate.is_relative() {
// This candidate is a relative path, either because the user invoked `which("./rel/path")`,
// or because there was a relative path in `PATH`. Resolve it to an absolute path.
let cwd = context
.evaluator
.context
.search
.justfile
.parent()
.ok_or_else(|| {
format!(
"Could not resolve absolute path from `{}` relative to the justfile directory. Justfile `{}` had no parent.",
candidate.display(),
context.evaluator.context.search.justfile.display()
)
})?;
let mut cwd = PathBuf::from(cwd);
cwd.push(candidate);
candidate = cwd;
}
if candidate.is_executable() {
return candidate.to_str().map(str::to_string).ok_or_else(|| {
format!(
"Executable path is not valid unicode: {}",
candidate.display()
)
});
}
}
// No viable candidates; return an empty string
Ok(String::new())
} }
fn without_extension(_context: Context, path: &str) -> FunctionResult { fn without_extension(_context: Context, path: &str) -> FunctionResult {