From 96c69c16367df7016a82e081cdb151af2886d08c Mon Sep 17 00:00:00 2001 From: Arian Dehghani Date: Thu, 20 Feb 2025 12:57:58 -0800 Subject: [PATCH] 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 --- src/bin_path.zig | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/bin_path.zig b/src/bin_path.zig index 756edfa..149a141 100644 --- a/src/bin_path.zig +++ b/src/bin_path.zig @@ -28,20 +28,28 @@ fn find_binary_in_path_windows(allocator: std.mem.Allocator, binary_name_: []con error.EnvironmentVariableNotFound, error.InvalidWtf8 => &.{}, }; defer allocator.free(bin_paths); - var path = std.ArrayList(u8).init(allocator); - try path.appendSlice(binary_name_); - try path.appendSlice(".exe"); - const binary_name = try path.toOwnedSlice(); - defer allocator.free(binary_name); + const bin_extensions = std.process.getEnvVarOwned(allocator, "PATHEXT") catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.EnvironmentVariableNotFound, error.InvalidWtf8 => &.{}, + }; + defer allocator.free(bin_extensions); var bin_path_iterator = std.mem.splitScalar(u8, bin_paths, std.fs.path.delimiter); while (bin_path_iterator.next()) |bin_path| { if (!std.fs.path.isAbsolute(bin_path)) continue; var dir = std.fs.openDirAbsolute(bin_path, .{}) catch continue; defer dir.close(); - _ = 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); + var bin_extensions_iterator = std.mem.splitScalar(u8, bin_extensions, ';'); + while (bin_extensions_iterator.next()) |bin_extension| { + var path = std.ArrayList(u8).init(allocator); + 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; }