Skip to content

Commit 5a13801

Browse files
OllieinCanadargushchin
authored andcommitted
ui: prevent progress bar capacity overflow
Signed-off-by: OllieinCanada <73385593+OllieinCanada@users.noreply.github.com>
1 parent c36b518 commit 5a13801

1 file changed

Lines changed: 27 additions & 12 deletions

File tree

src/main.rs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,32 +1148,24 @@ fn render_progress(state: &mut ProgressState) {
11481148
})
11491149
.sum();
11501150
let completed_stages: usize = state.patches.values().map(|p| p.completed_stages).sum();
1151-
let percent = if total_stages > 0 {
1152-
(completed_stages * 100) / total_stages
1153-
} else {
1154-
0
1155-
};
11561151
let width = 20;
1157-
let filled = if total_stages > 0 {
1158-
(completed_stages * width) / total_stages
1159-
} else {
1160-
0
1161-
};
1152+
let (display_completed_stages, percent, filled) =
1153+
calculate_progress_metrics(total_stages, completed_stages, width);
11621154

11631155
let mut tw = TruncatingWriter::new(limit, state.color_choice);
11641156
let _ = tw.write_segment("Overall: [", None, true);
11651157

11661158
let filled_bar = "█".repeat(filled);
11671159
let _ = tw.write_segment(&filled_bar, Some(Color::Green), false);
11681160

1169-
let empty_bar = "░".repeat(width - filled);
1161+
let empty_bar = "░".repeat(width.saturating_sub(filled));
11701162
let _ = tw.write_segment(&empty_bar, None, false);
11711163

11721164
let _ = tw.write_segment("] ", None, true);
11731165

11741166
let stats = format!(
11751167
"{}% | {}/{} stages | {} turns",
1176-
percent, completed_stages, total_stages, state.total_turns
1168+
percent, display_completed_stages, total_stages, state.total_turns
11771169
);
11781170
let _ = tw.write_segment(&stats, None, false);
11791171

@@ -1185,6 +1177,22 @@ fn render_progress(state: &mut ProgressState) {
11851177
let _ = std::io::stderr().flush();
11861178
}
11871179

1180+
fn calculate_progress_metrics(
1181+
total_stages: usize,
1182+
completed_stages: usize,
1183+
width: usize,
1184+
) -> (usize, usize, usize) {
1185+
if total_stages == 0 {
1186+
return (0, 0, 0);
1187+
}
1188+
1189+
let display_completed_stages = completed_stages.min(total_stages);
1190+
let percent = display_completed_stages.saturating_mul(100) / total_stages;
1191+
let filled = (display_completed_stages.saturating_mul(width) / total_stages).min(width);
1192+
1193+
(display_completed_stages, percent, filled)
1194+
}
1195+
11881196
#[allow(clippy::too_many_arguments)]
11891197
async fn handle_review_command(
11901198
input: String,
@@ -2281,6 +2289,13 @@ fn identify_subsystems_from_paths(
22812289
mod tests {
22822290
use super::*;
22832291

2292+
#[test]
2293+
fn test_progress_metrics_clamp_completed_stages_to_total() {
2294+
assert_eq!(calculate_progress_metrics(1, 5, 20), (1, 100, 20));
2295+
assert_eq!(calculate_progress_metrics(5, 2, 20), (2, 40, 8));
2296+
assert_eq!(calculate_progress_metrics(0, 5, 20), (0, 0, 0));
2297+
}
2298+
22842299
#[test]
22852300
fn test_cli_parsing() {
22862301
let args = vec!["sashiko", "--download", "100", "--track", "--no-api"];

0 commit comments

Comments
 (0)