diff options
author | 2021-10-14 05:22:47 -0700 | |
---|---|---|
committer | 2021-10-14 05:22:47 -0700 | |
commit | 4b618f9ad1a45f6819dcb65e9b6b5b859e0df9fd (patch) | |
tree | 9bc3aac20a9ab2863be3409c6cffb9983d165b84 /src/which.zig | |
parent | 0f7bc76f39b6792052be799779e8d10ee03c564c (diff) | |
download | bun-4b618f9ad1a45f6819dcb65e9b6b5b859e0df9fd.tar.gz bun-4b618f9ad1a45f6819dcb65e9b6b5b859e0df9fd.tar.zst bun-4b618f9ad1a45f6819dcb65e9b6b5b859e0df9fd.zip |
`bun create react app` is almost done
Diffstat (limited to 'src/which.zig')
-rw-r--r-- | src/which.zig | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/src/which.zig b/src/which.zig new file mode 100644 index 000000000..7cb65cbe2 --- /dev/null +++ b/src/which.zig @@ -0,0 +1,40 @@ +const std = @import("std"); + +fn isValid(buf: *[std.fs.MAX_PATH_BYTES]u8, segment: []const u8, bin: []const u8) ?u16 { + std.mem.copy(u8, buf, segment); + buf[segment.len] = std.fs.path.sep; + std.mem.copy(u8, buf[segment.len + 1 ..], bin); + buf[segment.len + 1 + bin.len ..][0] = 0; + var filepath = buf[0 .. segment.len + 1 + bin.len :0]; + + std.os.accessZ(filepath, std.os.X_OK) catch return null; + return @intCast(u16, filepath.len); +} + +// Like /usr/bin/which but without needing to exec a child process +// Remember to resolve the symlink if necessary +pub fn which(buf: *[std.fs.MAX_PATH_BYTES]u8, path: []const u8, cwd: []const u8, bin: []const u8) ?[:0]const u8 { + if (isValid(buf, std.mem.trimRight(u8, cwd, std.fs.path.sep_str), bin)) |len| { + return buf[0..len :0]; + } + + var path_iter = std.mem.tokenize(u8, path, ":"); + while (path_iter.next()) |segment| { + if (isValid(buf, segment, bin)) |len| { + return buf[0..len :0]; + } + } + + return null; +} + +test "which" { + var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var realpath = std.os.getenv("PATH") orelse unreachable; + var whichbin = which(&buf, realpath, try std.process.getCwdAlloc(std.heap.c_allocator), "which"); + try std.testing.expectEqualStrings(whichbin orelse return std.debug.assert(false), "/usr/bin/which"); + try std.testing.expect(null == which(&buf, realpath, try std.process.getCwdAlloc(std.heap.c_allocator), "baconnnnnn")); + try std.testing.expect(null != which(&buf, realpath, try std.process.getCwdAlloc(std.heap.c_allocator), "zig")); + try std.testing.expect(null == which(&buf, realpath, try std.process.getCwdAlloc(std.heap.c_allocator), "bin")); + try std.testing.expect(null == which(&buf, realpath, try std.process.getCwdAlloc(std.heap.c_allocator), "usr")); +} |