const std = @import("std");const io_mod = @import("../shared/io.zig"); const Allocator = std.mem.Allocator; pub const CommandResult = struct { exit_code: i64, stdout: []u8, stderr: []u8, duration_ms: ?u64 = null, pub fn deinit(self: *CommandResult, alloc: Allocator) void { alloc.free(self.stdout); alloc.free(self.stderr); self.* = undefined; } /// Caller owns the returned copy. pub fn clone(self: CommandResult, alloc: Allocator) !CommandResult { const stdout = try alloc.dupe(u8, self.stdout); errdefer alloc.free(stdout); const stderr = try alloc.dupe(u8, self.stderr); errdefer alloc.free(stderr); return .{ .exit_code = self.exit_code, .stdout = stdout, .stderr = stderr, .duration_ms = self.duration_ms, }; }}; pub const Control = struct { cancel_flag: ?*std.atomic.Value(bool) = null, timeout_ms: ?usize = null, started_ms: i64, pub fn check(self: Control) !void { if (self.cancel_flag) |flag| { if (flag.load(.seq_cst)) return error.Cancelled; } if (self.timeout_ms) |timeout_ms| { const now_ms = io_mod.milliTimestamp(); const elapsed_ms: u64 = if (now_ms > self.started_ms) @intCast(now_ms - self.started_ms) else 0; if (elapsed_ms >= timeout_ms) return error.TimeoutExpired; } } pub fn canInterrupt(self: Control) bool { return self.cancel_flag != null or self.timeout_ms != null; }}; pub const VercelOutcome = union(enum) { success: CommandResult, unavailable, request_failed,}; pub const ProviderError = error{ OutOfMemory, Cancelled, TimeoutExpired,}; pub const ProviderFn = *const fn ( ?*anyopaque, Allocator, []const u8, []const u8, Control,) ProviderError!VercelOutcome; pub const Provider = struct { ctx: ?*anyopaque = null, execute_fn: ProviderFn, pub fn execute( self: Provider, alloc: Allocator, command: []const u8, cwd: []const u8, control: Control, ) ProviderError!VercelOutcome { return self.execute_fn(self.ctx, alloc, command, cwd, control); }};
const std = @import("std");
const io_mod = @import("../shared/io.zig");
const Allocator = std.mem.Allocator;
pub const CommandResult = struct {
exit_code: i64,
stdout: []u8,
stderr: []u8,
duration_ms: ?u64 = null,
pub fn deinit(self: *CommandResult, alloc: Allocator) void {
alloc.free(self.stdout);
alloc.free(self.stderr);
self.* = undefined;
}
/// Caller owns the returned copy.
pub fn clone(self: CommandResult, alloc: Allocator) !CommandResult {
const stdout = try alloc.dupe(u8, self.stdout);
errdefer alloc.free(stdout);
const stderr = try alloc.dupe(u8, self.stderr);
errdefer alloc.free(stderr);
return .{
.exit_code = self.exit_code,
.stdout = stdout,
.stderr = stderr,
.duration_ms = self.duration_ms,
};
}
};
pub const Control = struct {
cancel_flag: ?*std.atomic.Value(bool) = null,
timeout_ms: ?usize = null,
started_ms: i64,
pub fn check(self: Control) !void {
if (self.cancel_flag) |flag| {
if (flag.load(.seq_cst)) return error.Cancelled;
}
if (self.timeout_ms) |timeout_ms| {
const now_ms = io_mod.milliTimestamp();
const elapsed_ms: u64 = if (now_ms > self.started_ms) @intCast(now_ms - self.started_ms) else 0;
if (elapsed_ms >= timeout_ms) return error.TimeoutExpired;
}
}
pub fn canInterrupt(self: Control) bool {
return self.cancel_flag != null or self.timeout_ms != null;
}
};
pub const VercelOutcome = union(enum) {
success: CommandResult,
unavailable,
request_failed,
};
pub const ProviderError = error{
OutOfMemory,
Cancelled,
TimeoutExpired,
};
pub const ProviderFn = *const fn (
?*anyopaque,
Allocator,
[]const u8,
[]const u8,
Control,
) ProviderError!VercelOutcome;
pub const Provider = struct {
ctx: ?*anyopaque = null,
execute_fn: ProviderFn,
pub fn execute(
self: Provider,
alloc: Allocator,
command: []const u8,
cwd: []const u8,
control: Control,
) ProviderError!VercelOutcome {
return self.execute_fn(self.ctx, alloc, command, cwd, control);
}
};