From a87db8433cd8d9b2670efbd52325ce1292a1b3b8 Mon Sep 17 00:00:00 2001 From: DualFroz Date: Thu, 23 Jul 2026 07:24:27 +0200 Subject: [PATCH] fix: guard label-rename against a stale repo index A background refresh (bulk-import/create-repo/profile-pull all replace state.repos wholesale) could complete while the 'Set label' modal was still open, so its captured index either panicked (out-of-bounds) or silently relabeled the wrong repo. Now degrades gracefully via .get(). --- src/hub/modals_confirm_project.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/hub/modals_confirm_project.rs b/src/hub/modals_confirm_project.rs index 27be6c0..c5d5af0 100644 --- a/src/hub/modals_confirm_project.rs +++ b/src/hub/modals_confirm_project.rs @@ -13,12 +13,19 @@ use crate::todos::{self, Todo, TodoStatus}; pub fn try_confirm(state: &mut HubState, modal: Modal) -> Option { match modal { Modal::Text { value, tag: TextTag::Label(ri), .. } => { - let display = if value.trim().is_empty() { - state.repos[ri].path.file_name().unwrap_or_default().to_string_lossy().to_string() - } else { value.clone() }; - state.repos[ri].name = display.clone(); - let _ = crate::labels::save_label(&state.repos[ri].path.clone(), &value, &state.workspace_root); - state.rebuild_display(); + // `ri` was captured when the modal opened; a background refresh + // (bulk import / create-repo / profile-pull all replace + // `state.repos` wholesale) may have completed since then, so this + // must degrade gracefully instead of indexing straight in. + if let Some(repo) = state.repos.get(ri) { + let display = if value.trim().is_empty() { + repo.path.file_name().unwrap_or_default().to_string_lossy().to_string() + } else { value.clone() }; + let path = repo.path.clone(); + state.repos[ri].name = display; + let _ = crate::labels::save_label(&path, &value, &state.workspace_root); + state.rebuild_display(); + } None }