Refactor out the node runtime crate and hook up all related imports

Mikayla Maki created

Change summary

Cargo.lock                              | 19 +++++++++++
Cargo.toml                              |  1 
crates/copilot/Cargo.toml               |  1 
crates/copilot/src/copilot.rs           | 14 ++++++--
crates/node_runtime/Cargo.toml          | 22 +++++++++++++
crates/node_runtime/src/node_runtime.rs |  0 
crates/util/src/github.rs               |  5 +++
crates/zed/Cargo.toml                   |  1 
crates/zed/src/languages.rs             |  9 ----
crates/zed/src/languages/c.rs           |  2 
crates/zed/src/languages/elixir.rs      |  2 
crates/zed/src/languages/github.rs      | 45 ---------------------------
crates/zed/src/languages/html.rs        |  2 
crates/zed/src/languages/json.rs        |  2 
crates/zed/src/languages/lua.rs         |  2 
crates/zed/src/languages/python.rs      |  2 
crates/zed/src/languages/rust.rs        |  2 
crates/zed/src/languages/typescript.rs  |  2 
crates/zed/src/languages/yaml.rs        |  2 
crates/zed/src/main.rs                  | 12 +++----
crates/zed/src/zed.rs                   | 10 ++---
21 files changed, 78 insertions(+), 79 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -1343,6 +1343,7 @@ dependencies = [
  "language",
  "log",
  "lsp",
+ "node_runtime",
  "serde",
  "serde_derive",
  "settings",
@@ -3931,6 +3932,23 @@ dependencies = [
  "memoffset 0.6.5",
 ]
 
+[[package]]
+name = "node_runtime"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "async-compression",
+ "async-tar",
+ "futures 0.3.25",
+ "gpui",
+ "parking_lot 0.11.2",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "smol",
+ "util",
+]
+
 [[package]]
 name = "nom"
 version = "7.1.1"
@@ -8512,6 +8530,7 @@ dependencies = [
  "libc",
  "log",
  "lsp",
+ "node_runtime",
  "num_cpus",
  "outline",
  "parking_lot 0.11.2",

Cargo.toml 🔗

@@ -36,6 +36,7 @@ members = [
     "crates/lsp",
     "crates/media",
     "crates/menu",
+    "crates/node_runtime",
     "crates/outline",
     "crates/picker",
     "crates/plugin",

crates/copilot/Cargo.toml 🔗

@@ -14,6 +14,7 @@ language = { path = "../language" }
 settings = { path = "../settings" }
 theme = { path = "../theme" }
 lsp = { path = "../lsp" }
+node_runtime = { path = "../node_runtime"}
 util = { path = "../util" }
 client = { path = "../client" }
 workspace = { path = "../workspace" }

crates/copilot/src/copilot.rs 🔗

@@ -8,6 +8,7 @@ use futures::{future::Shared, FutureExt, TryFutureExt};
 use gpui::{actions, AppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task};
 use language::{point_from_lsp, point_to_lsp, Anchor, Bias, Buffer, BufferSnapshot, ToPointUtf16};
 use lsp::LanguageServer;
+use node_runtime::NodeRuntime;
 use settings::Settings;
 use smol::{fs, io::BufReader, stream::StreamExt};
 use std::{
@@ -21,8 +22,8 @@ use util::{
 
 actions!(copilot, [SignIn, SignOut, NextSuggestion]);
 
-pub fn init(client: Arc<Client>, cx: &mut MutableAppContext) {
-    let copilot = cx.add_model(|cx| Copilot::start(client.http_client(), cx));
+pub fn init(client: Arc<Client>, node_runtime: Arc<NodeRuntime>, cx: &mut MutableAppContext) {
+    let copilot = cx.add_model(|cx| Copilot::start(client.http_client(), node_runtime, cx));
     cx.set_global(copilot.clone());
     cx.add_global_action(|_: &SignIn, cx| {
         let copilot = Copilot::global(cx).unwrap();
@@ -104,7 +105,11 @@ impl Copilot {
         }
     }
 
-    fn start(http: Arc<dyn HttpClient>, cx: &mut ModelContext<Self>) -> Self {
+    fn start(
+        http: Arc<dyn HttpClient>,
+        node_runtime: Arc<NodeRuntime>,
+        cx: &mut ModelContext<Self>,
+    ) -> Self {
         // TODO: Don't eagerly download the LSP
         cx.spawn(|this, mut cx| async move {
             let start_language_server = async {
@@ -469,7 +474,8 @@ mod tests {
     async fn test_smoke(cx: &mut TestAppContext) {
         Settings::test_async(cx);
         let http = http::client();
-        let copilot = cx.add_model(|cx| Copilot::start(http, cx));
+        let node_runtime = NodeRuntime::new(http.clone(), cx.background());
+        let copilot = cx.add_model(|cx| Copilot::start(http, node_runtime, cx));
         smol::Timer::after(std::time::Duration::from_secs(2)).await;
         copilot
             .update(cx, |copilot, cx| copilot.sign_in(cx))

crates/node_runtime/Cargo.toml 🔗

@@ -0,0 +1,22 @@
+[package]
+name = "node_runtime"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[lib]
+path = "src/node_runtime.rs"
+doctest = false
+
+[dependencies]
+gpui = { path = "../gpui" }
+util = { path = "../util" }
+async-compression = { version = "0.3", features = ["gzip", "futures-bufread"] }
+async-tar = "0.4.2"
+futures = "0.3"
+anyhow = "1.0.38"
+parking_lot = "0.11.1"
+serde = { workspace = true }
+serde_derive = { workspace = true }
+serde_json = { workspace = true }
+smol = "1.2.5"

crates/util/src/github.rs 🔗

@@ -4,6 +4,11 @@ use futures::AsyncReadExt;
 use serde::Deserialize;
 use std::sync::Arc;
 
+pub struct GitHubLspBinaryVersion {
+    pub name: String,
+    pub url: String,
+}
+
 #[derive(Deserialize)]
 pub struct GithubRelease {
     pub name: String,

crates/zed/Cargo.toml 🔗

@@ -45,6 +45,7 @@ journal = { path = "../journal" }
 language = { path = "../language" }
 language_selector = { path = "../language_selector" }
 lsp = { path = "../lsp" }
+node_runtime = { path = "../node_runtime" }
 outline = { path = "../outline" }
 plugin_runtime = { path = "../plugin_runtime" }
 project = { path = "../project" }

crates/zed/src/languages.rs 🔗

@@ -1,21 +1,17 @@
 use anyhow::Context;
-use gpui::executor::Background;
 pub use language::*;
 use node_runtime::NodeRuntime;
 use rust_embed::RustEmbed;
 use std::{borrow::Cow, str, sync::Arc};
 use theme::ThemeRegistry;
-use util::http::HttpClient;
 
 mod c;
 mod elixir;
-mod github;
 mod go;
 mod html;
 mod json;
 mod language_plugin;
 mod lua;
-mod node_runtime;
 mod python;
 mod ruby;
 mod rust;
@@ -37,13 +33,10 @@ mod yaml;
 struct LanguageDir;
 
 pub fn init(
-    http: Arc<dyn HttpClient>,
-    background: Arc<Background>,
     languages: Arc<LanguageRegistry>,
     themes: Arc<ThemeRegistry>,
+    node_runtime: Arc<NodeRuntime>,
 ) {
-    let node_runtime = NodeRuntime::new(http, background);
-
     for (name, grammar, lsp_adapter) in [
         (
             "c",

crates/zed/src/languages/c.rs 🔗

@@ -9,7 +9,7 @@ use util::github::latest_github_release;
 use util::http::HttpClient;
 use util::ResultExt;
 
-use super::github::GitHubLspBinaryVersion;
+use util::github::GitHubLspBinaryVersion;
 
 pub struct CLspAdapter;
 

crates/zed/src/languages/elixir.rs 🔗

@@ -10,7 +10,7 @@ use util::github::latest_github_release;
 use util::http::HttpClient;
 use util::ResultExt;
 
-use super::github::GitHubLspBinaryVersion;
+use util::github::GitHubLspBinaryVersion;
 
 pub struct ElixirLspAdapter;
 

crates/zed/src/languages/github.rs 🔗

@@ -1,45 +0,0 @@
-use anyhow::{Context, Result};
-use serde::Deserialize;
-use smol::io::AsyncReadExt;
-use std::sync::Arc;
-use util::http::HttpClient;
-
-pub struct GitHubLspBinaryVersion {
-    pub name: String,
-    pub url: String,
-}
-
-#[derive(Deserialize)]
-pub(crate) struct GithubRelease {
-    pub name: String,
-    pub assets: Vec<GithubReleaseAsset>,
-}
-
-#[derive(Deserialize)]
-pub(crate) struct GithubReleaseAsset {
-    pub name: String,
-    pub browser_download_url: String,
-}
-
-pub(crate) async fn latest_github_release(
-    repo_name_with_owner: &str,
-    http: Arc<dyn HttpClient>,
-) -> Result<GithubRelease, anyhow::Error> {
-    let mut response = http
-        .get(
-            &format!("https://api.github.com/repos/{repo_name_with_owner}/releases/latest"),
-            Default::default(),
-            true,
-        )
-        .await
-        .context("error fetching latest release")?;
-    let mut body = Vec::new();
-    response
-        .body_mut()
-        .read_to_end(&mut body)
-        .await
-        .context("error reading latest release")?;
-    let release: GithubRelease =
-        serde_json::from_slice(body.as_slice()).context("error deserializing latest release")?;
-    Ok(release)
-}

crates/zed/src/languages/html.rs 🔗

@@ -1,4 +1,4 @@
-use super::node_runtime::NodeRuntime;
+use node_runtime::NodeRuntime;
 use anyhow::{anyhow, Context, Result};
 use async_trait::async_trait;
 use futures::StreamExt;

crates/zed/src/languages/json.rs 🔗

@@ -1,4 +1,4 @@
-use super::node_runtime::NodeRuntime;
+use node_runtime::NodeRuntime;
 use anyhow::{anyhow, Context, Result};
 use async_trait::async_trait;
 use collections::HashMap;

crates/zed/src/languages/lua.rs 🔗

@@ -8,7 +8,7 @@ use smol::fs;
 use std::{any::Any, env::consts, ffi::OsString, path::PathBuf, sync::Arc};
 use util::{async_iife, github::latest_github_release, http::HttpClient, ResultExt};
 
-use super::github::GitHubLspBinaryVersion;
+use util::github::GitHubLspBinaryVersion;
 
 #[derive(Copy, Clone)]
 pub struct LuaLspAdapter;

crates/zed/src/languages/python.rs 🔗

@@ -1,4 +1,4 @@
-use super::node_runtime::NodeRuntime;
+use node_runtime::NodeRuntime;
 use anyhow::{anyhow, Context, Result};
 use async_trait::async_trait;
 use futures::StreamExt;

crates/zed/src/languages/rust.rs 🔗

@@ -1,4 +1,3 @@
-use super::github::{latest_github_release, GitHubLspBinaryVersion};
 use anyhow::{anyhow, Result};
 use async_compression::futures::bufread::GzipDecoder;
 use async_trait::async_trait;
@@ -9,6 +8,7 @@ use regex::Regex;
 use smol::fs::{self, File};
 use std::{any::Any, borrow::Cow, env::consts, path::PathBuf, str, sync::Arc};
 use util::fs::remove_matching;
+use util::github::{latest_github_release, GitHubLspBinaryVersion};
 use util::http::HttpClient;
 use util::ResultExt;
 

crates/zed/src/languages/typescript.rs 🔗

@@ -1,8 +1,8 @@
-use super::node_runtime::NodeRuntime;
 use anyhow::{anyhow, Context, Result};
 use async_trait::async_trait;
 use futures::StreamExt;
 use language::{LanguageServerBinary, LanguageServerName, LspAdapter};
+use node_runtime::NodeRuntime;
 use serde_json::json;
 use smol::fs;
 use std::{

crates/zed/src/languages/yaml.rs 🔗

@@ -1,9 +1,9 @@
-use super::node_runtime::NodeRuntime;
 use anyhow::{anyhow, Context, Result};
 use async_trait::async_trait;
 use futures::{future::BoxFuture, FutureExt, StreamExt};
 use gpui::MutableAppContext;
 use language::{LanguageServerBinary, LanguageServerName, LspAdapter};
+use node_runtime::NodeRuntime;
 use serde_json::Value;
 use settings::Settings;
 use smol::fs;

crates/zed/src/main.rs 🔗

@@ -18,6 +18,7 @@ use gpui::{Action, App, AssetSource, AsyncAppContext, MutableAppContext, Task, V
 use isahc::{config::Configurable, Request};
 use language::LanguageRegistry;
 use log::LevelFilter;
+use node_runtime::NodeRuntime;
 use parking_lot::Mutex;
 use project::Fs;
 use serde_json::json;
@@ -136,12 +137,9 @@ fn main() {
         languages.set_executor(cx.background().clone());
         languages.set_language_server_download_dir(paths::LANGUAGES_DIR.clone());
         let languages = Arc::new(languages);
-        languages::init(
-            http.clone(),
-            cx.background().clone(),
-            languages.clone(),
-            themes.clone(),
-        );
+        let node_runtime = NodeRuntime::new(http.clone(), cx.background().to_owned());
+
+        languages::init(languages.clone(), themes.clone(), node_runtime.clone());
         let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http.clone(), cx));
 
         cx.set_global(client.clone());
@@ -162,7 +160,7 @@ fn main() {
         terminal_view::init(cx);
         theme_testbench::init(cx);
         recent_projects::init(cx);
-        copilot::init(client.clone(), cx);
+        copilot::init(client.clone(), node_runtime, cx);
 
         cx.spawn(|cx| watch_themes(fs.clone(), themes.clone(), cx))
             .detach();

crates/zed/src/zed.rs 🔗

@@ -657,6 +657,7 @@ mod tests {
         executor::Deterministic, AssetSource, MutableAppContext, TestAppContext, ViewHandle,
     };
     use language::LanguageRegistry;
+    use node_runtime::NodeRuntime;
     use project::{Project, ProjectPath};
     use serde_json::json;
     use std::{
@@ -1851,12 +1852,9 @@ mod tests {
         languages.set_executor(cx.background().clone());
         let languages = Arc::new(languages);
         let themes = ThemeRegistry::new((), cx.font_cache().clone());
-        languages::init(
-            FakeHttpClient::with_404_response(),
-            cx.background().clone(),
-            languages.clone(),
-            themes,
-        );
+        let http = FakeHttpClient::with_404_response();
+        let node_runtime = NodeRuntime::new(http, cx.background().to_owned());
+        languages::init(languages.clone(), themes, node_runtime);
         for name in languages.language_names() {
             languages.language_for_name(&name);
         }