1use std::process::ExitStatus;
2
3use anyhow::Result;
4use gpui::{AppContext, Context, Entity, Task};
5use language::Buffer;
6use project::TaskSourceKind;
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).ssh_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 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 .detach();
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 window: &mut Window,
99 cx: &mut Context<Self>,
100 ) {
101 if let Some(provider) = self.debugger_provider.as_mut() {
102 provider.start_session(scenario, task_context, active_buffer, window, cx)
103 }
104 }
105
106 pub fn spawn_in_terminal(
107 self: &mut Workspace,
108 spawn_in_terminal: SpawnInTerminal,
109 window: &mut Window,
110 cx: &mut Context<Workspace>,
111 ) -> Task<Option<Result<ExitStatus>>> {
112 if let Some(terminal_provider) = self.terminal_provider.as_ref() {
113 terminal_provider.spawn(spawn_in_terminal, window, cx)
114 } else {
115 Task::ready(None)
116 }
117 }
118}