mirror of
https://github.com/lune-org/lune.git
synced 2025-05-04 10:43:57 +01:00
Bye bye tokio
This commit is contained in:
parent
62910f02ab
commit
39f6319bdb
14 changed files with 226 additions and 581 deletions
602
Cargo.lock
generated
602
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -28,9 +28,9 @@ futures = { version = "0.3", default-features = false, features = ["std"] }
|
||||||
futures-lite = "2.6"
|
futures-lite = "2.6"
|
||||||
futures-rustls = "0.26"
|
futures-rustls = "0.26"
|
||||||
http-body-util = "0.1"
|
http-body-util = "0.1"
|
||||||
hyper = { version = "1.6", features = ["http1", "client", "server"] }
|
hyper = { version = "1.6", default-features = false, features = ["http1", "client", "server"] }
|
||||||
pin-project-lite = "0.2"
|
pin-project-lite = "0.2"
|
||||||
rustls = "0.23"
|
rustls = { version = "0.23", default-features = false, features = ["std", "tls12", "ring"] }
|
||||||
rustls-pki-types = "1.11"
|
rustls-pki-types = "1.11"
|
||||||
url = "2.5"
|
url = "2.5"
|
||||||
urlencoding = "2.1"
|
urlencoding = "2.1"
|
||||||
|
|
|
@ -26,7 +26,7 @@ std-luau = ["dep:lune-std", "lune-std/luau"]
|
||||||
std-net = ["dep:lune-std", "lune-std/net"]
|
std-net = ["dep:lune-std", "lune-std/net"]
|
||||||
std-process = ["dep:lune-std", "lune-std/process"]
|
std-process = ["dep:lune-std", "lune-std/process"]
|
||||||
std-regex = ["dep:lune-std", "lune-std/regex"]
|
std-regex = ["dep:lune-std", "lune-std/regex"]
|
||||||
std-roblox = ["dep:lune-std", "lune-std/roblox", "dep:lune-roblox"]
|
std-roblox = ["dep:lune-std", "lune-std/roblox"]
|
||||||
std-serde = ["dep:lune-std", "lune-std/serde"]
|
std-serde = ["dep:lune-std", "lune-std/serde"]
|
||||||
std-stdio = ["dep:lune-std", "lune-std/stdio"]
|
std-stdio = ["dep:lune-std", "lune-std/stdio"]
|
||||||
std-task = ["dep:lune-std", "lune-std/task"]
|
std-task = ["dep:lune-std", "lune-std/task"]
|
||||||
|
@ -57,20 +57,20 @@ anyhow = "1.0"
|
||||||
console = "0.15"
|
console = "0.15"
|
||||||
dialoguer = "0.11"
|
dialoguer = "0.11"
|
||||||
directories = "6.0"
|
directories = "6.0"
|
||||||
futures-util = "0.3"
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
|
|
||||||
|
async-io = "2.4"
|
||||||
|
async-fs = "2.1"
|
||||||
|
blocking = "1.6"
|
||||||
|
futures-lite = "2.6"
|
||||||
|
ureq = { version = "3.0", default-features = false, features = ["rustls", "gzip"] }
|
||||||
|
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
tokio = { version = "1", features = ["full"] }
|
|
||||||
reqwest = { version = "0.11", default-features = false, features = [
|
|
||||||
"rustls-tls",
|
|
||||||
] }
|
|
||||||
|
|
||||||
lune-std = { optional = true, version = "0.2.0", path = "../lune-std" }
|
lune-std = { optional = true, version = "0.2.0", path = "../lune-std" }
|
||||||
lune-roblox = { optional = true, version = "0.2.0", path = "../lune-roblox" }
|
|
||||||
lune-utils = { version = "0.2.0", path = "../lune-utils" }
|
lune-utils = { version = "0.2.0", path = "../lune-utils" }
|
||||||
|
|
||||||
### CLI
|
### CLI
|
||||||
|
|
|
@ -3,7 +3,8 @@ use std::{
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
};
|
};
|
||||||
|
|
||||||
use tokio::{fs, task};
|
use async_fs as fs;
|
||||||
|
use blocking::unblock;
|
||||||
|
|
||||||
use crate::standalone::metadata::CURRENT_EXE;
|
use crate::standalone::metadata::CURRENT_EXE;
|
||||||
|
|
||||||
|
@ -44,25 +45,30 @@ pub async fn get_or_download_base_executable(target: BuildTarget) -> BuildResult
|
||||||
// Try to request to download the zip file from the target url,
|
// Try to request to download the zip file from the target url,
|
||||||
// making sure transient errors are handled gracefully and
|
// making sure transient errors are handled gracefully and
|
||||||
// with a different error message than "not found"
|
// with a different error message than "not found"
|
||||||
let response = reqwest::get(release_url).await?;
|
let (res_status, res_body) = unblock(move || {
|
||||||
if !response.status().is_success() {
|
let mut res = ureq::get(release_url).call()?;
|
||||||
if response.status().as_u16() == 404 {
|
let body = res.body_mut().read_to_vec()?;
|
||||||
|
Ok::<_, BuildError>((res.status(), body))
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if !res_status.is_success() {
|
||||||
|
if res_status.as_u16() == 404 {
|
||||||
return Err(BuildError::ReleaseTargetNotFound(target));
|
return Err(BuildError::ReleaseTargetNotFound(target));
|
||||||
}
|
}
|
||||||
return Err(BuildError::Download(
|
return Err(BuildError::Download(ureq::Error::StatusCode(
|
||||||
response.error_for_status().unwrap_err(),
|
res_status.as_u16(),
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receive the full zip file
|
// Start reading the zip file
|
||||||
let zip_bytes = response.bytes().await?.to_vec();
|
let zip_file = Cursor::new(res_body);
|
||||||
let zip_file = Cursor::new(zip_bytes);
|
|
||||||
|
|
||||||
// Look for and extract the binary file from the zip file
|
// Look for and extract the binary file from the zip file
|
||||||
// NOTE: We use spawn_blocking here since reading a zip
|
// NOTE: We use spawn_blocking here since reading a zip
|
||||||
// archive is a somewhat slow / blocking operation
|
// archive is a somewhat slow / blocking operation
|
||||||
let binary_file_name = format!("lune{}", target.exe_suffix());
|
let binary_file_name = format!("lune{}", target.exe_suffix());
|
||||||
let binary_file_handle = task::spawn_blocking(move || {
|
let binary_file_handle = unblock(move || {
|
||||||
let mut archive = zip::ZipArchive::new(zip_file)?;
|
let mut archive = zip::ZipArchive::new(zip_file)?;
|
||||||
|
|
||||||
let mut binary = Vec::new();
|
let mut binary = Vec::new();
|
||||||
|
@ -73,7 +79,7 @@ pub async fn get_or_download_base_executable(target: BuildTarget) -> BuildResult
|
||||||
|
|
||||||
Ok::<_, BuildError>(binary)
|
Ok::<_, BuildError>(binary)
|
||||||
});
|
});
|
||||||
let binary_file_contents = binary_file_handle.await??;
|
let binary_file_contents = binary_file_handle.await?;
|
||||||
|
|
||||||
// Finally, write the extracted binary to the cache
|
// Finally, write the extracted binary to the cache
|
||||||
if !CACHE_DIR.exists() {
|
if !CACHE_DIR.exists() {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use tokio::{fs, io::AsyncWriteExt};
|
use async_fs as fs;
|
||||||
|
use futures_lite::prelude::*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Removes the source file extension from the given path, if it has one.
|
Removes the source file extension from the given path, if it has one.
|
||||||
|
@ -32,6 +33,7 @@ pub async fn write_executable_file_to(
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
|
use fs::unix::OpenOptionsExt;
|
||||||
options.mode(0o755); // Read & execute for all, write for owner
|
options.mode(0o755); // Read & execute for all, write for owner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use std::{path::PathBuf, process::ExitCode};
|
use std::{path::PathBuf, process::ExitCode};
|
||||||
|
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
|
use async_fs as fs;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use console::style;
|
use console::style;
|
||||||
use tokio::fs;
|
|
||||||
|
|
||||||
use crate::standalone::metadata::Metadata;
|
use crate::standalone::metadata::Metadata;
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,9 @@ pub enum BuildError {
|
||||||
#[error("failed to find lune binary '{0}' in downloaded zip file")]
|
#[error("failed to find lune binary '{0}' in downloaded zip file")]
|
||||||
ZippedBinaryNotFound(String),
|
ZippedBinaryNotFound(String),
|
||||||
#[error("failed to download lune binary: {0}")]
|
#[error("failed to download lune binary: {0}")]
|
||||||
Download(#[from] reqwest::Error),
|
Download(#[from] ureq::Error),
|
||||||
#[error("failed to unzip lune binary: {0}")]
|
#[error("failed to unzip lune binary: {0}")]
|
||||||
Unzip(#[from] zip::result::ZipError),
|
Unzip(#[from] zip::result::ZipError),
|
||||||
#[error("panicked while unzipping lune binary: {0}")]
|
|
||||||
UnzipJoin(#[from] tokio::task::JoinError),
|
|
||||||
#[error("io error: {0}")]
|
#[error("io error: {0}")]
|
||||||
IoError(#[from] std::io::Error),
|
IoError(#[from] std::io::Error),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{path::PathBuf, process::ExitCode};
|
use std::{path::PathBuf, process::ExitCode};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
use async_fs as fs;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use directories::UserDirs;
|
use directories::UserDirs;
|
||||||
use rustyline::{error::ReadlineError, DefaultEditor};
|
use rustyline::{error::ReadlineError, DefaultEditor};
|
||||||
|
@ -28,7 +29,7 @@ impl ReplCommand {
|
||||||
.home_dir()
|
.home_dir()
|
||||||
.join(".lune_history");
|
.join(".lune_history");
|
||||||
if !history_file_path.exists() {
|
if !history_file_path.exists() {
|
||||||
tokio::fs::write(history_file_path, &[]).await?;
|
fs::write(history_file_path, &[]).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut repl = DefaultEditor::new()?;
|
let mut repl = DefaultEditor::new()?;
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
use std::{env, process::ExitCode};
|
use std::{env, io::stdin, process::ExitCode};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
use async_fs::read as read_to_vec;
|
||||||
|
use blocking::Unblock;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use tokio::{
|
use futures_lite::prelude::*;
|
||||||
fs::read as read_to_vec,
|
|
||||||
io::{stdin, AsyncReadExt as _},
|
|
||||||
};
|
|
||||||
|
|
||||||
use lune::Runtime;
|
use lune::Runtime;
|
||||||
|
|
||||||
|
@ -27,7 +26,7 @@ impl RunCommand {
|
||||||
// (dash) as the script name to run to the cli
|
// (dash) as the script name to run to the cli
|
||||||
let (script_display_name, script_contents) = if &self.script_path == "-" {
|
let (script_display_name, script_contents) = if &self.script_path == "-" {
|
||||||
let mut stdin_contents = Vec::new();
|
let mut stdin_contents = Vec::new();
|
||||||
stdin()
|
Unblock::new(stdin())
|
||||||
.read_to_end(&mut stdin_contents)
|
.read_to_end(&mut stdin_contents)
|
||||||
.await
|
.await
|
||||||
.context("Failed to read script contents from stdin")?;
|
.context("Failed to read script contents from stdin")?;
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
use std::{borrow::BorrowMut, env::current_dir, io::ErrorKind, path::PathBuf, process::ExitCode};
|
use std::{borrow::BorrowMut, env::current_dir, io::ErrorKind, path::PathBuf, process::ExitCode};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
use async_fs as fs;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use directories::UserDirs;
|
use directories::UserDirs;
|
||||||
use futures_util::future::try_join_all;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::fs;
|
|
||||||
|
|
||||||
// TODO: Use a library that supports json with comments since VSCode settings may contain comments
|
// TODO: Use a library that supports json with comments since VSCode settings may contain comments
|
||||||
use serde_json::Value as JsonValue;
|
use serde_json::Value as JsonValue;
|
||||||
|
@ -157,16 +156,12 @@ async fn generate_typedef_files_from_definitions() -> Result<String> {
|
||||||
files_to_write.push((name, path, builtin.typedefs()));
|
files_to_write.push((name, path, builtin.typedefs()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write all dirs and files only when we know generation was successful
|
// Write all dirs and files
|
||||||
let futs_dirs = dirs_to_write
|
for dir in dirs_to_write {
|
||||||
.drain(..)
|
fs::create_dir_all(dir).await?;
|
||||||
.map(fs::create_dir_all)
|
}
|
||||||
.collect::<Vec<_>>();
|
for (_name, path, contents) in files_to_write {
|
||||||
let futs_files = files_to_write
|
fs::write(path, contents).await?;
|
||||||
.iter()
|
}
|
||||||
.map(|(_, path, contents)| fs::write(path, contents))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
try_join_all(futs_dirs).await?;
|
|
||||||
try_join_all(futs_files).await?;
|
|
||||||
Ok(version_string.to_string())
|
Ok(version_string.to_string())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
#![allow(clippy::match_same_arms)]
|
#![allow(clippy::match_same_arms)]
|
||||||
|
|
||||||
use std::{cmp::Ordering, ffi::OsStr, fmt::Write as _, path::PathBuf, sync::LazyLock};
|
use std::{
|
||||||
|
cmp::Ordering, ffi::OsStr, fmt::Write as _, io::ErrorKind, path::PathBuf, sync::LazyLock,
|
||||||
|
};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
|
use async_fs as fs;
|
||||||
use console::Style;
|
use console::Style;
|
||||||
use directories::UserDirs;
|
use directories::UserDirs;
|
||||||
use tokio::{fs, io};
|
use futures_lite::prelude::*;
|
||||||
|
|
||||||
use super::files::{discover_script_path, parse_lune_description_from_file};
|
use super::files::{discover_script_path, parse_lune_description_from_file};
|
||||||
|
|
||||||
|
@ -25,7 +28,7 @@ pub async fn find_lune_scripts(in_home_dir: bool) -> Result<Vec<(String, String)
|
||||||
match lune_dir {
|
match lune_dir {
|
||||||
Ok(mut dir) => {
|
Ok(mut dir) => {
|
||||||
let mut files = Vec::new();
|
let mut files = Vec::new();
|
||||||
while let Some(entry) = dir.next_entry().await? {
|
while let Some(entry) = dir.try_next().await? {
|
||||||
let meta = entry.metadata().await?;
|
let meta = entry.metadata().await?;
|
||||||
if meta.is_file() {
|
if meta.is_file() {
|
||||||
let contents = fs::read(entry.path()).await?;
|
let contents = fs::read(entry.path()).await?;
|
||||||
|
@ -77,7 +80,7 @@ pub async fn find_lune_scripts(in_home_dir: bool) -> Result<Vec<(String, String)
|
||||||
.collect();
|
.collect();
|
||||||
Ok(parsed)
|
Ok(parsed)
|
||||||
}
|
}
|
||||||
Err(e) if matches!(e.kind(), io::ErrorKind::NotFound) => {
|
Err(e) if matches!(e.kind(), ErrorKind::NotFound) => {
|
||||||
bail!("No lune directory was found.")
|
bail!("No lune directory was found.")
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
|
@ -9,8 +9,7 @@ pub(crate) mod standalone;
|
||||||
|
|
||||||
use lune_utils::fmt::Label;
|
use lune_utils::fmt::Label;
|
||||||
|
|
||||||
#[tokio::main(flavor = "multi_thread")]
|
fn main() -> ExitCode {
|
||||||
async fn main() -> ExitCode {
|
|
||||||
tracing_subscriber::fmt()
|
tracing_subscriber::fmt()
|
||||||
.compact()
|
.compact()
|
||||||
.with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env())
|
.with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env())
|
||||||
|
@ -20,24 +19,26 @@ async fn main() -> ExitCode {
|
||||||
.with_writer(stderr)
|
.with_writer(stderr)
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
if let Some(bin) = standalone::check().await {
|
async_io::block_on(async {
|
||||||
return standalone::run(bin).await.unwrap();
|
if let Some(bin) = standalone::check().await {
|
||||||
}
|
return standalone::run(bin).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "cli")]
|
#[cfg(feature = "cli")]
|
||||||
{
|
{
|
||||||
match cli::Cli::new().run().await {
|
match cli::Cli::new().run().await {
|
||||||
Ok(code) => code,
|
Ok(code) => code,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("{}\n{err:?}", Label::Error);
|
eprintln!("{}\n{err:?}", Label::Error);
|
||||||
ExitCode::FAILURE
|
ExitCode::FAILURE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "cli"))]
|
#[cfg(not(feature = "cli"))]
|
||||||
{
|
{
|
||||||
eprintln!("{}\nCLI feature is disabled", Label::Error);
|
eprintln!("{}\nCLI feature is disabled", Label::Error);
|
||||||
ExitCode::FAILURE
|
ExitCode::FAILURE
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use std::{env, path::PathBuf, sync::LazyLock};
|
use std::{env, path::PathBuf, sync::LazyLock};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::{bail, Result};
|
||||||
|
use async_fs as fs;
|
||||||
use mlua::Compiler as LuaCompiler;
|
use mlua::Compiler as LuaCompiler;
|
||||||
use tokio::fs;
|
|
||||||
|
|
||||||
pub static CURRENT_EXE: LazyLock<PathBuf> =
|
pub static CURRENT_EXE: LazyLock<PathBuf> =
|
||||||
LazyLock::new(|| env::current_exe().expect("failed to get current exe"));
|
LazyLock::new(|| env::current_exe().expect("failed to get current exe"));
|
||||||
|
|
|
@ -3,9 +3,9 @@ use std::path::PathBuf;
|
||||||
use std::process::ExitCode;
|
use std::process::ExitCode;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use async_fs::read_to_string;
|
||||||
use console::set_colors_enabled;
|
use console::set_colors_enabled;
|
||||||
use console::set_colors_enabled_stderr;
|
use console::set_colors_enabled_stderr;
|
||||||
use tokio::fs::read_to_string;
|
|
||||||
|
|
||||||
use lune_utils::path::clean_path_and_make_absolute;
|
use lune_utils::path::clean_path_and_make_absolute;
|
||||||
|
|
||||||
|
@ -15,37 +15,39 @@ const ARGS: &[&str] = &["Foo", "Bar"];
|
||||||
|
|
||||||
macro_rules! create_tests {
|
macro_rules! create_tests {
|
||||||
($($name:ident: $value:expr,)*) => { $(
|
($($name:ident: $value:expr,)*) => { $(
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[test]
|
||||||
async fn $name() -> Result<ExitCode> {
|
fn $name() -> Result<ExitCode> {
|
||||||
// We need to change the current directory to the workspace root since
|
async_io::block_on(async {
|
||||||
// we are in a sub-crate and tests would run relative to the sub-crate
|
// We need to change the current directory to the workspace root since
|
||||||
let workspace_dir_str = format!("{}/../../", env!("CARGO_MANIFEST_DIR"));
|
// we are in a sub-crate and tests would run relative to the sub-crate
|
||||||
let workspace_dir = clean_path_and_make_absolute(PathBuf::from(workspace_dir_str));
|
let workspace_dir_str = format!("{}/../../", env!("CARGO_MANIFEST_DIR"));
|
||||||
set_current_dir(&workspace_dir)?;
|
let workspace_dir = clean_path_and_make_absolute(PathBuf::from(workspace_dir_str));
|
||||||
|
set_current_dir(&workspace_dir)?;
|
||||||
|
|
||||||
// Disable styling for stdout and stderr since
|
// Disable styling for stdout and stderr since
|
||||||
// some tests rely on output not being styled
|
// some tests rely on output not being styled
|
||||||
set_colors_enabled(false);
|
set_colors_enabled(false);
|
||||||
set_colors_enabled_stderr(false);
|
set_colors_enabled_stderr(false);
|
||||||
|
|
||||||
// The rest of the test logic can continue as normal
|
// The rest of the test logic can continue as normal
|
||||||
let full_name = format!("{}/tests/{}.luau", workspace_dir.display(), $value);
|
let full_name = format!("{}/tests/{}.luau", workspace_dir.display(), $value);
|
||||||
let script = read_to_string(&full_name).await?;
|
let script = read_to_string(&full_name).await?;
|
||||||
let mut lune = Runtime::new()?
|
let mut lune = Runtime::new()?
|
||||||
.with_jit(true)
|
.with_jit(true)
|
||||||
.with_args(
|
.with_args(
|
||||||
ARGS
|
ARGS
|
||||||
.clone()
|
.clone()
|
||||||
.iter()
|
.iter()
|
||||||
.map(ToString::to_string)
|
.map(ToString::to_string)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
);
|
);
|
||||||
let script_name = full_name
|
let script_name = full_name
|
||||||
.trim_end_matches(".luau")
|
.trim_end_matches(".luau")
|
||||||
.trim_end_matches(".lua")
|
.trim_end_matches(".lua")
|
||||||
.to_string();
|
.to_string();
|
||||||
let script_values = lune.run(&script_name, &script).await?;
|
let script_values = lune.run(&script_name, &script).await?;
|
||||||
Ok(ExitCode::from(script_values.status()))
|
Ok(ExitCode::from(script_values.status()))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
)* }
|
)* }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue