From ef45eca88e0dff078fca579f56d4c5f6f9beaed3 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 9 Dec 2024 15:23:28 -0500 Subject: [PATCH] extension_host: Fix uploading dev extensions to the remote server (#21761) This PR fixes an issue where dev extensions were not working when uploaded to the remote server. The `extension.toml` for dev extensions may not contain all of the information (such as the list of languages), as this is something that we derive from the filesystem at packaging time. This meant that uploading a dev extension that contained languages could have them absent from the uploaded `extension.toml`. For dev extensions we now upload a serialized version of the in-memory extension manifest, which should have all of the information present. Release Notes: - SSH Remoting: Fixed an issue where some dev extensions would not work after being uploaded to the remote server. --------- Co-authored-by: Conrad --- crates/extension_host/src/extension_host.rs | 52 +++++++++++++++------ 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/crates/extension_host/src/extension_host.rs b/crates/extension_host/src/extension_host.rs index 7ceb1fa7147cee6a45149785520c4fc881fdf075..6c965d3d56810a6ea65d5fcc3e692df666527a3f 100644 --- a/crates/extension_host/src/extension_host.rs +++ b/crates/extension_host/src/extension_host.rs @@ -32,7 +32,7 @@ use gpui::{ }; use http_client::{AsyncBody, HttpClient, HttpClientWithUrl}; use language::{ - LanguageConfig, LanguageMatcher, LanguageName, LanguageQueries, LoadedLanguage, + LanguageConfig, LanguageMatcher, LanguageName, LanguageQueries, LoadedLanguage, Rope, QUERY_FILENAME_PREFIXES, }; use node_runtime::NodeRuntime; @@ -1387,6 +1387,7 @@ impl ExtensionStore { fn prepare_remote_extension( &mut self, extension_id: Arc, + is_dev: bool, tmp_dir: PathBuf, cx: &mut ModelContext, ) -> Task> { @@ -1397,26 +1398,45 @@ impl ExtensionStore { }; let fs = self.fs.clone(); cx.background_executor().spawn(async move { - for well_known_path in ["extension.toml", "extension.json", "extension.wasm"] { - if fs.is_file(&src_dir.join(well_known_path)).await { - fs.copy_file( - &src_dir.join(well_known_path), - &tmp_dir.join(well_known_path), - fs::CopyOptions::default(), - ) - .await? - } + const EXTENSION_TOML: &str = "extension.toml"; + const EXTENSION_WASM: &str = "extension.wasm"; + const CONFIG_TOML: &str = "config.toml"; + + if is_dev { + let manifest_toml = toml::to_string(&loaded_extension.manifest)?; + fs.save( + &tmp_dir.join(EXTENSION_TOML), + &Rope::from(manifest_toml), + language::LineEnding::Unix, + ) + .await?; + } else { + fs.copy_file( + &src_dir.join(EXTENSION_TOML), + &tmp_dir.join(EXTENSION_TOML), + fs::CopyOptions::default(), + ) + .await? + } + + if fs.is_file(&src_dir.join(EXTENSION_WASM)).await { + fs.copy_file( + &src_dir.join(EXTENSION_WASM), + &tmp_dir.join(EXTENSION_WASM), + fs::CopyOptions::default(), + ) + .await? } for language_path in loaded_extension.manifest.languages.iter() { if fs - .is_file(&src_dir.join(language_path).join("config.toml")) + .is_file(&src_dir.join(language_path).join(CONFIG_TOML)) .await { fs.create_dir(&tmp_dir.join(language_path)).await?; fs.copy_file( - &src_dir.join(language_path).join("config.toml"), - &tmp_dir.join(language_path).join("config.toml"), + &src_dir.join(language_path).join(CONFIG_TOML), + &tmp_dir.join(language_path).join(CONFIG_TOML), fs::CopyOptions::default(), ) .await? @@ -1462,6 +1482,7 @@ impl ExtensionStore { this.update(cx, |this, cx| { this.prepare_remote_extension( missing_extension.id.clone().into(), + missing_extension.dev, tmp_dir.path().to_owned(), cx, ) @@ -1476,6 +1497,11 @@ impl ExtensionStore { })? .await?; + log::info!( + "Finished uploading extension {}", + missing_extension.clone().id + ); + client .update(cx, |client, _cx| { client.proto_client().request(proto::InstallExtension {