tasks.rs

  1use std::process::ExitStatus;
  2
  3use anyhow::{Result, anyhow};
  4use gpui::{Context, Task};
  5use project::TaskSourceKind;
  6use remote::ConnectionState;
  7use task::{DebugTaskDefinition, ResolvedTask, SpawnInTerminal, TaskContext, TaskTemplate};
  8use ui::Window;
  9
 10use crate::Workspace;
 11
 12impl Workspace {
 13    pub fn schedule_task(
 14        self: &mut Workspace,
 15        task_source_kind: TaskSourceKind,
 16        task_to_resolve: &TaskTemplate,
 17        task_cx: &TaskContext,
 18        omit_history: bool,
 19        window: &mut Window,
 20        cx: &mut Context<Self>,
 21    ) {
 22        match self.project.read(cx).ssh_connection_state(cx) {
 23            None | Some(ConnectionState::Connected) => {}
 24            Some(
 25                ConnectionState::Connecting
 26                | ConnectionState::Disconnected
 27                | ConnectionState::HeartbeatMissed
 28                | ConnectionState::Reconnecting,
 29            ) => {
 30                log::warn!("Cannot schedule tasks when disconnected from a remote host");
 31                return;
 32            }
 33        }
 34
 35        if let Some(spawn_in_terminal) =
 36            task_to_resolve.resolve_task(&task_source_kind.to_id_base(), task_cx)
 37        {
 38            self.schedule_resolved_task(
 39                task_source_kind,
 40                spawn_in_terminal,
 41                omit_history,
 42                window,
 43                cx,
 44            );
 45        }
 46    }
 47
 48    pub fn schedule_resolved_task(
 49        self: &mut Workspace,
 50        task_source_kind: TaskSourceKind,
 51        mut resolved_task: ResolvedTask,
 52        omit_history: bool,
 53        window: &mut Window,
 54        cx: &mut Context<Workspace>,
 55    ) {
 56        if let Some(spawn_in_terminal) = resolved_task.resolved.take() {
 57            if !omit_history {
 58                resolved_task.resolved = Some(spawn_in_terminal.clone());
 59                self.project().update(cx, |project, cx| {
 60                    if let Some(task_inventory) =
 61                        project.task_store().read(cx).task_inventory().cloned()
 62                    {
 63                        task_inventory.update(cx, |inventory, _| {
 64                            inventory.task_scheduled(task_source_kind, resolved_task);
 65                        })
 66                    }
 67                });
 68            }
 69
 70            if let Some(terminal_provider) = self.terminal_provider.as_ref() {
 71                terminal_provider
 72                    .spawn(spawn_in_terminal, window, cx)
 73                    .detach_and_log_err(cx);
 74            }
 75        }
 76    }
 77
 78    pub fn schedule_debug_task(
 79        &mut self,
 80        task: ResolvedTask,
 81        window: &mut Window,
 82        cx: &mut Context<Workspace>,
 83    ) {
 84        let Some(debug_config) = task.resolved_debug_adapter_config() else {
 85            log::error!("Debug task has no debug adapter config");
 86            return;
 87        };
 88
 89        let project = self.project().clone();
 90        cx.spawn_in(window, async move |workspace, cx| {
 91            let config = if debug_config.locator.is_some() {
 92                let task = workspace.update_in(cx, |workspace, window, cx| {
 93                    workspace.spawn_in_terminal(task.resolved.unwrap(), window, cx)
 94                })?;
 95
 96                let exit_code = task.await?;
 97                if !exit_code.success() {
 98                    return anyhow::Ok(());
 99                }
100                let ret = project
101                    .update(cx, |project, cx| {
102                        project.dap_store().update(cx, |dap_store, cx| {
103                            dap_store.run_debug_locator(debug_config, cx)
104                        })
105                    })?
106                    .await?;
107                ret
108            } else {
109                debug_config.definition
110            };
111
112            workspace.update_in(cx, |workspace, window, cx| {
113                workspace.start_debug_session(config, window, cx);
114            })?;
115
116            anyhow::Ok(())
117        })
118        .detach_and_log_err(cx);
119    }
120
121    pub fn start_debug_session(
122        &mut self,
123        definition: DebugTaskDefinition,
124        window: &mut Window,
125        cx: &mut Context<Self>,
126    ) {
127        if let Some(provider) = self.debugger_provider.as_mut() {
128            provider.start_session(definition, window, cx)
129        }
130    }
131
132    pub fn spawn_in_terminal(
133        self: &mut Workspace,
134        spawn_in_terminal: SpawnInTerminal,
135        window: &mut Window,
136        cx: &mut Context<Workspace>,
137    ) -> Task<Result<ExitStatus>> {
138        if let Some(terminal_provider) = self.terminal_provider.as_ref() {
139            terminal_provider.spawn(spawn_in_terminal, window, cx)
140        } else {
141            Task::ready(Err(anyhow!("No terminal provider")))
142        }
143    }
144}