feat: allow .cmd along with .exe for Windows paths (#187)

* Allow .cmd along with .exe for Windows paths

* Search windows path using %PATHEXT% instead of hardcoding extensions
This commit is contained in:
Arian Dehghani 2025-02-20 12:57:58 -08:00 committed by GitHub
parent b9cc3936c8
commit 96c69c1636
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -28,20 +28,28 @@ fn find_binary_in_path_windows(allocator: std.mem.Allocator, binary_name_: []con
error.EnvironmentVariableNotFound, error.InvalidWtf8 => &.{}, error.EnvironmentVariableNotFound, error.InvalidWtf8 => &.{},
}; };
defer allocator.free(bin_paths); defer allocator.free(bin_paths);
var path = std.ArrayList(u8).init(allocator); const bin_extensions = std.process.getEnvVarOwned(allocator, "PATHEXT") catch |err| switch (err) {
try path.appendSlice(binary_name_); error.OutOfMemory => return error.OutOfMemory,
try path.appendSlice(".exe"); error.EnvironmentVariableNotFound, error.InvalidWtf8 => &.{},
const binary_name = try path.toOwnedSlice(); };
defer allocator.free(binary_name); defer allocator.free(bin_extensions);
var bin_path_iterator = std.mem.splitScalar(u8, bin_paths, std.fs.path.delimiter); var bin_path_iterator = std.mem.splitScalar(u8, bin_paths, std.fs.path.delimiter);
while (bin_path_iterator.next()) |bin_path| { while (bin_path_iterator.next()) |bin_path| {
if (!std.fs.path.isAbsolute(bin_path)) continue; if (!std.fs.path.isAbsolute(bin_path)) continue;
var dir = std.fs.openDirAbsolute(bin_path, .{}) catch continue; var dir = std.fs.openDirAbsolute(bin_path, .{}) catch continue;
defer dir.close(); defer dir.close();
_ = dir.statFile(binary_name) catch continue; var bin_extensions_iterator = std.mem.splitScalar(u8, bin_extensions, ';');
const resolved_binary_path = try std.fs.path.join(allocator, &[_][]const u8{ bin_path, binary_name }); while (bin_extensions_iterator.next()) |bin_extension| {
defer allocator.free(resolved_binary_path); var path = std.ArrayList(u8).init(allocator);
return try allocator.dupeZ(u8, resolved_binary_path); try path.appendSlice(binary_name_);
try path.appendSlice(bin_extension);
const binary_name = try path.toOwnedSlice();
defer allocator.free(binary_name);
_ = dir.statFile(binary_name) catch continue;
const resolved_binary_path = try std.fs.path.join(allocator, &[_][]const u8{ bin_path, binary_name });
defer allocator.free(resolved_binary_path);
return try allocator.dupeZ(u8, resolved_binary_path);
}
} }
return null; return null;
} }