╭ changed ────╮ │build.zig.zon│ ╰─────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 3 .version = "0.0.0", │ │ 4 .dependencies = .{ │ │ 5 .xit = .{ │ │ 6 - .url = "git+https://github.com/xit-vcs/xit#5e4e683bdb5606a8ea10e037437c0d6c9624cf8a",│ │ 7 - .hash = "xit-0.0.0-Ub3nDOwEVAGjvCCeQEntxdFIOAERTuVNrYXYDCzYv2Ve", │ │ 6 + .url = "git+https://github.com/xit-vcs/xit#784a2c620ef05f6d0044fea7728eb2182a7009b8",│ │ 7 + .hash = "xit-0.0.0-Ub3nDC4OVAGih5LYUNG-i84UTl9J51Lq9kpk9lD_rnfr", │ │ 8 }, │ │ 9 }, │ │10 .paths = .{ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───╮ │src/push.zig│ ╰────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────╮ │36 try iter.include(&oid); │ │37 } │ │38 } │ │39 - var progress = serve_common.PushProgress{ .response = response, .writer = writer }; │ │39 + var progress = serve_common.SidebandProgress{ .response = response, .writer = writer };│ │40 try xit.patch.writePatches(repo_opts, state, io, allocator, &iter, &progress); │ │41 } │ │42 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │132 var updates = xit.net_server_receive_pack.AppliedRefUpdates.init(allocator); │ │133 defer updates.deinit(); │ │134 │ │135 - var progress = serve_common.PushProgress{ .response = &response, .writer = writer, .sess = sess }; │ │135 + var progress = serve_common.SidebandProgress{ .response = &response, .writer = writer, .sess = sess };│ │136 const Ctx = struct { │ │137 updates: *xit.net_server_receive_pack.AppliedRefUpdates, │ │138 core: *rp.Repo(.xit, repo_opts).Core, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────╮ │145 response: *xit.net_server_receive_pack.Response, │ │146 repo_root_path: []const u8, │ │147 error_writer: *std.Io.Writer, │ │148 - progress: *serve_common.PushProgress, │ │148 + progress: *serve_common.SidebandProgress, │ │149 │ │150 pub fn run(ctx: @This(), cursor: *DB.Cursor(.read_write)) !void {│ │151 var moment = try DB.HashMap(.read_write).init(cursor.*); │ ╰──────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │260 var revision_id_maybe: ?[evt.event_id_size]u8 = null; │ │261 var response = xit.net_server_receive_pack.Response.init(allocator); │ │262 defer response.deinit(); │ │263 - var progress = serve_common.PushProgress{ .response = &response, .writer = writer, .sess = sess }; │ │263 + var progress = serve_common.SidebandProgress{ .response = &response, .writer = writer, .sess = sess };│ │264 │ │265 // execute a transaction that receives the push and materializes its revision │ │266 const result = blk: { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │283 timestamp: u64, │ │284 newest: ?evt.PatchRev.WithId, │ │285 revision_id_maybe: *?[evt.event_id_size]u8, │ │286 - progress: *serve_common.PushProgress, │ │286 + progress: *serve_common.SidebandProgress, │ │287 │ │288 pub fn run(ctx: @This(), cursor: *DB.Cursor(.read_write)) !void {│ │289 // receive the branch update │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────╮ │src/serve_common.zig│ ╰────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │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 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯