11const std = @import ("std" );
22
3+ /// Returns true when `path` exists relative to the current working directory.
34pub fn fileExists (path : []const u8 ) bool {
45 std .fs .cwd ().access (path , .{}) catch return false ;
56 return true ;
67}
78
9+ /// Creates `path` and any missing parent directories.
810pub fn ensureDir (path : []const u8 ) ! void {
911 try std .fs .cwd ().makePath (path );
1012}
1113
14+ /// Renders argv-like tokens as a shell-style debug string.
1215pub fn joinArgs (alloc : std.mem.Allocator , argv : []const []const u8 ) ! []u8 {
1316 var out = std .ArrayList (u8 ).empty ;
1417 errdefer out .deinit (alloc );
@@ -26,6 +29,7 @@ pub fn joinArgs(alloc: std.mem.Allocator, argv: []const []const u8) ![]u8 {
2629 return out .toOwnedSlice (alloc );
2730}
2831
32+ /// Runs a child process inheriting stdio, returning error on non-zero exit.
2933pub fn runInherit (alloc : std.mem.Allocator , argv : []const []const u8 , cwd : ? []const u8 ) ! void {
3034 const pretty = try joinArgs (alloc , argv );
3135 defer alloc .free (pretty );
@@ -44,6 +48,7 @@ pub fn runInherit(alloc: std.mem.Allocator, argv: []const []const u8, cwd: ?[]co
4448 }
4549}
4650
51+ /// Runs a child process and returns combined stdout/stderr output.
4752pub fn runCaptureCombined (alloc : std.mem.Allocator , argv : []const []const u8 , cwd : ? []const u8 ) ! []u8 {
4853 const res = try std .process .Child .run (.{
4954 .allocator = alloc ,
@@ -68,6 +73,7 @@ pub fn runCaptureCombined(alloc: std.mem.Allocator, argv: []const []const u8, cw
6873 return out .toOwnedSlice (alloc );
6974}
7075
76+ /// Runs a child process and returns trimmed stdout output.
7177pub fn runCaptureStdout (alloc : std.mem.Allocator , argv : []const []const u8 , cwd : ? []const u8 ) ! []u8 {
7278 const res = try std .process .Child .run (.{
7379 .allocator = alloc ,
@@ -84,6 +90,7 @@ pub fn runCaptureStdout(alloc: std.mem.Allocator, argv: []const []const u8, cwd:
8490 return alloc .dupe (u8 , std .mem .trim (u8 , res .stdout , " \r \n \t " ));
8591}
8692
93+ /// Parses the last decimal integer token found in `text`.
8794pub fn parseLastInt (text : []const u8 ) ! u64 {
8895 var i : usize = text .len ;
8996 while (i > 0 ) : (i -= 1 ) {
@@ -96,6 +103,7 @@ pub fn parseLastInt(text: []const u8) !u64 {
96103 return std .fmt .parseInt (u64 , text [start .. i ], 10 );
97104}
98105
106+ /// Returns median value from `vals` (upper median for even length).
99107pub fn medianU64 (alloc : std.mem.Allocator , vals : []const u64 ) ! u64 {
100108 if (vals .len == 0 ) return error .EmptyInput ;
101109 const copy = try alloc .dupe (u64 , vals );
@@ -104,16 +112,19 @@ pub fn medianU64(alloc: std.mem.Allocator, vals: []const u64) !u64 {
104112 return copy [copy .len / 2 ];
105113}
106114
115+ /// Writes `bytes` to `path`, truncating any existing file.
107116pub fn writeFile (path : []const u8 , bytes : []const u8 ) ! void {
108117 const file = try std .fs .cwd ().createFile (path , .{ .truncate = true });
109118 defer file .close ();
110119 try file .writeAll (bytes );
111120}
112121
122+ /// Reads an entire file into allocator-owned memory.
113123pub fn readFileAlloc (alloc : std.mem.Allocator , path : []const u8 ) ! []u8 {
114124 return try std .fs .cwd ().readFileAlloc (alloc , path , std .math .maxInt (usize ));
115125}
116126
127+ /// Returns current UNIX timestamp in seconds.
117128pub fn nowUnix () i64 {
118129 return std .time .timestamp ();
119130}
0 commit comments