diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-07 15:12:59 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-07 16:29:45 +0300 |
| commit | 745ce4254c646922d667ec13dd21963656405c12 (patch) | |
| tree | 96704b9884d95d810be16b1dad5cb48c07ccdcc8 /src/app | |
| parent | f61ed48eff622de4f970adff220603ea50292f07 (diff) | |
fix: handle windows worktree paths and removal
Diffstat (limited to 'src/app')
| -rw-r--r-- | src/app/api/worktrees.rs | 16 | ||||
| -rw-r--r-- | src/app/worktrees.rs | 84 |
2 files changed, 80 insertions, 20 deletions
diff --git a/src/app/api/worktrees.rs b/src/app/api/worktrees.rs index d6a269ca..573771e2 100644 --- a/src/app/api/worktrees.rs +++ b/src/app/api/worktrees.rs @@ -292,6 +292,22 @@ impl App { ); } + #[cfg(windows)] + { + if !params.force + && crate::worktree::checkout_has_dirty_files(&space.checkout_path).unwrap_or(false) + { + return encode_error( + id, + "dirty_worktree_requires_force", + crate::worktree::worktree_dirty_remove_message(&space.checkout_path), + ); + } + } + + #[cfg(windows)] + self.shutdown_workspace_terminal_runtimes_for_worktree_remove(ws_idx); + let command = crate::worktree::build_worktree_remove_command( &space.repo_root, &space.checkout_path, diff --git a/src/app/worktrees.rs b/src/app/worktrees.rs index f7d906ee..f6635c23 100644 --- a/src/app/worktrees.rs +++ b/src/app/worktrees.rs @@ -548,21 +548,44 @@ impl App { } pub(crate) fn start_worktree_remove(&mut self) { - let Some(remove) = &mut self.state.worktree_remove else { + let Some((workspace_id, repo_root, path, force)) = + self.state.worktree_remove.as_mut().and_then(|remove| { + if remove.removing { + return None; + } + #[cfg(windows)] + if !remove.force_confirmation + && crate::worktree::checkout_has_dirty_files(&remove.path).unwrap_or(false) + { + remove.force_confirmation = true; + remove.error = None; + return None; + } + remove.removing = true; + remove.error = None; + Some(( + remove.workspace_id.clone(), + remove.repo_root.clone(), + remove.path.clone(), + remove.force_confirmation, + )) + }) + else { return; }; - if remove.removing { - return; + + #[cfg(windows)] + if let Some(ws_idx) = self + .state + .workspaces + .iter() + .position(|ws| ws.id == workspace_id) + { + self.shutdown_workspace_terminal_runtimes_for_worktree_remove(ws_idx); } - remove.removing = true; - remove.error = None; - let force = remove.force_confirmation; - - let command = - crate::worktree::build_worktree_remove_command(&remove.repo_root, &remove.path, force); - tracing::info!(workspace_id = %remove.workspace_id, path = %remove.path.display(), force, "starting git worktree remove"); - let path = remove.path.clone(); - let workspace_id = remove.workspace_id.clone(); + + let command = crate::worktree::build_worktree_remove_command(&repo_root, &path, force); + tracing::info!(workspace_id = %workspace_id, path = %path.display(), force, "starting git worktree remove"); let event_tx = self.event_tx.clone(); std::thread::spawn(move || { let result = crate::worktree::run_worktree_command(&command); @@ -697,6 +720,23 @@ impl App { } } } + + #[cfg(windows)] + pub(crate) fn shutdown_workspace_terminal_runtimes_for_worktree_remove( + &mut self, + ws_idx: usize, + ) { + for terminal_id in self.state.terminal_ids_for_workspace(ws_idx) { + if let Some(runtime) = self.terminal_runtimes.remove(&terminal_id) { + tracing::debug!( + workspace_index = ws_idx, + terminal_id = %terminal_id, + "shutting down terminal runtime before Windows worktree removal" + ); + runtime.shutdown(); + } + } + } } #[cfg(test)] @@ -1212,15 +1252,19 @@ mod tests { app.open_remove_linked_worktree_confirmation(0); app.start_worktree_remove(); - let safe_event = wait_for_worktree_event(&mut app); - match safe_event { - AppEvent::WorktreeRemoveFinished(result) => { - assert_eq!(result.workspace_id, workspace_id); - assert_eq!(result.path, checkout); - assert!(result.result.is_err()); - app.handle_worktree_remove_finished(result); + + #[cfg(not(windows))] + { + let safe_event = wait_for_worktree_event(&mut app); + match safe_event { + AppEvent::WorktreeRemoveFinished(result) => { + assert_eq!(result.workspace_id, workspace_id); + assert_eq!(result.path, checkout); + assert!(result.result.is_err()); + app.handle_worktree_remove_finished(result); + } + other => panic!("unexpected event: {other:?}"), } - other => panic!("unexpected event: {other:?}"), } let remove = app.state.worktree_remove.as_ref().unwrap(); |
