From 95245d211219c2ad660b85f7a241072c43c1ca13 Mon Sep 17 00:00:00 2001 From: Brett Mayson Date: Sat, 9 Nov 2024 03:59:26 +0000 Subject: [PATCH] hooks: ability to call scripts --- bin/src/commands/script.rs | 2 +- bin/src/modules/hook/libraries/hemtt.rs | 37 ++++++++++++++++++- bin/src/modules/hook/mod.rs | 27 ++++++++------ .../hooks/post_release/02_test_rhs.rhai | 4 ++ bin/tests/bravo/.hemtt/scripts/test.rhai | 1 + book/rhai/scripts/index.md | 22 +++++++++++ .../src/reporting/diagnostic/label.rs | 2 +- 7 files changed, 80 insertions(+), 15 deletions(-) diff --git a/bin/src/commands/script.rs b/bin/src/commands/script.rs index a0c40f4a..5be50380 100644 --- a/bin/src/commands/script.rs +++ b/bin/src/commands/script.rs @@ -30,5 +30,5 @@ pub fn execute(matches: &ArgMatches) -> Result { let name = matches .get_one::("name") .expect("name to be set as required"); - Hooks::run_file(&ctx, name) + Hooks::run_file(&ctx, name).map(|(report, _)| report) } diff --git a/bin/src/modules/hook/libraries/hemtt.rs b/bin/src/modules/hook/libraries/hemtt.rs index 2930df67..40a2bf9f 100644 --- a/bin/src/modules/hook/libraries/hemtt.rs +++ b/bin/src/modules/hook/libraries/hemtt.rs @@ -1,7 +1,7 @@ use hemtt_common::version::Version; use rhai::plugin::{ - export_module, Dynamic, FnNamespace, FuncRegistration, Module, NativeCallContext, PluginFunc, - RhaiResult, TypeId, + export_module, mem, Dynamic, FnNamespace, FuncRegistration, ImmutableString, Module, + NativeCallContext, PluginFunc, RhaiResult, TypeId, }; use crate::context::Context; @@ -11,6 +11,7 @@ use super::project::RhaiProject; #[allow(clippy::module_name_repetitions)] #[derive(Debug, Clone)] pub struct RhaiHemtt { + ctx: Context, version: Version, project: RhaiProject, folder: String, @@ -19,6 +20,7 @@ pub struct RhaiHemtt { impl RhaiHemtt { pub fn new(ctx: &Context) -> Self { Self { + ctx: ctx.clone(), version: Version::try_from(env!("HEMTT_VERSION")) .expect("hemtt version should be valid"), project: RhaiProject::new(ctx), @@ -31,6 +33,14 @@ impl RhaiHemtt { #[allow(clippy::unwrap_used)] // coming from rhai codegen #[export_module] pub mod project_functions { + use rhai::EvalAltResult; + + use crate::{ + modules::{hook::error::bhe1_script_not_found::ScriptNotFound, Hooks}, + report::Report, + Error, + }; + #[rhai_fn(global, pure)] pub fn version(hemtt: &mut RhaiHemtt) -> Version { hemtt.version.clone() @@ -65,4 +75,27 @@ pub mod project_functions { pub fn is_release(hemtt: &mut RhaiHemtt) -> bool { hemtt.folder == "release" } + + #[rhai_fn(global, pure, return_raw)] + pub fn script(hemtt: &mut RhaiHemtt, name: &str) -> Result> { + fn inner_script(hemtt: &mut RhaiHemtt, name: &str) -> Result<(Report, Dynamic), Error> { + let scripts = hemtt.ctx.workspace_path().join(".hemtt")?.join("scripts")?; + let path = scripts.join(name)?.with_extension("rhai")?; + trace!("running script: {}", path.as_str()); + if !path.exists()? { + return Ok(( + { + let mut report = Report::new(); + report.push(ScriptNotFound::code(name.to_owned(), &scripts)?); + report + }, + Dynamic::UNIT, + )); + } + Hooks::run(&hemtt.ctx, path, false) + } + inner_script(hemtt, name) + .map_err(|e| e.to_string().into()) + .map(|(_, d)| d) + } } diff --git a/bin/src/modules/hook/mod.rs b/bin/src/modules/hook/mod.rs index 42f94852..035b3a27 100644 --- a/bin/src/modules/hook/mod.rs +++ b/bin/src/modules/hook/mod.rs @@ -2,6 +2,7 @@ use std::sync::{Arc, Mutex}; use ::rhai::{packages::Package, Engine, Scope}; use hemtt_workspace::WorkspacePath; +use rhai::Dynamic; use crate::{context::Context, error::Error, report::Report}; @@ -102,7 +103,7 @@ impl Hooks { "Running hook: {}", file.as_str().trim_start_matches("/.hemtt/hooks/") ); - report.merge(Self::run(ctx, file, vfs)?); + report.merge(Self::run(ctx, file, vfs)?.0); ctx.config().version().invalidate(); } Ok(report) @@ -117,14 +118,14 @@ impl Hooks { /// /// # Panics /// If a file path is not a valid [`OsStr`] (UTF-8) - pub fn run_file(ctx: &Context, name: &str) -> Result { + pub fn run_file(ctx: &Context, name: &str) -> Result<(Report, Dynamic), Error> { let mut report = Report::new(); let scripts = ctx.workspace_path().join(".hemtt")?.join("scripts")?; let path = scripts.join(name)?.with_extension("rhai")?; trace!("running script: {}", path.as_str()); if !path.exists()? { report.push(ScriptNotFound::code(name.to_owned(), &scripts)?); - return Ok(report); + return Ok((report, Dynamic::UNIT)); } let res = Self::run(ctx, path, false); ctx.config().version().invalidate(); @@ -132,7 +133,7 @@ impl Hooks { } #[allow(clippy::needless_pass_by_value)] // rhai things - fn run(ctx: &Context, path: WorkspacePath, vfs: bool) -> Result { + fn run(ctx: &Context, path: WorkspacePath, vfs: bool) -> Result<(Report, Dynamic), Error> { let mut report = Report::new(); let mut engine = engine(vfs); let mut scope = scope(ctx, vfs)?; @@ -171,14 +172,18 @@ impl Hooks { .lock() .expect("told_to_fail mutex poisoned") = true; }); - if let Err(e) = engine.run_with_scope(&mut scope, &path.read_to_string()?) { - report.push(RuntimeError::code(path, &e)); - return Ok(report); - } - if *told_to_fail.lock().expect("told_to_fail mutex poisoned") { - report.push(ScriptFatal::code(name)); + match engine.eval_with_scope(&mut scope, &path.read_to_string()?) { + Err(e) => { + report.push(RuntimeError::code(path, &e)); + Ok((report, Dynamic::UNIT)) + } + Ok(ret) => { + if *told_to_fail.lock().expect("told_to_fail mutex poisoned") { + report.push(ScriptFatal::code(name)); + } + Ok((report, ret)) + } } - Ok(report) } } diff --git a/bin/tests/bravo/.hemtt/hooks/post_release/02_test_rhs.rhai b/bin/tests/bravo/.hemtt/hooks/post_release/02_test_rhs.rhai index 044b4236..3ffd7a2d 100644 --- a/bin/tests/bravo/.hemtt/hooks/post_release/02_test_rhs.rhai +++ b/bin/tests/bravo/.hemtt/hooks/post_release/02_test_rhs.rhai @@ -11,3 +11,7 @@ if !include.is_file() { if include.is_dir() { fatal("{} is a directory", include); } + +if HEMTT.script("test") != 42 { + fatal("HEMTT.script(\"test\") != 42"); +} diff --git a/bin/tests/bravo/.hemtt/scripts/test.rhai b/bin/tests/bravo/.hemtt/scripts/test.rhai index 4a963672..b6931986 100644 --- a/bin/tests/bravo/.hemtt/scripts/test.rhai +++ b/bin/tests/bravo/.hemtt/scripts/test.rhai @@ -1,3 +1,4 @@ print("Just a test"); print(date("[year]-[month]-[day] [hour]:[minute]:[second]")); print(date("[year repr:last_two][month][day]")); +42 diff --git a/book/rhai/scripts/index.md b/book/rhai/scripts/index.md index fc0adbba..43449e83 100644 --- a/book/rhai/scripts/index.md +++ b/book/rhai/scripts/index.md @@ -7,3 +7,25 @@ The files are located in the `.hemtt/scripts` folder, and are written in [Rhai]( They have access to all the same [libraries](../library/index.md) as [hooks](../hooks.md), but only use the [real file system](../library/filesystem.md#hemtt_rfs---real-file-system), since they run outside of the build process. Scripts are useful for automating tasks that are not part of the build process, such as creating a new addon, or updating the version number. + +## Calling from Hooks + +Scripts can be called from hooks using `HEMTT.script(