Allow using system node (#18172)

Release Notes:

- (Potentially breaking change) Zed will now use the node installed on
your $PATH (if it is more recent than v18) instead of downloading its
own. You can disable the new behavior with `{"node":
{"disable_path_lookup": true}}` in your settings. We do not yet use
system/project-local node_modules.

---------

Co-authored-by: Mikayla <mikayla@zed.dev>
This commit is contained in:
Conrad Irwin 2024-09-23 15:28:04 -06:00 committed by GitHub
parent e4080ef565
commit 3ba071b993
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 614 additions and 391 deletions

View file

@ -17,7 +17,7 @@ use async_trait::async_trait;
use client::{proto, TypedEnvelope};
use collections::{btree_map, BTreeMap, HashMap, HashSet};
use futures::{
future::{join_all, BoxFuture, Shared},
future::{join_all, Shared},
select,
stream::FuturesUnordered,
AsyncWriteExt, Future, FutureExt, StreamExt,
@ -27,7 +27,7 @@ use gpui::{
AppContext, AsyncAppContext, Context, Entity, EventEmitter, Model, ModelContext, PromptLevel,
Task, WeakModel,
};
use http_client::{AsyncBody, HttpClient, Request, Response, Uri};
use http_client::{BlockedHttpClient, HttpClient};
use language::{
language_settings::{
all_language_settings, language_settings, AllLanguageSettings, FormatOnSave, Formatter,
@ -7979,35 +7979,6 @@ impl LspAdapterDelegate for LocalLspAdapterDelegate {
}
}
struct BlockedHttpClient;
impl HttpClient for BlockedHttpClient {
fn send(
&self,
_req: Request<AsyncBody>,
) -> BoxFuture<'static, Result<Response<AsyncBody>, anyhow::Error>> {
Box::pin(async {
Err(std::io::Error::new(
std::io::ErrorKind::PermissionDenied,
"ssh host blocked http connection",
)
.into())
})
}
fn proxy(&self) -> Option<&Uri> {
None
}
fn send_with_redirect_policy(
&self,
req: Request<AsyncBody>,
_: bool,
) -> BoxFuture<'static, Result<Response<AsyncBody>, anyhow::Error>> {
self.send(req)
}
}
struct SshLspAdapterDelegate {
lsp_store: WeakModel<LspStore>,
worktree: worktree::Snapshot,

View file

@ -30,7 +30,7 @@ use crate::{
};
pub struct PrettierStore {
node: Arc<dyn NodeRuntime>,
node: NodeRuntime,
fs: Arc<dyn Fs>,
languages: Arc<LanguageRegistry>,
worktree_store: Model<WorktreeStore>,
@ -52,7 +52,7 @@ impl EventEmitter<PrettierStoreEvent> for PrettierStore {}
impl PrettierStore {
pub fn new(
node: Arc<dyn NodeRuntime>,
node: NodeRuntime,
fs: Arc<dyn Fs>,
languages: Arc<LanguageRegistry>,
worktree_store: Model<WorktreeStore>,
@ -212,7 +212,7 @@ impl PrettierStore {
}
fn start_prettier(
node: Arc<dyn NodeRuntime>,
node: NodeRuntime,
prettier_dir: PathBuf,
worktree_id: Option<WorktreeId>,
cx: &mut ModelContext<Self>,
@ -241,7 +241,7 @@ impl PrettierStore {
}
fn start_default_prettier(
node: Arc<dyn NodeRuntime>,
node: NodeRuntime,
worktree_id: Option<WorktreeId>,
cx: &mut ModelContext<PrettierStore>,
) -> Task<anyhow::Result<PrettierTask>> {
@ -749,7 +749,7 @@ impl DefaultPrettier {
pub fn prettier_task(
&mut self,
node: &Arc<dyn NodeRuntime>,
node: &NodeRuntime,
worktree_id: Option<WorktreeId>,
cx: &mut ModelContext<PrettierStore>,
) -> Option<Task<anyhow::Result<PrettierTask>>> {
@ -767,7 +767,7 @@ impl DefaultPrettier {
impl PrettierInstance {
pub fn prettier_task(
&mut self,
node: &Arc<dyn NodeRuntime>,
node: &NodeRuntime,
prettier_dir: Option<&Path>,
worktree_id: Option<WorktreeId>,
cx: &mut ModelContext<PrettierStore>,
@ -786,7 +786,7 @@ impl PrettierInstance {
None => match prettier_dir {
Some(prettier_dir) => {
let new_task = PrettierStore::start_prettier(
Arc::clone(node),
node.clone(),
prettier_dir.to_path_buf(),
worktree_id,
cx,
@ -797,7 +797,7 @@ impl PrettierInstance {
}
None => {
self.attempt += 1;
let node = Arc::clone(node);
let node = node.clone();
cx.spawn(|prettier_store, mut cx| async move {
prettier_store
.update(&mut cx, |_, cx| {
@ -818,7 +818,7 @@ impl PrettierInstance {
async fn install_prettier_packages(
fs: &dyn Fs,
plugins_to_install: HashSet<Arc<str>>,
node: Arc<dyn NodeRuntime>,
node: NodeRuntime,
) -> anyhow::Result<()> {
let packages_to_versions = future::try_join_all(
plugins_to_install

View file

@ -153,7 +153,7 @@ pub struct Project {
git_diff_debouncer: DebouncedDelay<Self>,
remotely_created_models: Arc<Mutex<RemotelyCreatedModels>>,
terminals: Terminals,
node: Option<Arc<dyn NodeRuntime>>,
node: Option<NodeRuntime>,
tasks: Model<Inventory>,
hosted_project_id: Option<ProjectId>,
dev_server_project_id: Option<client::DevServerProjectId>,
@ -579,7 +579,7 @@ impl Project {
pub fn local(
client: Arc<Client>,
node: Arc<dyn NodeRuntime>,
node: NodeRuntime,
user_store: Model<UserStore>,
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
@ -675,7 +675,7 @@ impl Project {
pub fn ssh(
ssh: Arc<SshSession>,
client: Arc<Client>,
node: Arc<dyn NodeRuntime>,
node: NodeRuntime,
user_store: Model<UserStore>,
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
@ -1064,7 +1064,7 @@ impl Project {
.update(|cx| {
Project::local(
client,
node_runtime::FakeNodeRuntime::new(),
node_runtime::NodeRuntime::unavailable(),
user_store,
Arc::new(languages),
fs,
@ -1104,7 +1104,7 @@ impl Project {
let project = cx.update(|cx| {
Project::local(
client,
node_runtime::FakeNodeRuntime::new(),
node_runtime::NodeRuntime::unavailable(),
user_store,
Arc::new(languages),
fs,
@ -1157,7 +1157,7 @@ impl Project {
self.user_store.clone()
}
pub fn node_runtime(&self) -> Option<&Arc<dyn NodeRuntime>> {
pub fn node_runtime(&self) -> Option<&NodeRuntime> {
self.node.as_ref()
}

View file

@ -34,6 +34,10 @@ pub struct ProjectSettings {
#[serde(default)]
pub git: GitSettings,
/// Configuration for Node-related features
#[serde(default)]
pub node: NodeBinarySettings,
/// Configuration for how direnv configuration should be loaded
#[serde(default)]
pub load_direnv: DirenvSettings,
@ -43,6 +47,17 @@ pub struct ProjectSettings {
pub session: SessionSettings,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct NodeBinarySettings {
/// The path to the node binary
pub path: Option<String>,
/// The path to the npm binary Zed should use (defaults to .path/../npm)
pub npm_path: Option<String>,
/// If disabled, zed will download its own copy of node.
#[serde(default)]
pub disable_path_lookup: Option<bool>,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum DirenvSettings {