From edf712d45ba233cf9571ec9254da9d17e096d494 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 31 Mar 2025 19:48:09 +0200 Subject: [PATCH] toolchains: Add support for relative paths (#27777) Closes #ISSUE Release Notes: - N/A --- crates/dap_adapters/src/python.rs | 1 + crates/language/src/toolchain.rs | 6 +- crates/languages/src/python.rs | 17 ++- crates/project/src/project.rs | 14 +- crates/project/src/terminals.rs | 9 +- crates/project/src/toolchain_store.rs | 122 +++++++++++------- crates/proto/proto/zed.proto | 3 + crates/repl/src/kernels/mod.rs | 15 ++- .../src/active_toolchain.rs | 37 ++++-- .../src/toolchain_selector.rs | 22 +++- crates/workspace/src/persistence.rs | 17 ++- crates/workspace/src/workspace.rs | 8 +- 12 files changed, 178 insertions(+), 93 deletions(-) diff --git a/crates/dap_adapters/src/python.rs b/crates/dap_adapters/src/python.rs index afc77bdf15..28cea73477 100644 --- a/crates/dap_adapters/src/python.rs +++ b/crates/dap_adapters/src/python.rs @@ -89,6 +89,7 @@ impl DebugAdapter for PythonDebugAdapter { .toolchain_store() .active_toolchain( delegate.worktree_id(), + Arc::from("".as_ref()), language::LanguageName::new(Self::LANGUAGE_NAME), cx, ) diff --git a/crates/language/src/toolchain.rs b/crates/language/src/toolchain.rs index b42a0f0432..2937879429 100644 --- a/crates/language/src/toolchain.rs +++ b/crates/language/src/toolchain.rs @@ -4,7 +4,10 @@ //! which is a set of tools used to interact with the projects written in said language. //! For example, a Python project can have an associated virtual environment; a Rust project can have a toolchain override. -use std::{path::PathBuf, sync::Arc}; +use std::{ + path::{Path, PathBuf}, + sync::Arc, +}; use async_trait::async_trait; use collections::HashMap; @@ -52,6 +55,7 @@ pub trait LanguageToolchainStore { async fn active_toolchain( self: Arc, worktree_id: WorktreeId, + relative_path: Arc, language_name: LanguageName, cx: &mut AsyncApp, ) -> Option; diff --git a/crates/languages/src/python.rs b/crates/languages/src/python.rs index 5da1c02c7f..cd4add33b1 100644 --- a/crates/languages/src/python.rs +++ b/crates/languages/src/python.rs @@ -293,7 +293,12 @@ impl LspAdapter for PythonLspAdapter { cx: &mut AsyncApp, ) -> Result { let toolchain = toolchains - .active_toolchain(adapter.worktree_id(), LanguageName::new("Python"), cx) + .active_toolchain( + adapter.worktree_id(), + Arc::from("".as_ref()), + LanguageName::new("Python"), + cx, + ) .await; cx.update(move |cx| { let mut user_settings = @@ -373,7 +378,7 @@ impl ContextProvider for PythonContextProvider { cx.spawn(async move |cx| { let active_toolchain = if let Some(worktree_id) = worktree_id { toolchains - .active_toolchain(worktree_id, "Python".into(), cx) + .active_toolchain(worktree_id, Arc::from("".as_ref()), "Python".into(), cx) .await .map_or_else( || "python3".to_owned(), @@ -900,6 +905,7 @@ impl LspAdapter for PyLspAdapter { let venv = toolchains .active_toolchain( delegate.worktree_id(), + Arc::from("".as_ref()), LanguageName::new("Python"), &mut cx.clone(), ) @@ -1046,7 +1052,12 @@ impl LspAdapter for PyLspAdapter { cx: &mut AsyncApp, ) -> Result { let toolchain = toolchains - .active_toolchain(adapter.worktree_id(), LanguageName::new("Python"), cx) + .active_toolchain( + adapter.worktree_id(), + Arc::from("".as_ref()), + LanguageName::new("Python"), + cx, + ) .await; cx.update(move |cx| { let mut user_settings = diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 5a71a87f13..1738ab845a 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -3065,7 +3065,7 @@ impl Project { pub fn available_toolchains( &self, - worktree_id: WorktreeId, + path: ProjectPath, language_name: LanguageName, cx: &App, ) -> Task> { @@ -3074,7 +3074,7 @@ impl Project { cx.update(|cx| { toolchain_store .read(cx) - .list_toolchains(worktree_id, language_name, cx) + .list_toolchains(path, language_name, cx) }) .ok()? .await @@ -3098,20 +3098,18 @@ impl Project { pub fn activate_toolchain( &self, - worktree_id: WorktreeId, + path: ProjectPath, toolchain: Toolchain, cx: &mut App, ) -> Task> { let Some(toolchain_store) = self.toolchain_store.clone() else { return Task::ready(None); }; - toolchain_store.update(cx, |this, cx| { - this.activate_toolchain(worktree_id, toolchain, cx) - }) + toolchain_store.update(cx, |this, cx| this.activate_toolchain(path, toolchain, cx)) } pub fn active_toolchain( &self, - worktree_id: WorktreeId, + path: ProjectPath, language_name: LanguageName, cx: &App, ) -> Task> { @@ -3120,7 +3118,7 @@ impl Project { }; toolchain_store .read(cx) - .active_toolchain(worktree_id, language_name, cx) + .active_toolchain(path, language_name, cx) } pub fn language_server_statuses<'a>( &'a self, diff --git a/crates/project/src/terminals.rs b/crates/project/src/terminals.rs index d3a9acc11e..f26cae3da6 100644 --- a/crates/project/src/terminals.rs +++ b/crates/project/src/terminals.rs @@ -1,4 +1,4 @@ -use crate::Project; +use crate::{Project, ProjectPath}; use anyhow::{Context as _, Result}; use collections::HashMap; use gpui::{AnyWindowHandle, App, AppContext as _, Context, Entity, Task, WeakEntity}; @@ -407,14 +407,17 @@ impl Project { cx: &Context, ) -> Task> { cx.spawn(async move |this, cx| { - if let Some((worktree, _)) = this + if let Some((worktree, relative_path)) = this .update(cx, |this, cx| this.find_worktree(&abs_path, cx)) .ok()? { let toolchain = this .update(cx, |this, cx| { this.active_toolchain( - worktree.read(cx).id(), + ProjectPath { + worktree_id: worktree.read(cx).id(), + path: relative_path.into(), + }, LanguageName::new("Python"), cx, ) diff --git a/crates/project/src/toolchain_store.rs b/crates/project/src/toolchain_store.rs index b33e4913a3..df9842f783 100644 --- a/crates/project/src/toolchain_store.rs +++ b/crates/project/src/toolchain_store.rs @@ -1,4 +1,8 @@ -use std::{path::PathBuf, str::FromStr, sync::Arc}; +use std::{ + path::{Path, PathBuf}, + str::FromStr, + sync::Arc, +}; use anyhow::{bail, Result}; @@ -15,7 +19,7 @@ use rpc::{ use settings::WorktreeId; use util::ResultExt as _; -use crate::{worktree_store::WorktreeStore, ProjectEnvironment}; +use crate::{worktree_store::WorktreeStore, ProjectEnvironment, ProjectPath}; pub struct ToolchainStore(ToolchainStoreInner); enum ToolchainStoreInner { @@ -58,56 +62,46 @@ impl ToolchainStore { } pub(crate) fn activate_toolchain( &self, - worktree_id: WorktreeId, + path: ProjectPath, toolchain: Toolchain, cx: &mut App, ) -> Task> { match &self.0 { - ToolchainStoreInner::Local(local, _) => local.update(cx, |this, cx| { - this.activate_toolchain(worktree_id, toolchain, cx) - }), + ToolchainStoreInner::Local(local, _) => { + local.update(cx, |this, cx| this.activate_toolchain(path, toolchain, cx)) + } ToolchainStoreInner::Remote(remote) => { - remote - .read(cx) - .activate_toolchain(worktree_id, toolchain, cx) + remote.read(cx).activate_toolchain(path, toolchain, cx) } } } pub(crate) fn list_toolchains( &self, - worktree_id: WorktreeId, + path: ProjectPath, language_name: LanguageName, cx: &App, ) -> Task> { match &self.0 { ToolchainStoreInner::Local(local, _) => { - local - .read(cx) - .list_toolchains(worktree_id, language_name, cx) + local.read(cx).list_toolchains(path, language_name, cx) } ToolchainStoreInner::Remote(remote) => { - remote - .read(cx) - .list_toolchains(worktree_id, language_name, cx) + remote.read(cx).list_toolchains(path, language_name, cx) } } } pub(crate) fn active_toolchain( &self, - worktree_id: WorktreeId, + path: ProjectPath, language_name: LanguageName, cx: &App, ) -> Task> { match &self.0 { ToolchainStoreInner::Local(local, _) => { - local - .read(cx) - .active_toolchain(worktree_id, language_name, cx) + local.read(cx).active_toolchain(path, language_name, cx) } ToolchainStoreInner::Remote(remote) => { - remote - .read(cx) - .active_toolchain(worktree_id, language_name, cx) + remote.read(cx).active_toolchain(path, language_name, cx) } } } @@ -130,7 +124,12 @@ impl ToolchainStore { language_name, }; let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id); - Ok(this.activate_toolchain(worktree_id, toolchain, cx)) + let path: Arc = if let Some(path) = envelope.payload.path { + Arc::from(path.as_ref()) + } else { + Arc::from("".as_ref()) + }; + Ok(this.activate_toolchain(ProjectPath { worktree_id, path }, toolchain, cx)) })?? .await; Ok(proto::Ack {}) @@ -144,7 +143,14 @@ impl ToolchainStore { .update(&mut cx, |this, cx| { let language_name = LanguageName::from_proto(envelope.payload.language_name); let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id); - this.active_toolchain(worktree_id, language_name, cx) + this.active_toolchain( + ProjectPath { + worktree_id, + path: Arc::from(envelope.payload.path.as_deref().unwrap_or("").as_ref()), + }, + language_name, + cx, + ) })? .await; @@ -169,7 +175,8 @@ impl ToolchainStore { .update(&mut cx, |this, cx| { let language_name = LanguageName::from_proto(envelope.payload.language_name); let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id); - this.list_toolchains(worktree_id, language_name, cx) + let path = Arc::from(envelope.payload.path.as_deref().unwrap_or("").as_ref()); + this.list_toolchains(ProjectPath { worktree_id, path }, language_name, cx) })? .await; let has_values = toolchains.is_some(); @@ -222,7 +229,7 @@ struct LocalToolchainStore { languages: Arc, worktree_store: Entity, project_environment: Entity, - active_toolchains: BTreeMap<(WorktreeId, LanguageName), Toolchain>, + active_toolchains: BTreeMap<(WorktreeId, LanguageName), BTreeMap, Toolchain>>, } #[async_trait(?Send)] @@ -230,12 +237,13 @@ impl language::LanguageToolchainStore for LocalStore { async fn active_toolchain( self: Arc, worktree_id: WorktreeId, + path: Arc, language_name: LanguageName, cx: &mut AsyncApp, ) -> Option { self.0 .update(cx, |this, cx| { - this.active_toolchain(worktree_id, language_name, cx) + this.active_toolchain(ProjectPath { worktree_id, path }, language_name, cx) }) .ok()? .await @@ -247,12 +255,13 @@ impl language::LanguageToolchainStore for RemoteStore { async fn active_toolchain( self: Arc, worktree_id: WorktreeId, + path: Arc, language_name: LanguageName, cx: &mut AsyncApp, ) -> Option { self.0 .update(cx, |this, cx| { - this.active_toolchain(worktree_id, language_name, cx) + this.active_toolchain(ProjectPath { worktree_id, path }, language_name, cx) }) .ok()? .await @@ -265,6 +274,7 @@ impl language::LanguageToolchainStore for EmptyToolchainStore { async fn active_toolchain( self: Arc, _: WorktreeId, + _: Arc, _: LanguageName, _: &mut AsyncApp, ) -> Option { @@ -284,16 +294,16 @@ impl EventEmitter for LocalToolchainStore {} impl LocalToolchainStore { pub(crate) fn activate_toolchain( &self, - worktree_id: WorktreeId, + path: ProjectPath, toolchain: Toolchain, cx: &mut Context, ) -> Task> { cx.spawn(async move |this, cx| { this.update(cx, |this, cx| { - this.active_toolchains.insert( - (worktree_id, toolchain.language_name.clone()), - toolchain.clone(), - ); + this.active_toolchains + .entry((path.worktree_id, toolchain.language_name.clone())) + .or_default() + .insert(path.path, toolchain.clone()); cx.emit(ToolchainStoreEvent::ToolchainActivated); }) .ok(); @@ -302,7 +312,7 @@ impl LocalToolchainStore { } pub(crate) fn list_toolchains( &self, - worktree_id: WorktreeId, + path: ProjectPath, language_name: LanguageName, cx: &App, ) -> Task> { @@ -310,17 +320,22 @@ impl LocalToolchainStore { let Some(root) = self .worktree_store .read(cx) - .worktree_for_id(worktree_id, cx) + .worktree_for_id(path.worktree_id, cx) .map(|worktree| worktree.read(cx).abs_path()) else { return Task::ready(None); }; + let abs_path = root.join(path.path); let environment = self.project_environment.clone(); cx.spawn(async move |cx| { let project_env = environment .update(cx, |environment, cx| { - environment.get_environment(Some(worktree_id), Some(root.clone()), cx) + environment.get_environment( + Some(path.worktree_id), + Some(Arc::from(abs_path.as_path())), + cx, + ) }) .ok()? .await; @@ -331,20 +346,26 @@ impl LocalToolchainStore { .await .ok()?; let toolchains = language.toolchain_lister()?; - Some(toolchains.list(root.to_path_buf(), project_env).await) + Some(toolchains.list(abs_path.to_path_buf(), project_env).await) }) .await }) } pub(crate) fn active_toolchain( &self, - worktree_id: WorktreeId, + path: ProjectPath, language_name: LanguageName, _: &App, ) -> Task> { + let ancestors = path.path.ancestors(); Task::ready( self.active_toolchains - .get(&(worktree_id, language_name)) + .get(&(path.worktree_id, language_name)) + .and_then(|paths| { + ancestors + .into_iter() + .find_map(|root_path| paths.get(root_path)) + }) .cloned(), ) } @@ -357,24 +378,25 @@ struct RemoteToolchainStore { impl RemoteToolchainStore { pub(crate) fn activate_toolchain( &self, - worktree_id: WorktreeId, + project_path: ProjectPath, toolchain: Toolchain, cx: &App, ) -> Task> { let project_id = self.project_id; let client = self.client.clone(); - cx.spawn(async move |_| { + cx.background_spawn(async move { let path = PathBuf::from(toolchain.path.to_string()); let _ = client .request(proto::ActivateToolchain { project_id, - worktree_id: worktree_id.to_proto(), + worktree_id: project_path.worktree_id.to_proto(), language_name: toolchain.language_name.into(), toolchain: Some(proto::Toolchain { name: toolchain.name.into(), path: path.to_proto(), raw_json: toolchain.as_json.to_string(), }), + path: Some(project_path.path.to_string_lossy().into_owned()), }) .await .log_err()?; @@ -384,18 +406,19 @@ impl RemoteToolchainStore { pub(crate) fn list_toolchains( &self, - worktree_id: WorktreeId, + path: ProjectPath, language_name: LanguageName, cx: &App, ) -> Task> { let project_id = self.project_id; let client = self.client.clone(); - cx.spawn(async move |_| { + cx.background_spawn(async move { let response = client .request(proto::ListToolchains { project_id, - worktree_id: worktree_id.to_proto(), + worktree_id: path.worktree_id.to_proto(), language_name: language_name.clone().into(), + path: Some(path.path.to_string_lossy().into_owned()), }) .await .log_err()?; @@ -435,18 +458,19 @@ impl RemoteToolchainStore { } pub(crate) fn active_toolchain( &self, - worktree_id: WorktreeId, + path: ProjectPath, language_name: LanguageName, cx: &App, ) -> Task> { let project_id = self.project_id; let client = self.client.clone(); - cx.spawn(async move |_| { + cx.background_spawn(async move { let response = client .request(proto::ActiveToolchain { project_id, - worktree_id: worktree_id.to_proto(), + worktree_id: path.worktree_id.to_proto(), language_name: language_name.clone().into(), + path: Some(path.path.to_string_lossy().into_owned()), }) .await .log_err()?; diff --git a/crates/proto/proto/zed.proto b/crates/proto/proto/zed.proto index e14da68aa7..668344f5df 100644 --- a/crates/proto/proto/zed.proto +++ b/crates/proto/proto/zed.proto @@ -3269,6 +3269,7 @@ message ListToolchains { uint64 project_id = 1; uint64 worktree_id = 2; string language_name = 3; + optional string path = 4; } message Toolchain { @@ -3293,12 +3294,14 @@ message ActivateToolchain { uint64 worktree_id = 2; Toolchain toolchain = 3; string language_name = 4; + optional string path = 5; } message ActiveToolchain { uint64 project_id = 1; uint64 worktree_id = 2; string language_name = 3; + optional string path = 4; } message ActiveToolchainResponse { diff --git a/crates/repl/src/kernels/mod.rs b/crates/repl/src/kernels/mod.rs index 08eb4e758d..30214f77a3 100644 --- a/crates/repl/src/kernels/mod.rs +++ b/crates/repl/src/kernels/mod.rs @@ -1,5 +1,5 @@ mod native_kernel; -use std::{fmt::Debug, future::Future, path::PathBuf}; +use std::{fmt::Debug, future::Future, path::PathBuf, sync::Arc}; use futures::{ channel::mpsc::{self, Receiver}, @@ -11,7 +11,7 @@ use language::LanguageName; pub use native_kernel::*; mod remote_kernels; -use project::{Project, WorktreeId}; +use project::{Project, ProjectPath, WorktreeId}; pub use remote_kernels::*; use anyhow::Result; @@ -81,9 +81,14 @@ pub fn python_env_kernel_specifications( cx: &mut App, ) -> impl Future>> { let python_language = LanguageName::new("Python"); - let toolchains = project - .read(cx) - .available_toolchains(worktree_id, python_language, cx); + let toolchains = project.read(cx).available_toolchains( + ProjectPath { + worktree_id, + path: Arc::from("".as_ref()), + }, + python_language, + cx, + ); let background_executor = cx.background_executor().clone(); async move { diff --git a/crates/toolchain_selector/src/active_toolchain.rs b/crates/toolchain_selector/src/active_toolchain.rs index 41a8b10f92..4bddeb0bb8 100644 --- a/crates/toolchain_selector/src/active_toolchain.rs +++ b/crates/toolchain_selector/src/active_toolchain.rs @@ -1,10 +1,12 @@ +use std::sync::Arc; + use editor::Editor; use gpui::{ div, AsyncWindowContext, Context, Entity, IntoElement, ParentElement, Render, Subscription, Task, WeakEntity, Window, }; use language::{Buffer, BufferEvent, LanguageName, Toolchain}; -use project::{Project, WorktreeId}; +use project::{Project, ProjectPath, WorktreeId}; use ui::{Button, ButtonCommon, Clickable, FluentBuilder, LabelSize, SharedString, Tooltip}; use workspace::{item::ItemHandle, StatusItemView, Workspace}; @@ -109,9 +111,14 @@ impl ActiveToolchain { .flatten()?; let selected_toolchain = workspace .update(cx, |this, cx| { - this.project() - .read(cx) - .active_toolchain(worktree_id, language_name.clone(), cx) + this.project().read(cx).active_toolchain( + ProjectPath { + worktree_id, + path: Arc::from("".as_ref()), + }, + language_name.clone(), + cx, + ) }) .ok()? .await; @@ -123,21 +130,33 @@ impl ActiveToolchain { .ok()?; let toolchains = cx .update(|_, cx| { - project - .read(cx) - .available_toolchains(worktree_id, language_name, cx) + project.read(cx).available_toolchains( + ProjectPath { + worktree_id, + path: Arc::from("".as_ref()), + }, + language_name, + cx, + ) }) .ok()? .await?; if let Some(toolchain) = toolchains.toolchains.first() { // Since we don't have a selected toolchain, pick one for user here. workspace::WORKSPACE_DB - .set_toolchain(workspace_id, worktree_id, toolchain.clone()) + .set_toolchain(workspace_id, worktree_id, "".to_owned(), toolchain.clone()) .await .ok()?; project .update(cx, |this, cx| { - this.activate_toolchain(worktree_id, toolchain.clone(), cx) + this.activate_toolchain( + ProjectPath { + worktree_id, + path: Arc::from("".as_ref()), + }, + toolchain.clone(), + cx, + ) }) .ok()? .await; diff --git a/crates/toolchain_selector/src/toolchain_selector.rs b/crates/toolchain_selector/src/toolchain_selector.rs index c6a5efec48..37afd2942b 100644 --- a/crates/toolchain_selector/src/toolchain_selector.rs +++ b/crates/toolchain_selector/src/toolchain_selector.rs @@ -9,7 +9,7 @@ use gpui::{ }; use language::{LanguageName, Toolchain, ToolchainList}; use picker::{Picker, PickerDelegate}; -use project::{Project, WorktreeId}; +use project::{Project, ProjectPath, WorktreeId}; use std::{path::Path, sync::Arc}; use ui::{prelude::*, HighlightedLabel, ListItem, ListItemSpacing}; use util::ResultExt; @@ -169,7 +169,14 @@ impl ToolchainSelectorDelegate { }); let available_toolchains = project .update(cx, |this, cx| { - this.available_toolchains(worktree_id, language_name, cx) + this.available_toolchains( + ProjectPath { + worktree_id, + path: Arc::from("".as_ref()), + }, + language_name, + cx, + ) }) .ok()? .await?; @@ -241,13 +248,20 @@ impl PickerDelegate for ToolchainSelectorDelegate { let worktree_id = self.worktree_id; cx.spawn_in(window, async move |_, cx| { workspace::WORKSPACE_DB - .set_toolchain(workspace_id, worktree_id, toolchain.clone()) + .set_toolchain(workspace_id, worktree_id, "".to_owned(), toolchain.clone()) .await .log_err(); workspace .update(cx, |this, cx| { this.project().update(cx, |this, cx| { - this.activate_toolchain(worktree_id, toolchain, cx) + this.activate_toolchain( + ProjectPath { + worktree_id, + path: Arc::from("".as_ref()), + }, + toolchain, + cx, + ) }) }) .ok()? diff --git a/crates/workspace/src/persistence.rs b/crates/workspace/src/persistence.rs index 1263f88015..fb9ba829d7 100644 --- a/crates/workspace/src/persistence.rs +++ b/crates/workspace/src/persistence.rs @@ -526,7 +526,8 @@ define_connection! { ), sql!( ALTER TABLE breakpoints DROP COLUMN kind - ) + ), + sql!(ALTER TABLE toolchains ADD COLUMN relative_worktree_path TEXT DEFAULT "" NOT NULL) ]; } @@ -1331,23 +1332,23 @@ impl WorkspaceDb { pub(crate) async fn toolchains( &self, workspace_id: WorkspaceId, - ) -> Result> { + ) -> Result)>> { self.write(move |this| { let mut select = this .select_bound(sql!( - SELECT name, path, worktree_id, language_name, raw_json FROM toolchains WHERE workspace_id = ? + SELECT name, path, worktree_id, relative_worktree_path, language_name, raw_json FROM toolchains WHERE workspace_id = ? )) .context("Preparing insertion")?; - let toolchain: Vec<(String, String, u64, String, String)> = + let toolchain: Vec<(String, String, u64, String, String, String)> = select(workspace_id)?; - Ok(toolchain.into_iter().filter_map(|(name, path, worktree_id, language_name, raw_json)| Some((Toolchain { + Ok(toolchain.into_iter().filter_map(|(name, path, worktree_id, relative_worktree_path, language_name, raw_json)| Some((Toolchain { name: name.into(), path: path.into(), language_name: LanguageName::new(&language_name), as_json: serde_json::Value::from_str(&raw_json).ok()? - }, WorktreeId::from_proto(worktree_id)))).collect()) + }, WorktreeId::from_proto(worktree_id), Arc::from(relative_worktree_path.as_ref())))).collect()) }) .await } @@ -1355,12 +1356,13 @@ impl WorkspaceDb { &self, workspace_id: WorkspaceId, worktree_id: WorktreeId, + relative_worktree_path: String, toolchain: Toolchain, ) -> Result<()> { self.write(move |conn| { let mut insert = conn .exec_bound(sql!( - INSERT INTO toolchains(workspace_id, worktree_id, language_name, name, path) VALUES (?, ?, ?, ?, ?) + INSERT INTO toolchains(workspace_id, worktree_id, relative_worktree_path, language_name, name, path) VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT DO UPDATE SET name = ?4, @@ -1372,6 +1374,7 @@ impl WorkspaceDb { insert(( workspace_id, worktree_id.to_usize(), + relative_worktree_path, toolchain.language_name.as_ref(), toolchain.name.as_ref(), toolchain.path.as_ref(), diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index c1e5dae2da..e0ece8514f 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1273,10 +1273,10 @@ impl Workspace { }; let toolchains = DB.toolchains(workspace_id).await?; - for (toolchain, worktree_id) in toolchains { + for (toolchain, worktree_id, path) in toolchains { project_handle .update(cx, |this, cx| { - this.activate_toolchain(worktree_id, toolchain, cx) + this.activate_toolchain(ProjectPath { worktree_id, path }, toolchain, cx) })? .await; } @@ -6319,10 +6319,10 @@ pub fn open_ssh_project( })?; let toolchains = DB.toolchains(workspace_id).await?; - for (toolchain, worktree_id) in toolchains { + for (toolchain, worktree_id, path) in toolchains { project .update(cx, |this, cx| { - this.activate_toolchain(worktree_id, toolchain, cx) + this.activate_toolchain(ProjectPath { worktree_id, path }, toolchain, cx) })? .await; }