const std = @import("std");
const Io = std.Io;
const valid_export =
"feature done\n" ++
"blob\n" ++
"mark :1\n" ++
"data 5\n" ++
"hello\n" ++
"commit refs/heads/main\n" ++
"mark :2\n" ++
"author A <[email protected]> 0 +0000\n" ++
"committer A <[email protected]> 0 +0000\n" ++
"data 4\n" ++
"init\n" ++
"M 100644 :1 README\n" ++
"\n" ++
"done\n";
pub fn main(init: std.process.Init) !void {
const io = init.io;
const args = try init.minimal.args.toSlice(init.arena.allocator());
const mode = if (args.len > 1) args[1] else "success";
var out_buffer: [1024]u8 = undefined;
var out = Io.File.Writer.initStreaming(.stdout(), io, &out_buffer);
var err_buffer: [1024]u8 = undefined;
var err = Io.File.Writer.initStreaming(.stderr(), io, &err_buffer);
// 8 MiB exceeds ordinary pipe capacity. Writing it before stdout makes a
// non-concurrent stderr drain deadlock, exactly what the parent test needs
// to detect, while this direct executable remains shell-free and local.
const chunk_bytes: [8192]u8 = @splat('x');
const chunk: []const u8 = &chunk_bytes;
if (!std.mem.eql(u8, mode, "truncated-nonzero")) {
for (0..1024) |_| try err.interface.writeAll(chunk);
try err.interface.flush();
}
if (std.mem.eql(u8, mode, "hold")) {
try out.interface.writeAll("feature done\nblob\nmark :1\ndata 1\nx\nbogus\n");
try out.interface.flush();
try std.Io.sleep(io, .fromSeconds(60), .awake);
return;
}
if (std.mem.eql(u8, mode, "truncated-nonzero")) {
try out.interface.writeAll("feature done\nblob\nmark :1\ndata 1\nx\n");
try out.interface.flush();
try err.interface.writeAll("fatal: signed commit rejected\n");
try err.interface.flush();
std.process.exit(23);
}
try out.interface.writeAll(valid_export);
try out.interface.flush();
if (std.mem.eql(u8, mode, "nonzero")) std.process.exit(23);
}