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