╭ changed ────╮ │build.zig.zon│ ╰─────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 3 .version = "0.0.0", │ │ 4 .dependencies = .{ │ │ 5 .xit = .{ │ │ 6 - .url = "git+https://github.com/xit-vcs/xit#67e37f5c37a04db17f5d985424639b7a20157c85",│ │ 7 - .hash = "xit-0.0.0-Ub3nDFksVAFHFM9QQaSYFCL7OjF5PVKwfIkNiursLxn1", │ │ 6 + .url = "git+https://github.com/xit-vcs/xit#f45f785b423dfa88288974ca405dd8822529c640",│ │ 7 + .hash = "xit-0.0.0-Ub3nDLwxVAHK56fiI9PPem70Ut4k6xdWHvszjrVCw1jg", │ │ 8 }, │ │ 9 }, │ │10 .paths = .{ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───╮ │src/main.zig│ ╰────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │15 // the user's global git config, used for the commit identity in local mode.│ │16 // null by default so tests and the server paths never read it. │ │17 global_config_path: ?[]const u8 = null, │ │18 + // false when NO_COLOR is set, so the TUI draws without colors │ │19 + color: bool = true, │ │20 }; │ │21 │ │22 pub fn main(init: std.process.Init) !u8 { │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────╮ │50 .out = &stdout_writer.interface, │ │51 .err = &stderr_writer.interface, │ │52 .global_config_path = global_config_path, │ │53 + .color = std.mem.eql(u8, environ_map.get("NO_COLOR") orelse "", ""),│ │54 }; │ │55 │ │56 const cwd_path = try std.process.currentPathAlloc(io, allocator); │ ╰────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────╮ │132 .io = io, │ │133 .local = local, │ │134 .is_terminal = true, │ │135 + .color = run_opts.color, │ │136 .data = .{ │ │137 // the files root; local routes carry no identity │ │138 .current_page = .{ .repo_files = .{ .name = .{} } },│ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────╮ │src/serve_ssh.zig│ ╰─────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │39 pub fn handleSession(self: *const SessionHandler, sess: *ssh.SessionCtx, request: ssh.Request) !void { │ │40 serve_common.logError(sess.conn.io, self.err, "ssh session: kind={s} key={s}\n", .{ @tagName(request), sess.fingerprint });│ │41 switch (request) { │ │42 - .shell => |pty_maybe| { │ │43 - const pty = pty_maybe orelse { │ │42 + .shell => |shell| { │ │43 + const pty = shell.pty orelse { │ │44 // a shell without a pty has no useful TUI to render; in │ │45 // openssh client terms this is `ssh -T host`. say so and │ │46 // exit non-zero. │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────╮ │49 return; │ │50 }; │ │51 sess.exemptFromIdleTimeout(); │ │52 - try runTuiSession(self, sess, pty); │ │52 + try runTuiSession(self, sess, pty, shell.color);│ │53 }, │ │54 .exec => |exec| { │ │55 try runGitSession(self, sess, exec); │ ╰────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │194 } │ │195 }; │ │196 │ │197 -fn runTuiSession(handler: *const SessionHandler, sess: *ssh.SessionCtx, pty: ssh.PtySize) !void { │ │197 +fn runTuiSession(handler: *const SessionHandler, sess: *ssh.SessionCtx, pty: ssh.PtySize, color: bool) !void {│ │198 // runTui owns the terminal, whose deinit restores the client's screen and │ │199 // runs as the function unwinds — so any error it returns leaves the TUI torn │ │200 // down and we can surface the failure on the restored screen before exiting. │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │201 - runTui(handler, sess, pty) catch |tui_err| { │ │201 + runTui(handler, sess, pty, color) catch |tui_err| { │ │202 const err = sess.underlyingError(tui_err); │ │203 serve_common.logError(sess.conn.io, handler.err, "ssh tui session failed: {s}\n", .{@errorName(err)});│ │204 var buf: [256]u8 = undefined; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │208 }; │ │209 } │ │210 │ │211 -fn runTui(handler: *const SessionHandler, sess: *ssh.SessionCtx, pty: ssh.PtySize) !void { │ │211 +fn runTui(handler: *const SessionHandler, sess: *ssh.SessionCtx, pty: ssh.PtySize, color: bool) !void {│ │212 const allocator = sess.conn.allocator; │ │213 const io = sess.conn.io; │ │214 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────╮ │229 defer repo.deinit(io, allocator); │ │230 var ui_session = try ui.Session.init(&session_arena, &repo, .{});│ │231 ui_session.is_terminal = true; │ │232 + ui_session.color = color; │ │233 ui_session.web_port = handler.wui_port; │ │234 ui_session.data.git_http_port = handler.git_http_port; │ │235 ui_session.data.git_ssh_port = handler.git_ssh_port; │ ╰──────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯