1use std::process::ExitStatus;
2
3use anyhow::Result;
4use gpui::{AppContext, Context, Entity, Task};
5use language::Buffer;
6use project::{TaskSourceKind, WorktreeId};
7use remote::ConnectionState;
8use task::{DebugScenario, ResolvedTask, SpawnInTerminal, TaskContext, TaskTemplate};
9use ui::Window;
10
11use crate::Workspace;
12
13impl Workspace {
14 pub fn schedule_task(
15 self: &mut Workspace,
16 task_source_kind: TaskSourceKind,
17 task_to_resolve: &TaskTemplate,
18 task_cx: &TaskContext,
19 omit_history: bool,
20 window: &mut Window,
21 cx: &mut Context<Self>,
22 ) {
23 match self.project.read(cx).remote_connection_state(cx) {
24 None | Some(ConnectionState::Connected) => {}
25 Some(
26 ConnectionState::Connecting
27 | ConnectionState::Disconnected
28 | ConnectionState::HeartbeatMissed
29 | ConnectionState::Reconnecting,
30 ) => {
31 log::warn!("Cannot schedule tasks when disconnected from a remote host");
32 return;
33 }
34 }
35
36 if let Some(spawn_in_terminal) =
37 task_to_resolve.resolve_task(&task_source_kind.to_id_base(), task_cx)
38 {
39 self.schedule_resolved_task(
40 task_source_kind,
41 spawn_in_terminal,
42 omit_history,
43 window,
44 cx,
45 );
46 }
47 }
48
49 pub fn schedule_resolved_task(
50 self: &mut Workspace,
51 task_source_kind: TaskSourceKind,
52 resolved_task: ResolvedTask,
53 omit_history: bool,
54 window: &mut Window,
55 cx: &mut Context<Workspace>,
56 ) {
57 let spawn_in_terminal = resolved_task.resolved.clone();
58 if !omit_history {
59 if let Some(debugger_provider) = self.debugger_provider.as_ref() {
60 debugger_provider.task_scheduled(cx);
61 }
62
63 self.project().update(cx, |project, cx| {
64 if let Some(task_inventory) =
65 project.task_store().read(cx).task_inventory().cloned()
66 {
67 task_inventory.update(cx, |inventory, _| {
68 inventory.task_scheduled(task_source_kind, resolved_task);
69 })
70 }
71 });
72 }
73
74 if let Some(terminal_provider) = self.terminal_provider.as_ref() {
75 let task_status = terminal_provider.spawn(spawn_in_terminal, window, cx);
76 let task = cx.background_spawn(async move {
77 match task_status.await {
78 Some(Ok(status)) => {
79 if status.success() {
80 log::debug!("Task spawn succeeded");
81 } else {
82 log::debug!("Task spawn failed, code: {:?}", status.code());
83 }
84 }
85 Some(Err(e)) => log::error!("Task spawn failed: {e:#}"),
86 None => log::debug!("Task spawn got cancelled"),
87 }
88 });
89 self.scheduled_tasks.push(task);
90 }
91 }
92
93 pub fn start_debug_session(
94 &mut self,
95 scenario: DebugScenario,
96 task_context: TaskContext,
97 active_buffer: Option<Entity<Buffer>>,
98 worktree_id: Option<WorktreeId>,
99 window: &mut Window,
100 cx: &mut Context<Self>,
101 ) {
102 if let Some(provider) = self.debugger_provider.as_mut() {
103 provider.start_session(
104 scenario,
105 task_context,
106 active_buffer,
107 worktree_id,
108 window,
109 cx,
110 )
111 }
112 }
113
114 pub fn spawn_in_terminal(
115 self: &mut Workspace,
116 spawn_in_terminal: SpawnInTerminal,
117 window: &mut Window,
118 cx: &mut Context<Workspace>,
119 ) -> Task<Option<Result<ExitStatus>>> {
120 if let Some(terminal_provider) = self.terminal_provider.as_ref() {
121 terminal_provider.spawn(spawn_in_terminal, window, cx)
122 } else {
123 Task::ready(None)
124 }
125 }
126}