╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ progress.zig ─────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯
26 // the last reported step, so a line is sent only when it changes 27 step: usize = 0, 28 29 // how many items a phase with no total advances between reports 30 const report_every = 1000; 31 32 // the phases a client is told about, listed so a new kind has to be 33 // decided on rather than inherit whatever label was last set. unpacking is 34 // left out because it runs while the client is still sending, so its line 35 // fights with the client's own upload bar over the same row. 36 fn reported(kind: rp.ProgressKind) bool { 37 return switch (kind) { 38 .writing_object, .checking_object, .walking_commit, .enumerating_object, .compressing_object, .writing_patch, .pruning_database, .compacting_database => true, 39 .writing_object_from_pack, .sending_bytes, .receiving_bytes => false, 40 }; 41 } 42 43 pub fn run(self: *Sideband, _: std.Io, event: rp.ProgressEvent) !void { 44 switch (event) { 45 .start => |start| { 46 if (!reported(start.kind)) return; 47 // a pack phase carries no label of its own; the rest send a 48 // .text first 49 switch (start.kind) { 50 .writing_object => self.label = "Copying objects", 51 .checking_object => self.label = "Checking connectivity", 52 .walking_commit => self.label = "Walking commits", 53 .enumerating_object => self.label = "Enumerating objects", 54 .compressing_object => self.label = "Compressing objects", 55 .pruning_database => self.label = "Pruning database", 56 .compacting_database => self.label = "Compacting database", 57 else => {}, 58 } 59 self.total = start.estimated_total_items; 60 self.count = 0; 61 self.step = 0; 62 }, 63 .complete_one => |kind| { 64 if (!reported(kind)) return; 65 self.count += 1; 66 }, 67 .end => |kind| { 68 if (!reported(kind)) return; 69 }, 70 // each phase names itself before reporting its count 71 .text => |text| { 72 self.label = text; 73 return; 74 }, 75 else => return, 76 } 77 // a phase that knows no total counts instead, and stays quiet until it 78 // has something to count 79 if (self.total == 0 and self.count == 0) return; 80 81 // every report flushes, so one is sent per percent, or per block of 82 // items when there is no total to turn into one 83 const step: usize = if (self.total > 0) @intCast(@as(u128, self.count) * 100 / self.total) else self.count / report_every; 84 if (event == .complete_one and step == self.step) return; 85 self.step = step; 86 87 // reporting is the only moment a transaction looks up from its work 88 if (self.sess) |sess| if (sess.peerGone()) { 89 self.gone = true; 90 return error.ClientGone; 91 }; 92 93 var buffer: [128]u8 = undefined; 94 const suffix = if (event == .end) "\n" else "\r"; 95 const text = if (self.total > 0) 96 try std.fmt.bufPrint(&buffer, "{s}: {d}% ({d}/{d}){s}", .{ self.label, step, self.count, self.total, suffix }) 97 else 98 try std.fmt.bufPrint(&buffer, "{s}: {d}{s}", .{ self.label, self.count, suffix }); 99 if (self.response) |response| { 100 try response.progress(self.writer, text); 101 } else { 102 try xit.net_server_pkt.sendSideband(self.writer, 2, text); 103 try self.writer.flush(); 104 } 105 } 106 }; 107 108 // whether the client the work is reporting to has hung up. only a sideband 109 // reporter probes, so any other context never cancels. 110 pub fn cancelled(comptime repo_opts: rp.RepoOpts(.xit), progress_ctx_maybe: ?repo_opts.ProgressCtx) bool { 111 if (repo_opts.ProgressCtx != *Sideband) return false; 112 const progress_ctx = progress_ctx_maybe orelse return false; 113 return progress_ctx.gone; 114 } 115