╭ changed ───────────╮ │src/serve_common.zig│ ╰────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │11 } │ │12 } │ │13 │ │14 -// progress for a push, sent on the pack stream's sideband │ │15 -pub const PushProgress = struct { │ │16 - response: *xit.net_server_receive_pack.Response, │ │14 +// progress for a push or a clone, sent on the pack stream's sideband │ │15 +pub const SidebandProgress = struct { │ │16 + // a push reports through its deferred response, which knows whether the │ │17 + // client wanted sideband at all. a clone has none and writes band 2 itself.│ │18 + response: ?*xit.net_server_receive_pack.Response = null, │ │19 writer: *std.Io.Writer, │ │20 // the client to probe, absent when nothing is listening │ │21 sess: ?*ssh.SessionCtx = null, │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │30 // how many items a phase with no total advances between reports │ │31 const report_every = 1000; │ │32 │ │31 - // the phases a push reports: the objects unpacked from the pack it │ │32 - // received, then everything counted after it │ │33 + // the phases a client is told about, listed so a new kind has to be │ │34 + // decided on rather than inherit whatever label was last set │ │35 fn reported(kind: rp.ProgressKind) bool { │ │34 - return kind == .writing_object_from_pack or kind == .writing_patch; │ │36 + return switch (kind) { │ │37 + .writing_object_from_pack, .enumerating_object, .compressing_object, .writing_patch => true,│ │38 + .writing_object, .sending_bytes, .receiving_bytes => false, │ │39 + }; │ │40 } │ │41 │ │37 - pub fn run(self: *PushProgress, _: std.Io, event: rp.ProgressEvent) !void { │ │42 + pub fn run(self: *SidebandProgress, _: std.Io, event: rp.ProgressEvent) !void { │ │43 switch (event) { │ │44 .start => |start| { │ │45 if (!reported(start.kind)) return; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │41 - // the unpack phase sends no label of its own │ │42 - if (start.kind == .writing_object_from_pack) self.label = "Unpacking objects";│ │46 + // a pack phase carries no label of its own; the rest send a │ │47 + // .text first │ │48 + switch (start.kind) { │ │49 + .writing_object_from_pack => self.label = "Unpacking objects", │ │50 + .enumerating_object => self.label = "Enumerating objects", │ │51 + .compressing_object => self.label = "Compressing objects", │ │52 + else => {}, │ │53 + } │ │54 self.total = start.estimated_total_items; │ │55 self.count = 0; │ │56 self.step = 0; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 91 try std.fmt.bufPrint(&buffer, "{s}: {d}% ({d}/{d}){s}", .{ self.label, step, self.count, self.total, suffix })│ │ 92 else │ │ 93 try std.fmt.bufPrint(&buffer, "{s}: {d}{s}", .{ self.label, self.count, suffix }); │ │ 83 - try self.response.progress(self.writer, text); │ │ 94 + if (self.response) |response| { │ │ 95 + try response.progress(self.writer, text); │ │ 96 + } else { │ │ 97 + try xit.net_server_pkt.sendSideband(self.writer, 2, text); │ │ 98 + try self.writer.flush(); │ │ 99 + } │ │100 } │ │101 }; │ │102 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯