## 再現手順 1. [[git-igitt]]を起動 2. 一番下のコミットまで移動 3. 1つ上のコミットに移動 ## エラーログ ```error thread 'main' panicked at 'assertion failed: min <= max', /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be\library\core\src\cmp.rs:840:9 stack backtrace: 0: std::panicking::begin_panic_handler at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library\std\src\panicking.rs:593 1: core::panicking::panic_fmt at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library\core\src\panicking.rs:67 2: core::panicking::panic at /rustc/5680fa18feaa87f3ff04063800aec256c3d4b4be/library\core\src\panicking.rs:117 3: __ImageBase 4: __ImageBase 5: __ImageBase 6: __ImageBase 7: __ImageBase 8: main 9: invoke_main at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78 10: __scrt_common_main_seh at D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288 11: BaseThreadInitThunk 12: RtlUserThreadStart note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. ``` ## 調査 落ちている場所は分からないので検討をつけにいってみる。 コマンド(ホットキー)に関する処理は`main.rs`に記載されているので眺めてみる。以下のようにコメントアウトしてみた。 ```rust KeyCode::Up | KeyCode::Char('k') => { let (rd, rf) = app.on_up( false, // XXX event.modifiers.contains(KeyModifiers::CONTROL), )?; // reload_diffs = rd; // reload_file = rf; } ``` この場合も再現する。つまり問題は`app.on_up`で起こっている。 `graph_view.rs`の以下が実行される。 ```rust impl GraphViewState { pub fn move_selection(&mut self, steps: usize, down: bool) -> bool { // steps: 1, down: false stdout().execute(cursor::MoveTo(150, 20)); stdout().execute(crossterm::style::Print(format!( "steps: {:8}", self.selected.unwrap() ))); let changed = if let Some(sel) = self.selected { let new_idx = if down { std::cmp::min(sel.saturating_add(steps), self.indices.len() - 1) } else { std::cmp::max(sel.saturating_sub(steps), 0) }; self.selected = Some(new_idx); new_idx != sel } else if !self.graph_lines.is_empty() { self.selected = Some(0); true } else { false }; if changed { self.secondary_changed = false; } changed } ``` - 1番上が0 - 1つ下が1 - 1番下だと落ちるからわからん.. `123`までは表示されたのでそこ。 ``` 124番目 125番目 126番目 ``` - 124 -> 125が落ちる - 126 -> 125も落ちる もしかして125への移動がダメ? 126に移動してその後に移動しても落ちない...。ムムム。 `-n 15`でやっても最後から2つ目で落ちる。コミットグラフの内容の問題ではない気がする。 `clamp`で落ちていることは分かった。 ```rust #[must_use] #[stable(feature = "clamp", since = "1.50.0")] fn clamp(self, min: Self, max: Self) -> Self where Self: Sized, Self: PartialOrd, { assert!(min <= max); if self < min { min } else if self > max { max } else { self } } ``` `graph_view.rs`の以下2箇所が怪しい。 ```rust let move_to_end = if selected_index >= state.indices.len() - 1 { state.graph_lines.len() - 1 } else { (state.indices[selected_index + 1] - 1).clamp( move_to_selected + SCROLL_MARGIN, state.graph_lines.len() - 1, ) }; ``` ```rust let scroll_start = list_area.top() as usize + (((list_height * start) as f32 / state.graph_lines.len() as f32).ceil() as usize) .min(list_height - 1); let scroll_height = (((list_height * list_height) as f32 / state.graph_lines.len() as f32) .floor() as usize) .clamp(1, list_height); ``` 前者の`clamp`をコメントアウトしたら落ちなくなった。 ```rust let move_to_end = if selected_index >= state.indices.len() - 1 { state.graph_lines.len() - 1 } else { state.indices[selected_index + 1] - 1 // (state.indices[selected_index + 1] - 1).clamp( // move_to_selected + SCROLL_MARGIN, // state.graph_lines.len() - 1, // ) }; let move_to_start = move_to_selected.saturating_sub(SCROLL_MARGIN); ``` この処理がなぜ必要なのかを考慮する必要がある。 ## 改めて確認 | パラメータ | 意味 | | ----------------------- | ----------------------------------------------------- | | move_to_selected | ターミナルのN+1行目 (0から。空行も1カウント) | | state.graph_lines.len() | コミットグラフのターミナル最大行数 | | selected_index | 上からN+1番目のコミット (0から。空行はカウントしない) | | state.indices.len() | コミット行の総数 | | SCROLL_MARGIN | ??? (3で固定?) | - `move_to_selected + SCROLL_MARGIN` が `state.graph_lines.len()` を2上回っている - これが直接的な原因