From 5bb8c26b4ff960814c01bd2bb1cca870470b6b3b Mon Sep 17 00:00:00 2001 From: Miles Johnson Date: Wed, 6 Sep 2023 15:21:16 -0700 Subject: [PATCH 1/4] Start on events. --- Cargo.lock | 47 ++++++++++++------------ crates/core/Cargo.toml | 1 + crates/core/src/events.rs | 45 +++++++++++++++++++++++ crates/core/src/lib.rs | 2 ++ crates/core/src/tool.rs | 76 ++++++++++++++++++++++++++++++++++++--- 5 files changed, 143 insertions(+), 28 deletions(-) create mode 100644 crates/core/src/events.rs diff --git a/Cargo.lock b/Cargo.lock index a39e0ff0d..db38bcf1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -172,13 +172,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.72" +version = "0.1.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.31", ] [[package]] @@ -518,7 +518,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.31", ] [[package]] @@ -818,7 +818,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.28", + "syn 2.0.31", ] [[package]] @@ -835,7 +835,7 @@ checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.31", ] [[package]] @@ -883,7 +883,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.28", + "syn 2.0.31", ] [[package]] @@ -905,7 +905,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core 0.20.3", "quote", - "syn 2.0.28", + "syn 2.0.31", ] [[package]] @@ -1161,7 +1161,7 @@ checksum = "d2be216330f7304de051e0faf1578880e9e0dc1ecbd2c0fea5765c63a079d0ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.31", ] [[package]] @@ -1347,7 +1347,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.31", ] [[package]] @@ -2036,7 +2036,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.31", ] [[package]] @@ -2364,6 +2364,7 @@ dependencies = [ "serde_json", "sha2", "starbase_archive", + "starbase_events", "starbase_sandbox", "starbase_styles", "starbase_utils", @@ -2448,9 +2449,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -2839,7 +2840,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.31", ] [[package]] @@ -3044,9 +3045,9 @@ dependencies = [ [[package]] name = "starbase_events" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6913545608418518959d13ac9e05568d0d059f53ab3a24cf3283b7958ee5e732" +checksum = "5f172a2185991dbfb2a3446c47749ade52d66d2aaea724d19bd45607527ebd9d" dependencies = [ "async-trait", "miette", @@ -3056,14 +3057,14 @@ dependencies = [ [[package]] name = "starbase_macros" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd2a77f76022474557803637dbefe72e38fa196564e9a1daf3c695c06b1ee222" +checksum = "63159597180d00c01353e4bf4d4401328a30eb618c0130adf7b9371db4df3d3a" dependencies = [ "darling 0.20.3", "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.31", ] [[package]] @@ -3163,9 +3164,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.28" +version = "2.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" dependencies = [ "proc-macro2", "quote", @@ -3277,7 +3278,7 @@ checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.31", ] [[package]] @@ -3393,7 +3394,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.31", ] [[package]] diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 7488b2ef1..5c7ce576d 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -23,6 +23,7 @@ serde = { workspace = true } serde_json = { workspace = true } sha2 = { workspace = true } starbase_archive = { workspace = true } +starbase_events = "0.2.1" starbase_styles = { workspace = true } starbase_utils = { workspace = true, features = ["fs-lock"] } thiserror = { workspace = true } diff --git a/crates/core/src/events.rs b/crates/core/src/events.rs new file mode 100644 index 000000000..ef9b31d68 --- /dev/null +++ b/crates/core/src/events.rs @@ -0,0 +1,45 @@ +use crate::version::AliasOrVersion; +use starbase_events::Event; + +macro_rules! impl_event { + ($name:ident, $impl:tt) => { + impl_event!($name, (), $impl); + }; + + ($name:ident, $data:ty, $impl:tt) => { + pub struct $name $impl + + impl Event for $name { + type Data = $data; + } + }; +} + +impl_event!(InstallingEvent, { + pub version: AliasOrVersion, +}); + +impl_event!(InstalledEvent, { + pub version: AliasOrVersion, +}); + +impl_event!(InstalledGlobalEvent, { + pub dependency: String, +}); + +impl_event!(UninstallingEvent, { + pub version: AliasOrVersion, +}); + +impl_event!(UninstalledEvent, { + pub version: AliasOrVersion, +}); + +impl_event!(UninstalledGlobalEvent, { + pub dependency: String, +}); + +impl_event!(CreatedShimsEvent, { + pub global: Vec, + pub local: Vec, +}); diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index e5559bac9..6b0dcb71f 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -1,4 +1,5 @@ mod error; +mod events; mod helpers; mod proto; mod shimmer; @@ -12,6 +13,7 @@ mod version_detector; mod version_resolver; pub use error::*; +pub use events::*; pub use extism::{manifest::Wasm, Manifest as PluginManifest}; pub use helpers::*; pub use proto::*; diff --git a/crates/core/src/tool.rs b/crates/core/src/tool.rs index 83768f37c..e8adc42b6 100644 --- a/crates/core/src/tool.rs +++ b/crates/core/src/tool.rs @@ -1,4 +1,5 @@ use crate::error::ProtoError; +use crate::events::*; use crate::helpers::{hash_file_contents, is_cache_enabled, is_offline}; use crate::proto::ProtoEnvironment; use crate::shimmer::{ @@ -17,6 +18,7 @@ use proto_pdk_api::*; use proto_wasm_plugin::{create_host_functions, HostData}; use serde::Serialize; use starbase_archive::Archiver; +use starbase_events::Emitter; use starbase_styles::color; use starbase_utils::fs; use std::collections::{BTreeMap, HashSet}; @@ -36,6 +38,15 @@ pub struct Tool { pub proto: ProtoEnvironment, pub version: Option, + // Events + pub on_created_shims: Emitter, + pub on_installing: Emitter, + pub on_installed: Emitter, + pub on_installed_global: Emitter, + pub on_uninstalling: Emitter, + pub on_uninstalled: Emitter, + pub on_uninstalled_global: Emitter, + bin_path: Option, globals_dir: Option, globals_prefix: Option, @@ -83,6 +94,15 @@ impl Tool { )?, proto: proto.to_owned(), version: None, + + // Events + on_created_shims: Emitter::new(), + on_installing: Emitter::new(), + on_installed: Emitter::new(), + on_installed_global: Emitter::new(), + on_uninstalling: Emitter::new(), + on_uninstalled: Emitter::new(), + on_uninstalled_global: Emitter::new(), }; debug!( @@ -707,6 +727,12 @@ impl Tool { return Ok(false); } + self.on_installing + .emit(InstallingEvent { + version: self.get_resolved_version(), + }) + .await?; + // If this function is defined, it acts like an escape hatch and // takes precedence over all other install strategies if self.plugin.has_func("native_install") { @@ -725,6 +751,12 @@ impl Tool { // Install from a prebuilt archive self.install_from_prebuilt(&install_dir).await?; + self.on_installed + .emit(InstalledEvent { + version: self.get_resolved_version(), + }) + .await?; + debug!( tool = self.id.as_str(), install_dir = ?install_dir, @@ -759,6 +791,12 @@ impl Tool { ))?; } + self.on_installed_global + .emit(InstalledGlobalEvent { + dependency: dependency.to_owned(), + }) + .await?; + Ok(result.installed) } @@ -775,6 +813,12 @@ impl Tool { return Ok(false); } + self.on_uninstalling + .emit(UninstallingEvent { + version: self.get_resolved_version(), + }) + .await?; + if self.plugin.has_func("native_uninstall") { debug!(tool = self.id.as_str(), "Uninstalling tool natively"); @@ -798,6 +842,12 @@ impl Tool { fs::remove_dir_all(install_dir)?; + self.on_uninstalled + .emit(UninstalledEvent { + version: self.get_resolved_version(), + }) + .await?; + debug!(tool = self.id.as_str(), "Successfully uninstalled tool"); Ok(true) @@ -828,6 +878,12 @@ impl Tool { ))?; } + self.on_uninstalled_global + .emit(UninstalledGlobalEvent { + dependency: dependency.to_owned(), + }) + .await?; + Ok(result.uninstalled) } @@ -963,11 +1019,19 @@ impl Tool { /// If find only is enabled, will only check if they exist, and not create. pub async fn create_shims(&self, find_only: bool) -> miette::Result<()> { let mut primary_context = self.create_shim_context(); + let mut shim_event = CreatedShimsEvent { + global: vec![], + local: vec![], + }; // If not configured from the plugin, always create the primary global if !self.plugin.has_func("create_shims") { create_global_shim(&self.proto, primary_context, find_only)?; + shim_event.global.push(self.id.to_string()); + + self.on_created_shims.emit(shim_event).await?; + return Ok(()); } @@ -986,6 +1050,7 @@ impl Tool { if !shim_configs.no_primary_global { create_global_shim(&self.proto, primary_context, find_only)?; + shim_event.global.push(self.id.to_string()); } // Create alternate/secondary global shims @@ -997,6 +1062,7 @@ impl Tool { context.after_args = config.after_args.as_deref(); create_global_shim(&self.proto, context, find_only)?; + shim_event.global.push(name.to_owned()); } // Create local shims @@ -1015,8 +1081,11 @@ impl Tool { context.after_args = config.after_args.as_deref(); create_local_shim(context, find_only)?; + shim_event.local.push(name.to_owned()); } + self.on_created_shims.emit(shim_event).await?; + Ok(()) } } @@ -1025,12 +1094,9 @@ impl Tool { impl Tool { fn is_installed(&self) -> bool { - if let Some(AliasOrVersion::Version(version)) = &self.version { - return self.manifest.installed_versions.contains(version) - && self.get_tool_dir().exists(); - } + let dir = self.get_tool_dir(); - false + dir.exists() // && !dir.join(fs::LOCK_NAME).exists() } /// Return true if the tool has been setup (installed and binaries are located). From 31fbd68a01eed54e134bf3cc8e6fec87936045c0 Mon Sep 17 00:00:00 2001 From: Miles Johnson Date: Wed, 6 Sep 2023 15:27:20 -0700 Subject: [PATCH 2/4] Add version events. --- crates/core/src/events.rs | 7 ++++++- crates/core/src/tool.rs | 22 ++++++++++++++++++++-- crates/pdk/src/helpers.rs | 12 +++++------- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/crates/core/src/events.rs b/crates/core/src/events.rs index ef9b31d68..60a0a0131 100644 --- a/crates/core/src/events.rs +++ b/crates/core/src/events.rs @@ -1,4 +1,4 @@ -use crate::version::AliasOrVersion; +use crate::version::*; use starbase_events::Event; macro_rules! impl_event { @@ -43,3 +43,8 @@ impl_event!(CreatedShimsEvent, { pub global: Vec, pub local: Vec, }); + +impl_event!(ResolvedVersionEvent, { + pub candidate: VersionType, + pub version: AliasOrVersion, +}); diff --git a/crates/core/src/tool.rs b/crates/core/src/tool.rs index e8adc42b6..fafe7bfaa 100644 --- a/crates/core/src/tool.rs +++ b/crates/core/src/tool.rs @@ -43,6 +43,7 @@ pub struct Tool { pub on_installing: Emitter, pub on_installed: Emitter, pub on_installed_global: Emitter, + pub on_resolved_version: Emitter, pub on_uninstalling: Emitter, pub on_uninstalled: Emitter, pub on_uninstalled_global: Emitter, @@ -100,6 +101,7 @@ impl Tool { on_installing: Emitter::new(), on_installed: Emitter::new(), on_installed_global: Emitter::new(), + on_resolved_version: Emitter::new(), on_uninstalling: Emitter::new(), on_uninstalled: Emitter::new(), on_uninstalled_global: Emitter::new(), @@ -420,7 +422,16 @@ impl Tool { // If offline but we have a fully qualified semantic version, // exit early and assume the version is legitimate! if is_offline() && matches!(initial_version, VersionType::Version(_)) { - self.version = Some(initial_version.to_explicit_version()); + let version = initial_version.to_explicit_version(); + + self.on_resolved_version + .emit(ResolvedVersionEvent { + candidate: initial_version.to_owned(), + version: version.clone(), + }) + .await?; + + self.version = Some(version); return Ok(()); } @@ -479,6 +490,13 @@ impl Tool { version ); + self.on_resolved_version + .emit(ResolvedVersionEvent { + candidate: initial_version.to_owned(), + version: version.clone(), + }) + .await?; + self.version = Some(version); Ok(()) @@ -1096,7 +1114,7 @@ impl Tool { fn is_installed(&self) -> bool { let dir = self.get_tool_dir(); - dir.exists() // && !dir.join(fs::LOCK_NAME).exists() + dir.exists() && !dir.join(".lock").exists() } /// Return true if the tool has been setup (installed and binaries are located). diff --git a/crates/pdk/src/helpers.rs b/crates/pdk/src/helpers.rs index c9938b7be..3d89f622f 100644 --- a/crates/pdk/src/helpers.rs +++ b/crates/pdk/src/helpers.rs @@ -156,13 +156,11 @@ pub fn get_target_triple(env: &HostEnvironment, name: &str) -> Result Ok(format!("{}-apple-darwin", env.arch.to_rust_arch())), HostOS::Windows => Ok(format!("{}-pc-windows-msvc", env.arch.to_rust_arch())), - _ => { - return Err(PluginError::UnsupportedTarget { - tool: name.into(), - arch: env.arch.to_string(), - os: env.os.to_string(), - }) - } + _ => Err(PluginError::UnsupportedTarget { + tool: name.into(), + arch: env.arch.to_string(), + os: env.os.to_string(), + }), } } From d9c193d0171cefe358df2e409687e8aa72b84e4a Mon Sep 17 00:00:00 2001 From: Miles Johnson Date: Wed, 6 Sep 2023 15:33:43 -0700 Subject: [PATCH 3/4] Rework loader. --- crates/core/src/proto.rs | 13 +++++++++++++ crates/core/src/tool_loader.rs | 14 ++++++++------ crates/warpgate/src/loader.rs | 1 + 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/crates/core/src/proto.rs b/crates/core/src/proto.rs index c70ce3233..a36c16432 100644 --- a/crates/core/src/proto.rs +++ b/crates/core/src/proto.rs @@ -1,6 +1,8 @@ use crate::helpers::{get_home_dir, get_proto_home}; +use once_cell::sync::OnceCell; use std::env; use std::path::{Path, PathBuf}; +use warpgate::PluginLoader; #[derive(Clone, Debug)] pub struct ProtoEnvironment { @@ -11,6 +13,8 @@ pub struct ProtoEnvironment { pub tools_dir: PathBuf, pub home: PathBuf, // ~ pub root: PathBuf, // ~/.proto + + loader: OnceCell, } impl ProtoEnvironment { @@ -36,6 +40,15 @@ impl ProtoEnvironment { tools_dir: root.join("tools"), home: get_home_dir()?, root: root.to_owned(), + loader: OnceCell::new(), + }) + } + + pub fn create_plugin_loader(&self) -> &PluginLoader { + self.loader.get_or_init(|| { + let mut loader = PluginLoader::new(&self.plugins_dir, &self.temp_dir); + loader.set_seed(env!("CARGO_PKG_VERSION")); + loader }) } } diff --git a/crates/core/src/tool_loader.rs b/crates/core/src/tool_loader.rs index 73860d7dd..3c2d4546e 100644 --- a/crates/core/src/tool_loader.rs +++ b/crates/core/src/tool_loader.rs @@ -14,7 +14,7 @@ use std::{ path::Path, }; use tracing::debug; -use warpgate::{to_virtual_path, Id, PluginLoader, PluginLocator}; +use warpgate::{to_virtual_path, Id, PluginLocator}; pub fn inject_default_manifest_config( id: &Id, @@ -60,10 +60,8 @@ pub async fn load_tool_from_locator( let proto = proto.as_ref(); let locator = locator.as_ref(); - let mut loader = PluginLoader::new(&proto.plugins_dir, &proto.temp_dir); - loader.set_seed(env!("CARGO_PKG_VERSION")); - - let plugin_path = loader.load_plugin(&id, locator).await?; + let plugin_loader = proto.create_plugin_loader(); + let plugin_path = plugin_loader.load_plugin(&id, locator).await?; // If a TOML plugin, we need to load the WASM plugin for it, // wrap it, and modify the plugin manifest. @@ -76,7 +74,11 @@ pub async fn load_tool_from_locator( let mut manifest = Tool::create_plugin_manifest( proto, - Wasm::file(loader.load_plugin(id, ToolsConfig::schema_plugin()).await?), + Wasm::file( + plugin_loader + .load_plugin(id, ToolsConfig::schema_plugin()) + .await?, + ), )?; manifest diff --git a/crates/warpgate/src/loader.rs b/crates/warpgate/src/loader.rs index 843247da4..5f76ce7a3 100644 --- a/crates/warpgate/src/loader.rs +++ b/crates/warpgate/src/loader.rs @@ -16,6 +16,7 @@ use tracing::trace; /// A system for loading plugins from a locator strategy, /// and caching the `.wasm` file to the host's file system. +#[derive(Clone, Debug)] pub struct PluginLoader { /// Location where downloaded `.wasm` plugins are stored. plugins_dir: PathBuf, From 6f09bf781f2fb2f479ba3ecd53cf5aa68aac0b92 Mon Sep 17 00:00:00 2001 From: Miles Johnson Date: Wed, 6 Sep 2023 15:34:10 -0700 Subject: [PATCH 4/4] Rename method. --- crates/core/src/proto.rs | 2 +- crates/core/src/tool_loader.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/core/src/proto.rs b/crates/core/src/proto.rs index a36c16432..56e123ff7 100644 --- a/crates/core/src/proto.rs +++ b/crates/core/src/proto.rs @@ -44,7 +44,7 @@ impl ProtoEnvironment { }) } - pub fn create_plugin_loader(&self) -> &PluginLoader { + pub fn get_plugin_loader(&self) -> &PluginLoader { self.loader.get_or_init(|| { let mut loader = PluginLoader::new(&self.plugins_dir, &self.temp_dir); loader.set_seed(env!("CARGO_PKG_VERSION")); diff --git a/crates/core/src/tool_loader.rs b/crates/core/src/tool_loader.rs index 3c2d4546e..fdb25df60 100644 --- a/crates/core/src/tool_loader.rs +++ b/crates/core/src/tool_loader.rs @@ -60,7 +60,7 @@ pub async fn load_tool_from_locator( let proto = proto.as_ref(); let locator = locator.as_ref(); - let plugin_loader = proto.create_plugin_loader(); + let plugin_loader = proto.get_plugin_loader(); let plugin_path = plugin_loader.load_plugin(&id, locator).await?; // If a TOML plugin, we need to load the WASM plugin for it,