╭ changed ────╮ │build.zig.zon│ ╰─────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 3 .version = "0.0.0", │ │ 4 .dependencies = .{ │ │ 5 .xit = .{ │ │ 6 - .url = "git+https://github.com/xit-vcs/xit#abb9dd0eb25acfe1138e50a89fddcb8d4584d6e3",│ │ 7 - .hash = "xit-0.0.0-Ub3nDH5MTwF3pS471llPX_eB8G5KfyXpiNTJdOuW4a1j", │ │ 6 + .url = "git+https://github.com/xit-vcs/xit#d852314d281940090f3f0a8c5b8d97437a4024d9",│ │ 7 + .hash = "xit-0.0.0-Ub3nDORQTwGhcCHiWDdUxsz4EnIRZp0ehyAi7DgpjDeG", │ │ 8 }, │ │ 9 }, │ │10 .paths = .{ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────╮ │src/command.zig│ ╰───────────────╯ ╭─────────────────────────╮ │ 7 upload_pack, │ │ 8 receive_pack, │ │ 9 http_backend, │ │10 + serve, │ │11 }; │ │12 │ │13 const Help = struct {│ ╰─────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │43 , │ │44 .example = │ │45 \\haxy http-backend │ │46 + , │ │47 + }, │ │48 + .serve => .{ │ │49 + .name = "serve", │ │50 + .descrip = │ │51 + \\a long-running HTTP server forwarding receive-pack and upload-pack.│ │52 + , │ │53 + .example = │ │54 + \\haxy serve --http-listen 127.0.0.1:8080 --project-root /srv/git │ │55 , │ │56 }, │ │57 }; │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │113 │ │114 // flags that can have a value associated with them │ │115 // must be included here │ │106 - const value_flags = std.StaticStringMap(void).initComptime(.{}); │ │116 + const value_flags = std.StaticStringMap(void).initComptime(.{ │ │117 + .{"--http-listen"}, │ │118 + .{"--project-root"}, │ │119 + }); │ │120 │ │121 pub fn init(allocator: std.mem.Allocator, args: []const []const u8) !CommandArgs {│ │122 const arena = try allocator.create(std.heap.ArenaAllocator); │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │216 options: xit.net_server_receive_pack.Options, │ │217 }, │ │218 http_backend, │ │219 + serve: struct { │ │220 + http_listen: []const u8, │ │221 + project_root: []const u8, │ │222 + }, │ │223 │ │224 pub fn initMaybe(cmd_args: *CommandArgs) !?Command(repo_kind, hash_kind) {│ │225 const command_kind = cmd_args.command_kind orelse return null; │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │252 │ │253 return .http_backend; │ │254 }, │ │255 + .serve => { │ │256 + if (cmd_args.positional_args.len != 0) return null; │ │257 + │ │258 + return .{ .serve = .{ │ │259 + .http_listen = (cmd_args.get("--http-listen") orelse null) orelse "127.0.0.1:8080",│ │260 + .project_root = (cmd_args.get("--project-root") orelse null) orelse ".", │ │261 + } }; │ │262 + }, │ │263 } │ │264 } │ │265 }; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───╮ │src/main.zig│ ╰────────────╯ ╭────────────────────────────────────────╮ │3 const xit = @import("xit"); │ │4 const rp = xit.repo; │ │5 const cmd = @import("./command.zig");│ │6 +const serve = @import("./serve.zig");│ │7 │ │8 pub const RunOpts = struct { │ │9 out: *std.Io.Writer, │ ╰────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │74 }, │ │75 .help => |cmd_kind_maybe| try cmd.printHelp(cmd_kind_maybe, run_opts.out), │ │76 .cli => |cli_cmd| { │ │77 + if (cli_cmd == .serve) { │ │78 + try serve.run(repo_kind, any_repo_opts, io, allocator, cwd_path, .{ │ │79 + .http_listen = cli_cmd.serve.http_listen, │ │80 + .project_root = cli_cmd.serve.project_root, │ │81 + }, run_opts.err); │ │82 + return; │ │83 + } │ │84 + │ │85 // some commands allow the path to be specified. for all others, just use the cwd path. │ │86 const work_path = switch (cli_cmd) { │ │87 .upload_pack => |upload_pack| try std.fs.path.resolve(allocator, &.{ cwd_path, upload_pack.dir }),│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────╮ │92 try xit.net_server_http_backend.sendNotFound(&http_stdout_writer.interface);│ │93 return; │ │94 }, │ │95 + .serve => unreachable, │ │96 }; │ │97 defer allocator.free(work_path); │ │98 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │167 │ │168 var stdin_buf: [repo_opts.net_buffer_size]u8 = undefined; │ │169 var stdin_reader = std.Io.File.stdin().reader(io, &stdin_buf); │ │160 - try repo.httpBackend(io, allocator, &stdin_reader.interface, &stdout_writer.interface, .{ │ │170 + try repo.httpBackend(io, allocator, &stdin_reader.interface, &stdout_writer.interface, .cgi, .{│ │171 .request_method = request_method, │ │172 .handler = handler, │ │173 .suffix = suffix, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯