From 9dacc276949fdb8919eef98a688447430936cacc Mon Sep 17 00:00:00 2001 From: StressTestor <212606152+StressTestor@users.noreply.github.com> Date: Sun, 31 May 2026 15:17:05 -0600 Subject: [PATCH] fix(log): avoid panic when showing log of a branch with no commits Opening the log of a branch with no commits panicked with "index out of bounds: the len is 0 but the index is 0". The log screen had no items, so `line_index` was empty, but `update_cursor` still tried to position the cursor and indexed `line_index[0]` via `at_line`. Guard `update_cursor` to reset the cursor when nothing is selectable, matching the existing empty-checks in the other cursor/scroll helpers. Closes #262 --- src/screen/mod.rs | 8 ++++++ src/tests/log.rs | 15 +++++++++++ .../gitu__tests__log__log_empty_branch.snap | 25 +++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 src/tests/snapshots/gitu__tests__log__log_empty_branch.snap diff --git a/src/screen/mod.rs b/src/screen/mod.rs index 41376296bc..4020ce404e 100644 --- a/src/screen/mod.rs +++ b/src/screen/mod.rs @@ -234,6 +234,14 @@ impl Screen { } fn update_cursor(&mut self, nav_mode: NavMode) { + // Nothing is selectable (e.g. the log of a branch with no commits). + // Reset the cursor to a valid sentinel rather than positioning it, + // which would index into an empty `line_index` and panic (#262). + if self.line_index.is_empty() { + self.cursor = 0; + return; + } + self.clamp_cursor(); if self.is_cursor_off_screen() { self.move_cursor_to_screen_center(); diff --git a/src/tests/log.rs b/src/tests/log.rs index dd6d086316..a50204342a 100644 --- a/src/tests/log.rs +++ b/src/tests/log.rs @@ -76,3 +76,18 @@ fn log_other_input() { fn log_other_invalid() { snapshot!(setup(setup_clone!()), "lo "); } + +#[test] +fn log_empty_branch() { + // Regression for #262: showing the log of a branch with no commits used to + // panic ("index out of bounds") because the log screen had no items but the + // cursor still indexed into it. + let mut ctx = setup_clone!(); + run(&ctx.dir, &["rm", "-rf", ".git"]); + run(&ctx.dir, &["rm", "initial-file"]); + run(&ctx.dir, &["git", "init", "--initial-branch=main"]); + + let mut app = ctx.init_app(); + ctx.update(&mut app, keys("ll")); + insta::assert_snapshot!(ctx.redact_buffer()); +} diff --git a/src/tests/snapshots/gitu__tests__log__log_empty_branch.snap b/src/tests/snapshots/gitu__tests__log__log_empty_branch.snap new file mode 100644 index 0000000000..2049dfc25c --- /dev/null +++ b/src/tests/snapshots/gitu__tests__log__log_empty_branch.snap @@ -0,0 +1,25 @@ +--- +source: src/tests/log.rs +expression: ctx.redact_buffer() +--- + | + | + | + | + | + | + | + | + | + | + | + | + | + | + | + | + | + | + | + | +styles_hash: 355101d0bd329837