`which()` does not use PATHEXT on Windows
Subtly different from #2826
Reproduced on just 1.43.0.
The built-in which() and require() commands fails to find executables on Windows because they do not follow Windows conventions for executable lookup: use PATH and PATHEXT.
For example:
# Suppose I am writing a cross-platform justfile
set unstable
# require_git_path_fails_windows := require('git')
# Logs error:
# error: Call to function `require` failed: could not find executable `git`
# This succeeds on Windows but fails on Linux
require_git_path_succeeds_windows := require('git.exe')
git_path_empty_string_on_windows := which('git')
git_path_found_on_windows := which('git.exe')
# Is forcing extra syntax to be cross-platform desirable?
# What value comes from forcing this extra syntax, as opposed to finding the desired path on all systems without it?
# On Windows, executables are invoked without explicit extension and have extension on the filesystem.
git_path_cross_platform := if os() == "windows" { which("git.exe") } else { which("git") }
@default:
echo "require_git_path_succeeds_windows = {{require_git_path_succeeds_windows}}"
echo "git_path_empty_string_on_windows = {{git_path_empty_string_on_windows}}"
echo "git_path_found_on_windows = {{git_path_found_on_windows}}"
echo "git_path_cross_platform = {{git_path_cross_platform}}"
Some people may feel that checking $PATHEXT is a windows-specific hack that just shouldn't implement. But I disagree.
Just as filesystem logic must use \s on Windows, and the $PATH parser must split on ; instead of :, so too must implementations of which look at $PATHEXT. This is baked into the way $PATH works on Windows: it only makes sense paired with $PATHEXT. You will never find a file named git on the Windows path. It will never exist. You will find git.exe.
I did a quick search, and the pathsearch rust crate implements cross-platform path searching, supporting PATHEXT on Windows:
https://docs.rs/pathsearch/latest/pathsearch/
I understand just implements its own which, I hope it doesn't need custom logic that precludes switching to an external dependency: https://github.com/casey/just/blob/master/src/which.rs