Skip to content

Commit

Permalink
Add settings to remote servers, use XDG paths on remote, and enable n…
Browse files Browse the repository at this point in the history
…ode LSPs (#19176)

Supersedes #19166

TODO:
- [x] Update basic zed paths
- [x] update create_state_directory
- [x] Use this with `NodeRuntime`
- [x] Add server settings
- [x] Add an 'open server settings command'
- [x] Make sure it all works


Release Notes:

- Updated the actions `zed::OpenLocalSettings` and `zed::OpenLocalTasks`
to `zed::OpenProjectSettings` and `zed::OpenProjectTasks`.

---------

Co-authored-by: Conrad <[email protected]>
Co-authored-by: Richard <[email protected]>
  • Loading branch information
3 people authored Oct 16, 2024
1 parent 1dda039 commit f944ebc
Show file tree
Hide file tree
Showing 44 changed files with 804 additions and 218 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions assets/settings/initial_server_settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Server-specific settings
//
// For a full list of overridable settings, and general information on settings,
// see the documentation: https://zed.dev/docs/configuring-zed#settings-files
{
"lsp": {}
}
2 changes: 1 addition & 1 deletion crates/assistant/src/inline_assistant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2278,7 +2278,7 @@ impl InlineAssist {
struct InlineAssistantError;

let id =
NotificationId::identified::<InlineAssistantError>(
NotificationId::composite::<InlineAssistantError>(
assist_id.0,
);

Expand Down
5 changes: 4 additions & 1 deletion crates/assistant/src/slash_command_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ impl Settings for SlashCommandSettings {

fn load(sources: SettingsSources<Self::FileContent>, _cx: &mut AppContext) -> Result<Self> {
SettingsSources::<Self::FileContent>::json_merge_with(
[sources.default].into_iter().chain(sources.user),
[sources.default]
.into_iter()
.chain(sources.user)
.chain(sources.server),
)
}
}
2 changes: 1 addition & 1 deletion crates/assistant/src/terminal_inline_assistant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ impl TerminalInlineAssist {
struct InlineAssistantError;

let id =
NotificationId::identified::<InlineAssistantError>(
NotificationId::composite::<InlineAssistantError>(
assist_id.0,
);

Expand Down
2 changes: 1 addition & 1 deletion crates/auto_update/src/auto_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ impl Settings for AutoUpdateSetting {
type FileContent = Option<AutoUpdateSettingContent>;

fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
let auto_update = [sources.release_channel, sources.user]
let auto_update = [sources.server, sources.release_channel, sources.user]
.into_iter()
.find_map(|value| value.copied().flatten())
.unwrap_or(sources.default.ok_or_else(Self::missing_default)?);
Expand Down
19 changes: 13 additions & 6 deletions crates/client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ impl Settings for ProxySettings {
Ok(Self {
proxy: sources
.user
.or(sources.server)
.and_then(|value| value.proxy.clone())
.or(sources.default.proxy.clone()),
})
Expand Down Expand Up @@ -472,15 +473,21 @@ impl settings::Settings for TelemetrySettings {

fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
Ok(Self {
diagnostics: sources.user.as_ref().and_then(|v| v.diagnostics).unwrap_or(
sources
.default
.diagnostics
.ok_or_else(Self::missing_default)?,
),
diagnostics: sources
.user
.as_ref()
.or(sources.server.as_ref())
.and_then(|v| v.diagnostics)
.unwrap_or(
sources
.default
.diagnostics
.ok_or_else(Self::missing_default)?,
),
metrics: sources
.user
.as_ref()
.or(sources.server.as_ref())
.and_then(|v| v.metrics)
.unwrap_or(sources.default.metrics.ok_or_else(Self::missing_default)?),
})
Expand Down
24 changes: 20 additions & 4 deletions crates/collab/src/tests/remote_editing_collaboration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ use crate::tests::TestServer;
use call::ActiveCall;
use fs::{FakeFs, Fs as _};
use gpui::{Context as _, TestAppContext};
use language::language_settings::all_language_settings;
use http_client::BlockedHttpClient;
use language::{language_settings::all_language_settings, LanguageRegistry};
use node_runtime::NodeRuntime;
use project::ProjectPath;
use remote::SshRemoteClient;
use remote_server::HeadlessProject;
use remote_server::{HeadlessAppState, HeadlessProject};
use serde_json::json;
use std::{path::Path, sync::Arc};

Expand Down Expand Up @@ -48,8 +50,22 @@ async fn test_sharing_an_ssh_remote_project(

// User A connects to the remote project via SSH.
server_cx.update(HeadlessProject::init);
let _headless_project =
server_cx.new_model(|cx| HeadlessProject::new(server_ssh, remote_fs.clone(), cx));
let remote_http_client = Arc::new(BlockedHttpClient);
let node = NodeRuntime::unavailable();
let languages = Arc::new(LanguageRegistry::new(server_cx.executor()));
let _headless_project = server_cx.new_model(|cx| {
client::init_settings(cx);
HeadlessProject::new(
HeadlessAppState {
session: server_ssh,
fs: remote_fs.clone(),
http_client: remote_http_client,
node_runtime: node,
languages,
},
cx,
)
});

let (project_a, worktree_id) = client_a
.build_ssh_project("/code/project1", client_ssh, cx_a)
Expand Down
13 changes: 9 additions & 4 deletions crates/editor/src/git/blame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,10 @@ impl GitBlame {
if this.user_triggered {
log::error!("failed to get git blame data: {error:?}");
let notification = format!("{:#}", error).trim().to_string();
cx.emit(project::Event::Notification(notification));
cx.emit(project::Event::Toast {
notification_id: "git-blame".into(),
message: notification,
});
} else {
// If we weren't triggered by a user, we just log errors in the background, instead of sending
// notifications.
Expand Down Expand Up @@ -619,9 +622,11 @@ mod tests {
let event = project.next_event(cx).await;
assert_eq!(
event,
project::Event::Notification(
"Failed to blame \"file.txt\": failed to get blame for \"file.txt\"".to_string()
)
project::Event::Toast {
notification_id: "git-blame".into(),
message: "Failed to blame \"file.txt\": failed to get blame for \"file.txt\""
.to_string()
}
);

blame.update(cx, |blame, cx| {
Expand Down
5 changes: 4 additions & 1 deletion crates/extension/src/extension_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ impl Settings for ExtensionSettings {

fn load(sources: SettingsSources<Self::FileContent>, _cx: &mut AppContext) -> Result<Self> {
SettingsSources::<Self::FileContent>::json_merge_with(
[sources.default].into_iter().chain(sources.user),
[sources.default]
.into_iter()
.chain(sources.user)
.chain(sources.server),
)
}
}
2 changes: 1 addition & 1 deletion crates/extensions_ui/src/extension_suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ pub(crate) fn suggest(buffer: Model<Buffer>, cx: &mut ViewContext<Workspace>) {

struct ExtensionSuggestionNotification;

let notification_id = NotificationId::identified::<ExtensionSuggestionNotification>(
let notification_id = NotificationId::composite::<ExtensionSuggestionNotification>(
SharedString::from(extension_id.clone()),
);

Expand Down
6 changes: 6 additions & 0 deletions crates/gpui/src/app/entity_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,12 @@ pub struct WeakModel<T> {
entity_type: PhantomData<T>,
}

impl<T> std::fmt::Debug for WeakModel<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct(type_name::<WeakModel<T>>()).finish()
}
}

unsafe impl<T> Send for WeakModel<T> {}
unsafe impl<T> Sync for WeakModel<T> {}

Expand Down
6 changes: 6 additions & 0 deletions crates/http_client/src/http_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,12 @@ pub fn read_proxy_from_env() -> Option<Uri> {

pub struct BlockedHttpClient;

impl BlockedHttpClient {
pub fn new() -> Self {
BlockedHttpClient
}
}

impl HttpClient for BlockedHttpClient {
fn send(
&self,
Expand Down
2 changes: 1 addition & 1 deletion crates/language/src/language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ pub trait LspAdapter: 'static + Send + Sync {
}

let Some(container_dir) = delegate.language_server_download_dir(&self.name()).await else {
anyhow::bail!("cannot download language servers for remotes (yet)")
anyhow::bail!("no language server download dir defined")
};

let mut binary = try_fetch_server_binary(self.as_ref(), &delegate, container_dir.to_path_buf(), cx).await;
Expand Down
11 changes: 11 additions & 0 deletions crates/paths/src/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ use std::sync::OnceLock;

pub use util::paths::home_dir;

/// Returns the relative path to the zed_server directory on the ssh host.
pub fn remote_server_dir_relative() -> &'static Path {
Path::new(".zed_server")
}

/// Returns the path to the configuration directory used by Zed.
pub fn config_dir() -> &'static PathBuf {
static CONFIG_DIR: OnceLock<PathBuf> = OnceLock::new();
Expand Down Expand Up @@ -96,6 +101,12 @@ pub fn logs_dir() -> &'static PathBuf {
})
}

/// Returns the path to the zed server directory on this ssh host.
pub fn remote_server_state_dir() -> &'static PathBuf {
static REMOTE_SERVER_STATE: OnceLock<PathBuf> = OnceLock::new();
REMOTE_SERVER_STATE.get_or_init(|| return support_dir().join("server_state"))
}

/// Returns the path to the `Zed.log` file.
pub fn log_file() -> &'static PathBuf {
static LOG_FILE: OnceLock<PathBuf> = OnceLock::new();
Expand Down
11 changes: 4 additions & 7 deletions crates/project/src/lsp_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use gpui::{
AppContext, AsyncAppContext, Context, Entity, EventEmitter, Model, ModelContext, PromptLevel,
Task, WeakModel,
};
use http_client::{BlockedHttpClient, HttpClient};
use http_client::HttpClient;
use language::{
language_settings::{
all_language_settings, language_settings, AllLanguageSettings, FormatOnSave, Formatter,
Expand Down Expand Up @@ -116,7 +116,7 @@ impl FormatTrigger {
}

pub struct LocalLspStore {
http_client: Option<Arc<dyn HttpClient>>,
http_client: Arc<dyn HttpClient>,
environment: Model<ProjectEnvironment>,
fs: Arc<dyn Fs>,
yarn: Model<YarnPathStore>,
Expand Down Expand Up @@ -839,7 +839,7 @@ impl LspStore {
prettier_store: Model<PrettierStore>,
environment: Model<ProjectEnvironment>,
languages: Arc<LanguageRegistry>,
http_client: Option<Arc<dyn HttpClient>>,
http_client: Arc<dyn HttpClient>,
fs: Arc<dyn Fs>,
cx: &mut ModelContext<Self>,
) -> Self {
Expand Down Expand Up @@ -7579,10 +7579,7 @@ impl LocalLspAdapterDelegate {
.as_local()
.expect("LocalLspAdapterDelegate cannot be constructed on a remote");

let http_client = local
.http_client
.clone()
.unwrap_or_else(|| Arc::new(BlockedHttpClient));
let http_client = local.http_client.clone();

Self::new(lsp_store, worktree, http_client, local.fs.clone(), cx)
}
Expand Down
Loading

0 comments on commit f944ebc

Please sign in to comment.