Sync config with ssh remotes (#17349)
Release Notes: - N/A --------- Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
parent
4b094798e0
commit
7fb94c4c4d
13 changed files with 609 additions and 193 deletions
|
@ -36,6 +36,7 @@ serde_json.workspace = true
|
|||
shellexpand.workspace = true
|
||||
smol.workspace = true
|
||||
worktree.workspace = true
|
||||
language.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
client = { workspace = true, features = ["test-support"] }
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use fs::Fs;
|
||||
use gpui::{AppContext, AsyncAppContext, Context, Model, ModelContext};
|
||||
use gpui::{AppContext, AsyncAppContext, Context, Model, ModelContext, Task};
|
||||
use language::LanguageRegistry;
|
||||
use project::{
|
||||
buffer_store::BufferStore, search::SearchQuery, worktree_store::WorktreeStore, ProjectPath,
|
||||
WorktreeId, WorktreeSettings,
|
||||
buffer_store::BufferStore, project_settings::SettingsObserver, search::SearchQuery,
|
||||
worktree_store::WorktreeStore, LspStore, ProjectPath, WorktreeId, WorktreeSettings,
|
||||
};
|
||||
use remote::SshSession;
|
||||
use rpc::{
|
||||
proto::{self, AnyProtoClient, SSH_PEER_ID, SSH_PROJECT_ID},
|
||||
TypedEnvelope,
|
||||
};
|
||||
use settings::{Settings as _, SettingsStore};
|
||||
use settings::Settings as _;
|
||||
use smol::stream::StreamExt;
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
|
@ -23,16 +24,25 @@ pub struct HeadlessProject {
|
|||
pub session: AnyProtoClient,
|
||||
pub worktree_store: Model<WorktreeStore>,
|
||||
pub buffer_store: Model<BufferStore>,
|
||||
pub lsp_store: Model<LspStore>,
|
||||
pub settings_observer: Model<SettingsObserver>,
|
||||
pub next_entry_id: Arc<AtomicUsize>,
|
||||
}
|
||||
|
||||
impl HeadlessProject {
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
cx.set_global(SettingsStore::new(cx));
|
||||
settings::init(cx);
|
||||
language::init(cx);
|
||||
WorktreeSettings::register(cx);
|
||||
}
|
||||
|
||||
pub fn new(session: Arc<SshSession>, fs: Arc<dyn Fs>, cx: &mut ModelContext<Self>) -> Self {
|
||||
// TODO: we should load the env correctly (as we do in login_shell_env_loaded when stdout is not a pty). Can we re-use the ProjectEnvironment for that?
|
||||
let languages = Arc::new(LanguageRegistry::new(
|
||||
Task::ready(()),
|
||||
cx.background_executor().clone(),
|
||||
));
|
||||
|
||||
let worktree_store = cx.new_model(|_| WorktreeStore::new(true, fs.clone()));
|
||||
let buffer_store = cx.new_model(|cx| {
|
||||
let mut buffer_store =
|
||||
|
@ -40,12 +50,34 @@ impl HeadlessProject {
|
|||
buffer_store.shared(SSH_PROJECT_ID, session.clone().into(), cx);
|
||||
buffer_store
|
||||
});
|
||||
let settings_observer = cx.new_model(|cx| {
|
||||
let mut observer = SettingsObserver::new_local(fs.clone(), worktree_store.clone(), cx);
|
||||
observer.shared(SSH_PROJECT_ID, session.clone().into(), cx);
|
||||
observer
|
||||
});
|
||||
let environment = project::ProjectEnvironment::new(&worktree_store, None, cx);
|
||||
let lsp_store = cx.new_model(|cx| {
|
||||
LspStore::new(
|
||||
buffer_store.clone(),
|
||||
worktree_store.clone(),
|
||||
Some(environment),
|
||||
languages,
|
||||
None,
|
||||
fs.clone(),
|
||||
Some(session.clone().into()),
|
||||
None,
|
||||
Some(0),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
let client: AnyProtoClient = session.clone().into();
|
||||
|
||||
session.subscribe_to_entity(SSH_PROJECT_ID, &worktree_store);
|
||||
session.subscribe_to_entity(SSH_PROJECT_ID, &buffer_store);
|
||||
session.subscribe_to_entity(SSH_PROJECT_ID, &cx.handle());
|
||||
session.subscribe_to_entity(SSH_PROJECT_ID, &lsp_store);
|
||||
session.subscribe_to_entity(SSH_PROJECT_ID, &settings_observer);
|
||||
|
||||
client.add_request_handler(cx.weak_model(), Self::handle_list_remote_directory);
|
||||
|
||||
|
@ -58,12 +90,15 @@ impl HeadlessProject {
|
|||
|
||||
BufferStore::init(&client);
|
||||
WorktreeStore::init(&client);
|
||||
SettingsObserver::init(&client);
|
||||
|
||||
HeadlessProject {
|
||||
session: client,
|
||||
settings_observer,
|
||||
fs,
|
||||
worktree_store,
|
||||
buffer_store,
|
||||
lsp_store,
|
||||
next_entry_id: Default::default(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ fn main() {
|
|||
}
|
||||
|
||||
gpui::App::headless().run(move |cx| {
|
||||
settings::init(cx);
|
||||
HeadlessProject::init(cx);
|
||||
|
||||
let (incoming_tx, incoming_rx) = mpsc::unbounded();
|
||||
|
|
|
@ -4,7 +4,10 @@ use clock::FakeSystemClock;
|
|||
use fs::{FakeFs, Fs};
|
||||
use gpui::{Context, Model, TestAppContext};
|
||||
use http_client::FakeHttpClient;
|
||||
use language::{Buffer, LanguageRegistry};
|
||||
use language::{
|
||||
language_settings::{all_language_settings, AllLanguageSettings},
|
||||
Buffer, LanguageRegistry,
|
||||
};
|
||||
use node_runtime::FakeNodeRuntime;
|
||||
use project::{
|
||||
search::{SearchQuery, SearchResult},
|
||||
|
@ -12,7 +15,7 @@ use project::{
|
|||
};
|
||||
use remote::SshSession;
|
||||
use serde_json::json;
|
||||
use settings::SettingsStore;
|
||||
use settings::{Settings, SettingsLocation, SettingsStore};
|
||||
use smol::stream::StreamExt;
|
||||
use std::{path::Path, sync::Arc};
|
||||
|
||||
|
@ -33,7 +36,6 @@ async fn test_basic_remote_editing(cx: &mut TestAppContext, server_cx: &mut Test
|
|||
assert_eq!(
|
||||
worktree.paths().map(Arc::as_ref).collect::<Vec<_>>(),
|
||||
vec![
|
||||
Path::new(".git"),
|
||||
Path::new("README.md"),
|
||||
Path::new("src"),
|
||||
Path::new("src/lib.rs"),
|
||||
|
@ -84,7 +86,6 @@ async fn test_basic_remote_editing(cx: &mut TestAppContext, server_cx: &mut Test
|
|||
assert_eq!(
|
||||
worktree.paths().map(Arc::as_ref).collect::<Vec<_>>(),
|
||||
vec![
|
||||
Path::new(".git"),
|
||||
Path::new("README.md"),
|
||||
Path::new("src"),
|
||||
Path::new("src/lib.rs"),
|
||||
|
@ -184,6 +185,85 @@ async fn test_remote_project_search(cx: &mut TestAppContext, server_cx: &mut Tes
|
|||
do_search(&project, cx.clone()).await;
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_remote_settings(cx: &mut TestAppContext, server_cx: &mut TestAppContext) {
|
||||
let (project, headless, fs) = init_test(cx, server_cx).await;
|
||||
|
||||
cx.update_global(|settings_store: &mut SettingsStore, cx| {
|
||||
settings_store.set_user_settings(
|
||||
r#"{"languages":{"Rust":{"language_servers":["custom-rust-analyzer"]}}}"#,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
cx.run_until_parked();
|
||||
|
||||
server_cx.read(|cx| {
|
||||
assert_eq!(
|
||||
AllLanguageSettings::get_global(cx)
|
||||
.language(Some("Rust"))
|
||||
.language_servers,
|
||||
["custom-rust-analyzer".into()]
|
||||
)
|
||||
});
|
||||
|
||||
fs.insert_tree("/code/project1/.zed", json!({
|
||||
"settings.json": r#"{"languages":{"Rust":{"language_servers":["override-rust-analyzer"]}}}"#
|
||||
})).await;
|
||||
|
||||
let worktree_id = project
|
||||
.update(cx, |project, cx| {
|
||||
project.find_or_create_worktree("/code/project1", true, cx)
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.0
|
||||
.read_with(cx, |worktree, _| worktree.id());
|
||||
|
||||
let buffer = project
|
||||
.update(cx, |project, cx| {
|
||||
project.open_buffer((worktree_id, Path::new("src/lib.rs")), cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
cx.run_until_parked();
|
||||
|
||||
server_cx.read(|cx| {
|
||||
let worktree_id = headless
|
||||
.read(cx)
|
||||
.worktree_store
|
||||
.read(cx)
|
||||
.worktrees()
|
||||
.next()
|
||||
.unwrap()
|
||||
.read(cx)
|
||||
.id();
|
||||
assert_eq!(
|
||||
AllLanguageSettings::get(
|
||||
Some(SettingsLocation {
|
||||
worktree_id: worktree_id.into(),
|
||||
path: Path::new("src/lib.rs")
|
||||
}),
|
||||
cx
|
||||
)
|
||||
.language(Some("Rust"))
|
||||
.language_servers,
|
||||
["override-rust-analyzer".into()]
|
||||
)
|
||||
});
|
||||
|
||||
cx.read(|cx| {
|
||||
let file = buffer.read(cx).file();
|
||||
assert_eq!(
|
||||
all_language_settings(file, cx)
|
||||
.language(Some("Rust"))
|
||||
.language_servers,
|
||||
["override-rust-analyzer".into()]
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
fn init_logger() {
|
||||
if std::env::var("RUST_LOG").is_ok() {
|
||||
env_logger::try_init().ok();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue