toolchains: Add support for relative paths (#27777)
Closes #ISSUE Release Notes: - N/A
This commit is contained in:
parent
627ae7af6f
commit
edf712d45b
12 changed files with 178 additions and 93 deletions
|
@ -89,6 +89,7 @@ impl DebugAdapter for PythonDebugAdapter {
|
||||||
.toolchain_store()
|
.toolchain_store()
|
||||||
.active_toolchain(
|
.active_toolchain(
|
||||||
delegate.worktree_id(),
|
delegate.worktree_id(),
|
||||||
|
Arc::from("".as_ref()),
|
||||||
language::LanguageName::new(Self::LANGUAGE_NAME),
|
language::LanguageName::new(Self::LANGUAGE_NAME),
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,7 +4,10 @@
|
||||||
//! which is a set of tools used to interact with the projects written in said language.
|
//! 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.
|
//! 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 async_trait::async_trait;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
|
@ -52,6 +55,7 @@ pub trait LanguageToolchainStore {
|
||||||
async fn active_toolchain(
|
async fn active_toolchain(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
worktree_id: WorktreeId,
|
worktree_id: WorktreeId,
|
||||||
|
relative_path: Arc<Path>,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
cx: &mut AsyncApp,
|
cx: &mut AsyncApp,
|
||||||
) -> Option<Toolchain>;
|
) -> Option<Toolchain>;
|
||||||
|
|
|
@ -293,7 +293,12 @@ impl LspAdapter for PythonLspAdapter {
|
||||||
cx: &mut AsyncApp,
|
cx: &mut AsyncApp,
|
||||||
) -> Result<Value> {
|
) -> Result<Value> {
|
||||||
let toolchain = toolchains
|
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;
|
.await;
|
||||||
cx.update(move |cx| {
|
cx.update(move |cx| {
|
||||||
let mut user_settings =
|
let mut user_settings =
|
||||||
|
@ -373,7 +378,7 @@ impl ContextProvider for PythonContextProvider {
|
||||||
cx.spawn(async move |cx| {
|
cx.spawn(async move |cx| {
|
||||||
let active_toolchain = if let Some(worktree_id) = worktree_id {
|
let active_toolchain = if let Some(worktree_id) = worktree_id {
|
||||||
toolchains
|
toolchains
|
||||||
.active_toolchain(worktree_id, "Python".into(), cx)
|
.active_toolchain(worktree_id, Arc::from("".as_ref()), "Python".into(), cx)
|
||||||
.await
|
.await
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|| "python3".to_owned(),
|
|| "python3".to_owned(),
|
||||||
|
@ -900,6 +905,7 @@ impl LspAdapter for PyLspAdapter {
|
||||||
let venv = toolchains
|
let venv = toolchains
|
||||||
.active_toolchain(
|
.active_toolchain(
|
||||||
delegate.worktree_id(),
|
delegate.worktree_id(),
|
||||||
|
Arc::from("".as_ref()),
|
||||||
LanguageName::new("Python"),
|
LanguageName::new("Python"),
|
||||||
&mut cx.clone(),
|
&mut cx.clone(),
|
||||||
)
|
)
|
||||||
|
@ -1046,7 +1052,12 @@ impl LspAdapter for PyLspAdapter {
|
||||||
cx: &mut AsyncApp,
|
cx: &mut AsyncApp,
|
||||||
) -> Result<Value> {
|
) -> Result<Value> {
|
||||||
let toolchain = toolchains
|
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;
|
.await;
|
||||||
cx.update(move |cx| {
|
cx.update(move |cx| {
|
||||||
let mut user_settings =
|
let mut user_settings =
|
||||||
|
|
|
@ -3065,7 +3065,7 @@ impl Project {
|
||||||
|
|
||||||
pub fn available_toolchains(
|
pub fn available_toolchains(
|
||||||
&self,
|
&self,
|
||||||
worktree_id: WorktreeId,
|
path: ProjectPath,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
cx: &App,
|
cx: &App,
|
||||||
) -> Task<Option<ToolchainList>> {
|
) -> Task<Option<ToolchainList>> {
|
||||||
|
@ -3074,7 +3074,7 @@ impl Project {
|
||||||
cx.update(|cx| {
|
cx.update(|cx| {
|
||||||
toolchain_store
|
toolchain_store
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.list_toolchains(worktree_id, language_name, cx)
|
.list_toolchains(path, language_name, cx)
|
||||||
})
|
})
|
||||||
.ok()?
|
.ok()?
|
||||||
.await
|
.await
|
||||||
|
@ -3098,20 +3098,18 @@ impl Project {
|
||||||
|
|
||||||
pub fn activate_toolchain(
|
pub fn activate_toolchain(
|
||||||
&self,
|
&self,
|
||||||
worktree_id: WorktreeId,
|
path: ProjectPath,
|
||||||
toolchain: Toolchain,
|
toolchain: Toolchain,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> Task<Option<()>> {
|
) -> Task<Option<()>> {
|
||||||
let Some(toolchain_store) = self.toolchain_store.clone() else {
|
let Some(toolchain_store) = self.toolchain_store.clone() else {
|
||||||
return Task::ready(None);
|
return Task::ready(None);
|
||||||
};
|
};
|
||||||
toolchain_store.update(cx, |this, cx| {
|
toolchain_store.update(cx, |this, cx| this.activate_toolchain(path, toolchain, cx))
|
||||||
this.activate_toolchain(worktree_id, toolchain, cx)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
pub fn active_toolchain(
|
pub fn active_toolchain(
|
||||||
&self,
|
&self,
|
||||||
worktree_id: WorktreeId,
|
path: ProjectPath,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
cx: &App,
|
cx: &App,
|
||||||
) -> Task<Option<Toolchain>> {
|
) -> Task<Option<Toolchain>> {
|
||||||
|
@ -3120,7 +3118,7 @@ impl Project {
|
||||||
};
|
};
|
||||||
toolchain_store
|
toolchain_store
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.active_toolchain(worktree_id, language_name, cx)
|
.active_toolchain(path, language_name, cx)
|
||||||
}
|
}
|
||||||
pub fn language_server_statuses<'a>(
|
pub fn language_server_statuses<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::Project;
|
use crate::{Project, ProjectPath};
|
||||||
use anyhow::{Context as _, Result};
|
use anyhow::{Context as _, Result};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use gpui::{AnyWindowHandle, App, AppContext as _, Context, Entity, Task, WeakEntity};
|
use gpui::{AnyWindowHandle, App, AppContext as _, Context, Entity, Task, WeakEntity};
|
||||||
|
@ -407,14 +407,17 @@ impl Project {
|
||||||
cx: &Context<Project>,
|
cx: &Context<Project>,
|
||||||
) -> Task<Option<PathBuf>> {
|
) -> Task<Option<PathBuf>> {
|
||||||
cx.spawn(async move |this, cx| {
|
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))
|
.update(cx, |this, cx| this.find_worktree(&abs_path, cx))
|
||||||
.ok()?
|
.ok()?
|
||||||
{
|
{
|
||||||
let toolchain = this
|
let toolchain = this
|
||||||
.update(cx, |this, cx| {
|
.update(cx, |this, cx| {
|
||||||
this.active_toolchain(
|
this.active_toolchain(
|
||||||
worktree.read(cx).id(),
|
ProjectPath {
|
||||||
|
worktree_id: worktree.read(cx).id(),
|
||||||
|
path: relative_path.into(),
|
||||||
|
},
|
||||||
LanguageName::new("Python"),
|
LanguageName::new("Python"),
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
|
|
@ -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};
|
use anyhow::{bail, Result};
|
||||||
|
|
||||||
|
@ -15,7 +19,7 @@ use rpc::{
|
||||||
use settings::WorktreeId;
|
use settings::WorktreeId;
|
||||||
use util::ResultExt as _;
|
use util::ResultExt as _;
|
||||||
|
|
||||||
use crate::{worktree_store::WorktreeStore, ProjectEnvironment};
|
use crate::{worktree_store::WorktreeStore, ProjectEnvironment, ProjectPath};
|
||||||
|
|
||||||
pub struct ToolchainStore(ToolchainStoreInner);
|
pub struct ToolchainStore(ToolchainStoreInner);
|
||||||
enum ToolchainStoreInner {
|
enum ToolchainStoreInner {
|
||||||
|
@ -58,56 +62,46 @@ impl ToolchainStore {
|
||||||
}
|
}
|
||||||
pub(crate) fn activate_toolchain(
|
pub(crate) fn activate_toolchain(
|
||||||
&self,
|
&self,
|
||||||
worktree_id: WorktreeId,
|
path: ProjectPath,
|
||||||
toolchain: Toolchain,
|
toolchain: Toolchain,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> Task<Option<()>> {
|
) -> Task<Option<()>> {
|
||||||
match &self.0 {
|
match &self.0 {
|
||||||
ToolchainStoreInner::Local(local, _) => local.update(cx, |this, cx| {
|
ToolchainStoreInner::Local(local, _) => {
|
||||||
this.activate_toolchain(worktree_id, toolchain, cx)
|
local.update(cx, |this, cx| this.activate_toolchain(path, toolchain, cx))
|
||||||
}),
|
}
|
||||||
ToolchainStoreInner::Remote(remote) => {
|
ToolchainStoreInner::Remote(remote) => {
|
||||||
remote
|
remote.read(cx).activate_toolchain(path, toolchain, cx)
|
||||||
.read(cx)
|
|
||||||
.activate_toolchain(worktree_id, toolchain, cx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub(crate) fn list_toolchains(
|
pub(crate) fn list_toolchains(
|
||||||
&self,
|
&self,
|
||||||
worktree_id: WorktreeId,
|
path: ProjectPath,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
cx: &App,
|
cx: &App,
|
||||||
) -> Task<Option<ToolchainList>> {
|
) -> Task<Option<ToolchainList>> {
|
||||||
match &self.0 {
|
match &self.0 {
|
||||||
ToolchainStoreInner::Local(local, _) => {
|
ToolchainStoreInner::Local(local, _) => {
|
||||||
local
|
local.read(cx).list_toolchains(path, language_name, cx)
|
||||||
.read(cx)
|
|
||||||
.list_toolchains(worktree_id, language_name, cx)
|
|
||||||
}
|
}
|
||||||
ToolchainStoreInner::Remote(remote) => {
|
ToolchainStoreInner::Remote(remote) => {
|
||||||
remote
|
remote.read(cx).list_toolchains(path, language_name, cx)
|
||||||
.read(cx)
|
|
||||||
.list_toolchains(worktree_id, language_name, cx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub(crate) fn active_toolchain(
|
pub(crate) fn active_toolchain(
|
||||||
&self,
|
&self,
|
||||||
worktree_id: WorktreeId,
|
path: ProjectPath,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
cx: &App,
|
cx: &App,
|
||||||
) -> Task<Option<Toolchain>> {
|
) -> Task<Option<Toolchain>> {
|
||||||
match &self.0 {
|
match &self.0 {
|
||||||
ToolchainStoreInner::Local(local, _) => {
|
ToolchainStoreInner::Local(local, _) => {
|
||||||
local
|
local.read(cx).active_toolchain(path, language_name, cx)
|
||||||
.read(cx)
|
|
||||||
.active_toolchain(worktree_id, language_name, cx)
|
|
||||||
}
|
}
|
||||||
ToolchainStoreInner::Remote(remote) => {
|
ToolchainStoreInner::Remote(remote) => {
|
||||||
remote
|
remote.read(cx).active_toolchain(path, language_name, cx)
|
||||||
.read(cx)
|
|
||||||
.active_toolchain(worktree_id, language_name, cx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,7 +124,12 @@ impl ToolchainStore {
|
||||||
language_name,
|
language_name,
|
||||||
};
|
};
|
||||||
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||||
Ok(this.activate_toolchain(worktree_id, toolchain, cx))
|
let path: Arc<Path> = 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;
|
.await;
|
||||||
Ok(proto::Ack {})
|
Ok(proto::Ack {})
|
||||||
|
@ -144,7 +143,14 @@ impl ToolchainStore {
|
||||||
.update(&mut cx, |this, cx| {
|
.update(&mut cx, |this, cx| {
|
||||||
let language_name = LanguageName::from_proto(envelope.payload.language_name);
|
let language_name = LanguageName::from_proto(envelope.payload.language_name);
|
||||||
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
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;
|
.await;
|
||||||
|
|
||||||
|
@ -169,7 +175,8 @@ impl ToolchainStore {
|
||||||
.update(&mut cx, |this, cx| {
|
.update(&mut cx, |this, cx| {
|
||||||
let language_name = LanguageName::from_proto(envelope.payload.language_name);
|
let language_name = LanguageName::from_proto(envelope.payload.language_name);
|
||||||
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
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;
|
.await;
|
||||||
let has_values = toolchains.is_some();
|
let has_values = toolchains.is_some();
|
||||||
|
@ -222,7 +229,7 @@ struct LocalToolchainStore {
|
||||||
languages: Arc<LanguageRegistry>,
|
languages: Arc<LanguageRegistry>,
|
||||||
worktree_store: Entity<WorktreeStore>,
|
worktree_store: Entity<WorktreeStore>,
|
||||||
project_environment: Entity<ProjectEnvironment>,
|
project_environment: Entity<ProjectEnvironment>,
|
||||||
active_toolchains: BTreeMap<(WorktreeId, LanguageName), Toolchain>,
|
active_toolchains: BTreeMap<(WorktreeId, LanguageName), BTreeMap<Arc<Path>, Toolchain>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
|
@ -230,12 +237,13 @@ impl language::LanguageToolchainStore for LocalStore {
|
||||||
async fn active_toolchain(
|
async fn active_toolchain(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
worktree_id: WorktreeId,
|
worktree_id: WorktreeId,
|
||||||
|
path: Arc<Path>,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
cx: &mut AsyncApp,
|
cx: &mut AsyncApp,
|
||||||
) -> Option<Toolchain> {
|
) -> Option<Toolchain> {
|
||||||
self.0
|
self.0
|
||||||
.update(cx, |this, cx| {
|
.update(cx, |this, cx| {
|
||||||
this.active_toolchain(worktree_id, language_name, cx)
|
this.active_toolchain(ProjectPath { worktree_id, path }, language_name, cx)
|
||||||
})
|
})
|
||||||
.ok()?
|
.ok()?
|
||||||
.await
|
.await
|
||||||
|
@ -247,12 +255,13 @@ impl language::LanguageToolchainStore for RemoteStore {
|
||||||
async fn active_toolchain(
|
async fn active_toolchain(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
worktree_id: WorktreeId,
|
worktree_id: WorktreeId,
|
||||||
|
path: Arc<Path>,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
cx: &mut AsyncApp,
|
cx: &mut AsyncApp,
|
||||||
) -> Option<Toolchain> {
|
) -> Option<Toolchain> {
|
||||||
self.0
|
self.0
|
||||||
.update(cx, |this, cx| {
|
.update(cx, |this, cx| {
|
||||||
this.active_toolchain(worktree_id, language_name, cx)
|
this.active_toolchain(ProjectPath { worktree_id, path }, language_name, cx)
|
||||||
})
|
})
|
||||||
.ok()?
|
.ok()?
|
||||||
.await
|
.await
|
||||||
|
@ -265,6 +274,7 @@ impl language::LanguageToolchainStore for EmptyToolchainStore {
|
||||||
async fn active_toolchain(
|
async fn active_toolchain(
|
||||||
self: Arc<Self>,
|
self: Arc<Self>,
|
||||||
_: WorktreeId,
|
_: WorktreeId,
|
||||||
|
_: Arc<Path>,
|
||||||
_: LanguageName,
|
_: LanguageName,
|
||||||
_: &mut AsyncApp,
|
_: &mut AsyncApp,
|
||||||
) -> Option<Toolchain> {
|
) -> Option<Toolchain> {
|
||||||
|
@ -284,16 +294,16 @@ impl EventEmitter<ToolchainStoreEvent> for LocalToolchainStore {}
|
||||||
impl LocalToolchainStore {
|
impl LocalToolchainStore {
|
||||||
pub(crate) fn activate_toolchain(
|
pub(crate) fn activate_toolchain(
|
||||||
&self,
|
&self,
|
||||||
worktree_id: WorktreeId,
|
path: ProjectPath,
|
||||||
toolchain: Toolchain,
|
toolchain: Toolchain,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> Task<Option<()>> {
|
) -> Task<Option<()>> {
|
||||||
cx.spawn(async move |this, cx| {
|
cx.spawn(async move |this, cx| {
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
this.active_toolchains.insert(
|
this.active_toolchains
|
||||||
(worktree_id, toolchain.language_name.clone()),
|
.entry((path.worktree_id, toolchain.language_name.clone()))
|
||||||
toolchain.clone(),
|
.or_default()
|
||||||
);
|
.insert(path.path, toolchain.clone());
|
||||||
cx.emit(ToolchainStoreEvent::ToolchainActivated);
|
cx.emit(ToolchainStoreEvent::ToolchainActivated);
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
@ -302,7 +312,7 @@ impl LocalToolchainStore {
|
||||||
}
|
}
|
||||||
pub(crate) fn list_toolchains(
|
pub(crate) fn list_toolchains(
|
||||||
&self,
|
&self,
|
||||||
worktree_id: WorktreeId,
|
path: ProjectPath,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
cx: &App,
|
cx: &App,
|
||||||
) -> Task<Option<ToolchainList>> {
|
) -> Task<Option<ToolchainList>> {
|
||||||
|
@ -310,17 +320,22 @@ impl LocalToolchainStore {
|
||||||
let Some(root) = self
|
let Some(root) = self
|
||||||
.worktree_store
|
.worktree_store
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.worktree_for_id(worktree_id, cx)
|
.worktree_for_id(path.worktree_id, cx)
|
||||||
.map(|worktree| worktree.read(cx).abs_path())
|
.map(|worktree| worktree.read(cx).abs_path())
|
||||||
else {
|
else {
|
||||||
return Task::ready(None);
|
return Task::ready(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let abs_path = root.join(path.path);
|
||||||
let environment = self.project_environment.clone();
|
let environment = self.project_environment.clone();
|
||||||
cx.spawn(async move |cx| {
|
cx.spawn(async move |cx| {
|
||||||
let project_env = environment
|
let project_env = environment
|
||||||
.update(cx, |environment, cx| {
|
.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()?
|
.ok()?
|
||||||
.await;
|
.await;
|
||||||
|
@ -331,20 +346,26 @@ impl LocalToolchainStore {
|
||||||
.await
|
.await
|
||||||
.ok()?;
|
.ok()?;
|
||||||
let toolchains = language.toolchain_lister()?;
|
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
|
.await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub(crate) fn active_toolchain(
|
pub(crate) fn active_toolchain(
|
||||||
&self,
|
&self,
|
||||||
worktree_id: WorktreeId,
|
path: ProjectPath,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
_: &App,
|
_: &App,
|
||||||
) -> Task<Option<Toolchain>> {
|
) -> Task<Option<Toolchain>> {
|
||||||
|
let ancestors = path.path.ancestors();
|
||||||
Task::ready(
|
Task::ready(
|
||||||
self.active_toolchains
|
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(),
|
.cloned(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -357,24 +378,25 @@ struct RemoteToolchainStore {
|
||||||
impl RemoteToolchainStore {
|
impl RemoteToolchainStore {
|
||||||
pub(crate) fn activate_toolchain(
|
pub(crate) fn activate_toolchain(
|
||||||
&self,
|
&self,
|
||||||
worktree_id: WorktreeId,
|
project_path: ProjectPath,
|
||||||
toolchain: Toolchain,
|
toolchain: Toolchain,
|
||||||
cx: &App,
|
cx: &App,
|
||||||
) -> Task<Option<()>> {
|
) -> Task<Option<()>> {
|
||||||
let project_id = self.project_id;
|
let project_id = self.project_id;
|
||||||
let client = self.client.clone();
|
let client = self.client.clone();
|
||||||
cx.spawn(async move |_| {
|
cx.background_spawn(async move {
|
||||||
let path = PathBuf::from(toolchain.path.to_string());
|
let path = PathBuf::from(toolchain.path.to_string());
|
||||||
let _ = client
|
let _ = client
|
||||||
.request(proto::ActivateToolchain {
|
.request(proto::ActivateToolchain {
|
||||||
project_id,
|
project_id,
|
||||||
worktree_id: worktree_id.to_proto(),
|
worktree_id: project_path.worktree_id.to_proto(),
|
||||||
language_name: toolchain.language_name.into(),
|
language_name: toolchain.language_name.into(),
|
||||||
toolchain: Some(proto::Toolchain {
|
toolchain: Some(proto::Toolchain {
|
||||||
name: toolchain.name.into(),
|
name: toolchain.name.into(),
|
||||||
path: path.to_proto(),
|
path: path.to_proto(),
|
||||||
raw_json: toolchain.as_json.to_string(),
|
raw_json: toolchain.as_json.to_string(),
|
||||||
}),
|
}),
|
||||||
|
path: Some(project_path.path.to_string_lossy().into_owned()),
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.log_err()?;
|
.log_err()?;
|
||||||
|
@ -384,18 +406,19 @@ impl RemoteToolchainStore {
|
||||||
|
|
||||||
pub(crate) fn list_toolchains(
|
pub(crate) fn list_toolchains(
|
||||||
&self,
|
&self,
|
||||||
worktree_id: WorktreeId,
|
path: ProjectPath,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
cx: &App,
|
cx: &App,
|
||||||
) -> Task<Option<ToolchainList>> {
|
) -> Task<Option<ToolchainList>> {
|
||||||
let project_id = self.project_id;
|
let project_id = self.project_id;
|
||||||
let client = self.client.clone();
|
let client = self.client.clone();
|
||||||
cx.spawn(async move |_| {
|
cx.background_spawn(async move {
|
||||||
let response = client
|
let response = client
|
||||||
.request(proto::ListToolchains {
|
.request(proto::ListToolchains {
|
||||||
project_id,
|
project_id,
|
||||||
worktree_id: worktree_id.to_proto(),
|
worktree_id: path.worktree_id.to_proto(),
|
||||||
language_name: language_name.clone().into(),
|
language_name: language_name.clone().into(),
|
||||||
|
path: Some(path.path.to_string_lossy().into_owned()),
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.log_err()?;
|
.log_err()?;
|
||||||
|
@ -435,18 +458,19 @@ impl RemoteToolchainStore {
|
||||||
}
|
}
|
||||||
pub(crate) fn active_toolchain(
|
pub(crate) fn active_toolchain(
|
||||||
&self,
|
&self,
|
||||||
worktree_id: WorktreeId,
|
path: ProjectPath,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
cx: &App,
|
cx: &App,
|
||||||
) -> Task<Option<Toolchain>> {
|
) -> Task<Option<Toolchain>> {
|
||||||
let project_id = self.project_id;
|
let project_id = self.project_id;
|
||||||
let client = self.client.clone();
|
let client = self.client.clone();
|
||||||
cx.spawn(async move |_| {
|
cx.background_spawn(async move {
|
||||||
let response = client
|
let response = client
|
||||||
.request(proto::ActiveToolchain {
|
.request(proto::ActiveToolchain {
|
||||||
project_id,
|
project_id,
|
||||||
worktree_id: worktree_id.to_proto(),
|
worktree_id: path.worktree_id.to_proto(),
|
||||||
language_name: language_name.clone().into(),
|
language_name: language_name.clone().into(),
|
||||||
|
path: Some(path.path.to_string_lossy().into_owned()),
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.log_err()?;
|
.log_err()?;
|
||||||
|
|
|
@ -3269,6 +3269,7 @@ message ListToolchains {
|
||||||
uint64 project_id = 1;
|
uint64 project_id = 1;
|
||||||
uint64 worktree_id = 2;
|
uint64 worktree_id = 2;
|
||||||
string language_name = 3;
|
string language_name = 3;
|
||||||
|
optional string path = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Toolchain {
|
message Toolchain {
|
||||||
|
@ -3293,12 +3294,14 @@ message ActivateToolchain {
|
||||||
uint64 worktree_id = 2;
|
uint64 worktree_id = 2;
|
||||||
Toolchain toolchain = 3;
|
Toolchain toolchain = 3;
|
||||||
string language_name = 4;
|
string language_name = 4;
|
||||||
|
optional string path = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ActiveToolchain {
|
message ActiveToolchain {
|
||||||
uint64 project_id = 1;
|
uint64 project_id = 1;
|
||||||
uint64 worktree_id = 2;
|
uint64 worktree_id = 2;
|
||||||
string language_name = 3;
|
string language_name = 3;
|
||||||
|
optional string path = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ActiveToolchainResponse {
|
message ActiveToolchainResponse {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod native_kernel;
|
mod native_kernel;
|
||||||
use std::{fmt::Debug, future::Future, path::PathBuf};
|
use std::{fmt::Debug, future::Future, path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use futures::{
|
use futures::{
|
||||||
channel::mpsc::{self, Receiver},
|
channel::mpsc::{self, Receiver},
|
||||||
|
@ -11,7 +11,7 @@ use language::LanguageName;
|
||||||
pub use native_kernel::*;
|
pub use native_kernel::*;
|
||||||
|
|
||||||
mod remote_kernels;
|
mod remote_kernels;
|
||||||
use project::{Project, WorktreeId};
|
use project::{Project, ProjectPath, WorktreeId};
|
||||||
pub use remote_kernels::*;
|
pub use remote_kernels::*;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
@ -81,9 +81,14 @@ pub fn python_env_kernel_specifications(
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> impl Future<Output = Result<Vec<KernelSpecification>>> {
|
) -> impl Future<Output = Result<Vec<KernelSpecification>>> {
|
||||||
let python_language = LanguageName::new("Python");
|
let python_language = LanguageName::new("Python");
|
||||||
let toolchains = project
|
let toolchains = project.read(cx).available_toolchains(
|
||||||
.read(cx)
|
ProjectPath {
|
||||||
.available_toolchains(worktree_id, python_language, cx);
|
worktree_id,
|
||||||
|
path: Arc::from("".as_ref()),
|
||||||
|
},
|
||||||
|
python_language,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
let background_executor = cx.background_executor().clone();
|
let background_executor = cx.background_executor().clone();
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use editor::Editor;
|
use editor::Editor;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, AsyncWindowContext, Context, Entity, IntoElement, ParentElement, Render, Subscription,
|
div, AsyncWindowContext, Context, Entity, IntoElement, ParentElement, Render, Subscription,
|
||||||
Task, WeakEntity, Window,
|
Task, WeakEntity, Window,
|
||||||
};
|
};
|
||||||
use language::{Buffer, BufferEvent, LanguageName, Toolchain};
|
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 ui::{Button, ButtonCommon, Clickable, FluentBuilder, LabelSize, SharedString, Tooltip};
|
||||||
use workspace::{item::ItemHandle, StatusItemView, Workspace};
|
use workspace::{item::ItemHandle, StatusItemView, Workspace};
|
||||||
|
|
||||||
|
@ -109,9 +111,14 @@ impl ActiveToolchain {
|
||||||
.flatten()?;
|
.flatten()?;
|
||||||
let selected_toolchain = workspace
|
let selected_toolchain = workspace
|
||||||
.update(cx, |this, cx| {
|
.update(cx, |this, cx| {
|
||||||
this.project()
|
this.project().read(cx).active_toolchain(
|
||||||
.read(cx)
|
ProjectPath {
|
||||||
.active_toolchain(worktree_id, language_name.clone(), cx)
|
worktree_id,
|
||||||
|
path: Arc::from("".as_ref()),
|
||||||
|
},
|
||||||
|
language_name.clone(),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.ok()?
|
.ok()?
|
||||||
.await;
|
.await;
|
||||||
|
@ -123,21 +130,33 @@ impl ActiveToolchain {
|
||||||
.ok()?;
|
.ok()?;
|
||||||
let toolchains = cx
|
let toolchains = cx
|
||||||
.update(|_, cx| {
|
.update(|_, cx| {
|
||||||
project
|
project.read(cx).available_toolchains(
|
||||||
.read(cx)
|
ProjectPath {
|
||||||
.available_toolchains(worktree_id, language_name, cx)
|
worktree_id,
|
||||||
|
path: Arc::from("".as_ref()),
|
||||||
|
},
|
||||||
|
language_name,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.ok()?
|
.ok()?
|
||||||
.await?;
|
.await?;
|
||||||
if let Some(toolchain) = toolchains.toolchains.first() {
|
if let Some(toolchain) = toolchains.toolchains.first() {
|
||||||
// Since we don't have a selected toolchain, pick one for user here.
|
// Since we don't have a selected toolchain, pick one for user here.
|
||||||
workspace::WORKSPACE_DB
|
workspace::WORKSPACE_DB
|
||||||
.set_toolchain(workspace_id, worktree_id, toolchain.clone())
|
.set_toolchain(workspace_id, worktree_id, "".to_owned(), toolchain.clone())
|
||||||
.await
|
.await
|
||||||
.ok()?;
|
.ok()?;
|
||||||
project
|
project
|
||||||
.update(cx, |this, cx| {
|
.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()?
|
.ok()?
|
||||||
.await;
|
.await;
|
||||||
|
|
|
@ -9,7 +9,7 @@ use gpui::{
|
||||||
};
|
};
|
||||||
use language::{LanguageName, Toolchain, ToolchainList};
|
use language::{LanguageName, Toolchain, ToolchainList};
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use project::{Project, WorktreeId};
|
use project::{Project, ProjectPath, WorktreeId};
|
||||||
use std::{path::Path, sync::Arc};
|
use std::{path::Path, sync::Arc};
|
||||||
use ui::{prelude::*, HighlightedLabel, ListItem, ListItemSpacing};
|
use ui::{prelude::*, HighlightedLabel, ListItem, ListItemSpacing};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
|
@ -169,7 +169,14 @@ impl ToolchainSelectorDelegate {
|
||||||
});
|
});
|
||||||
let available_toolchains = project
|
let available_toolchains = project
|
||||||
.update(cx, |this, cx| {
|
.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()?
|
.ok()?
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -241,13 +248,20 @@ impl PickerDelegate for ToolchainSelectorDelegate {
|
||||||
let worktree_id = self.worktree_id;
|
let worktree_id = self.worktree_id;
|
||||||
cx.spawn_in(window, async move |_, cx| {
|
cx.spawn_in(window, async move |_, cx| {
|
||||||
workspace::WORKSPACE_DB
|
workspace::WORKSPACE_DB
|
||||||
.set_toolchain(workspace_id, worktree_id, toolchain.clone())
|
.set_toolchain(workspace_id, worktree_id, "".to_owned(), toolchain.clone())
|
||||||
.await
|
.await
|
||||||
.log_err();
|
.log_err();
|
||||||
workspace
|
workspace
|
||||||
.update(cx, |this, cx| {
|
.update(cx, |this, cx| {
|
||||||
this.project().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()?
|
.ok()?
|
||||||
|
|
|
@ -526,7 +526,8 @@ define_connection! {
|
||||||
),
|
),
|
||||||
sql!(
|
sql!(
|
||||||
ALTER TABLE breakpoints DROP COLUMN kind
|
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(
|
pub(crate) async fn toolchains(
|
||||||
&self,
|
&self,
|
||||||
workspace_id: WorkspaceId,
|
workspace_id: WorkspaceId,
|
||||||
) -> Result<Vec<(Toolchain, WorktreeId)>> {
|
) -> Result<Vec<(Toolchain, WorktreeId, Arc<Path>)>> {
|
||||||
self.write(move |this| {
|
self.write(move |this| {
|
||||||
let mut select = this
|
let mut select = this
|
||||||
.select_bound(sql!(
|
.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")?;
|
.context("Preparing insertion")?;
|
||||||
|
|
||||||
let toolchain: Vec<(String, String, u64, String, String)> =
|
let toolchain: Vec<(String, String, u64, String, String, String)> =
|
||||||
select(workspace_id)?;
|
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(),
|
name: name.into(),
|
||||||
path: path.into(),
|
path: path.into(),
|
||||||
language_name: LanguageName::new(&language_name),
|
language_name: LanguageName::new(&language_name),
|
||||||
as_json: serde_json::Value::from_str(&raw_json).ok()?
|
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
|
.await
|
||||||
}
|
}
|
||||||
|
@ -1355,12 +1356,13 @@ impl WorkspaceDb {
|
||||||
&self,
|
&self,
|
||||||
workspace_id: WorkspaceId,
|
workspace_id: WorkspaceId,
|
||||||
worktree_id: WorktreeId,
|
worktree_id: WorktreeId,
|
||||||
|
relative_worktree_path: String,
|
||||||
toolchain: Toolchain,
|
toolchain: Toolchain,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.write(move |conn| {
|
self.write(move |conn| {
|
||||||
let mut insert = conn
|
let mut insert = conn
|
||||||
.exec_bound(sql!(
|
.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
|
ON CONFLICT DO
|
||||||
UPDATE SET
|
UPDATE SET
|
||||||
name = ?4,
|
name = ?4,
|
||||||
|
@ -1372,6 +1374,7 @@ impl WorkspaceDb {
|
||||||
insert((
|
insert((
|
||||||
workspace_id,
|
workspace_id,
|
||||||
worktree_id.to_usize(),
|
worktree_id.to_usize(),
|
||||||
|
relative_worktree_path,
|
||||||
toolchain.language_name.as_ref(),
|
toolchain.language_name.as_ref(),
|
||||||
toolchain.name.as_ref(),
|
toolchain.name.as_ref(),
|
||||||
toolchain.path.as_ref(),
|
toolchain.path.as_ref(),
|
||||||
|
|
|
@ -1273,10 +1273,10 @@ impl Workspace {
|
||||||
};
|
};
|
||||||
|
|
||||||
let toolchains = DB.toolchains(workspace_id).await?;
|
let toolchains = DB.toolchains(workspace_id).await?;
|
||||||
for (toolchain, worktree_id) in toolchains {
|
for (toolchain, worktree_id, path) in toolchains {
|
||||||
project_handle
|
project_handle
|
||||||
.update(cx, |this, cx| {
|
.update(cx, |this, cx| {
|
||||||
this.activate_toolchain(worktree_id, toolchain, cx)
|
this.activate_toolchain(ProjectPath { worktree_id, path }, toolchain, cx)
|
||||||
})?
|
})?
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
@ -6319,10 +6319,10 @@ pub fn open_ssh_project(
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let toolchains = DB.toolchains(workspace_id).await?;
|
let toolchains = DB.toolchains(workspace_id).await?;
|
||||||
for (toolchain, worktree_id) in toolchains {
|
for (toolchain, worktree_id, path) in toolchains {
|
||||||
project
|
project
|
||||||
.update(cx, |this, cx| {
|
.update(cx, |this, cx| {
|
||||||
this.activate_toolchain(worktree_id, toolchain, cx)
|
this.activate_toolchain(ProjectPath { worktree_id, path }, toolchain, cx)
|
||||||
})?
|
})?
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue