Bye bye tokio

This commit is contained in:
Filip Tibell 2025-04-29 15:38:04 +02:00
parent 62910f02ab
commit 39f6319bdb
No known key found for this signature in database
14 changed files with 226 additions and 581 deletions

602
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -28,9 +28,9 @@ futures = { version = "0.3", default-features = false, features = ["std"] }
futures-lite = "2.6"
futures-rustls = "0.26"
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"
rustls = "0.23"
rustls = { version = "0.23", default-features = false, features = ["std", "tls12", "ring"] }
rustls-pki-types = "1.11"
url = "2.5"
urlencoding = "2.1"

View file

@ -26,7 +26,7 @@ std-luau = ["dep:lune-std", "lune-std/luau"]
std-net = ["dep:lune-std", "lune-std/net"]
std-process = ["dep:lune-std", "lune-std/process"]
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-stdio = ["dep:lune-std", "lune-std/stdio"]
std-task = ["dep:lune-std", "lune-std/task"]
@ -57,20 +57,20 @@ anyhow = "1.0"
console = "0.15"
dialoguer = "0.11"
directories = "6.0"
futures-util = "0.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.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-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-roblox = { optional = true, version = "0.2.0", path = "../lune-roblox" }
lune-utils = { version = "0.2.0", path = "../lune-utils" }
### CLI

View file

@ -3,7 +3,8 @@ use std::{
path::PathBuf,
};
use tokio::{fs, task};
use async_fs as fs;
use blocking::unblock;
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,
// making sure transient errors are handled gracefully and
// with a different error message than "not found"
let response = reqwest::get(release_url).await?;
if !response.status().is_success() {
if response.status().as_u16() == 404 {
let (res_status, res_body) = unblock(move || {
let mut res = ureq::get(release_url).call()?;
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::Download(
response.error_for_status().unwrap_err(),
));
return Err(BuildError::Download(ureq::Error::StatusCode(
res_status.as_u16(),
)));
}
// Receive the full zip file
let zip_bytes = response.bytes().await?.to_vec();
let zip_file = Cursor::new(zip_bytes);
// Start reading the zip file
let zip_file = Cursor::new(res_body);
// Look for and extract the binary file from the zip file
// NOTE: We use spawn_blocking here since reading a zip
// archive is a somewhat slow / blocking operation
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 binary = Vec::new();
@ -73,7 +79,7 @@ pub async fn get_or_download_base_executable(target: BuildTarget) -> BuildResult
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
if !CACHE_DIR.exists() {

View file

@ -1,7 +1,8 @@
use std::path::{Path, PathBuf};
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.
@ -32,6 +33,7 @@ pub async fn write_executable_file_to(
#[cfg(unix)]
{
use fs::unix::OpenOptionsExt;
options.mode(0o755); // Read & execute for all, write for owner
}

View file

@ -1,9 +1,9 @@
use std::{path::PathBuf, process::ExitCode};
use anyhow::{bail, Context, Result};
use async_fs as fs;
use clap::Parser;
use console::style;
use tokio::fs;
use crate::standalone::metadata::Metadata;

View file

@ -12,11 +12,9 @@ pub enum BuildError {
#[error("failed to find lune binary '{0}' in downloaded zip file")]
ZippedBinaryNotFound(String),
#[error("failed to download lune binary: {0}")]
Download(#[from] reqwest::Error),
Download(#[from] ureq::Error),
#[error("failed to unzip lune binary: {0}")]
Unzip(#[from] zip::result::ZipError),
#[error("panicked while unzipping lune binary: {0}")]
UnzipJoin(#[from] tokio::task::JoinError),
#[error("io error: {0}")]
IoError(#[from] std::io::Error),
}

View file

@ -1,6 +1,7 @@
use std::{path::PathBuf, process::ExitCode};
use anyhow::{Context, Result};
use async_fs as fs;
use clap::Parser;
use directories::UserDirs;
use rustyline::{error::ReadlineError, DefaultEditor};
@ -28,7 +29,7 @@ impl ReplCommand {
.home_dir()
.join(".lune_history");
if !history_file_path.exists() {
tokio::fs::write(history_file_path, &[]).await?;
fs::write(history_file_path, &[]).await?;
}
let mut repl = DefaultEditor::new()?;

View file

@ -1,11 +1,10 @@
use std::{env, process::ExitCode};
use std::{env, io::stdin, process::ExitCode};
use anyhow::{Context, Result};
use async_fs::read as read_to_vec;
use blocking::Unblock;
use clap::Parser;
use tokio::{
fs::read as read_to_vec,
io::{stdin, AsyncReadExt as _},
};
use futures_lite::prelude::*;
use lune::Runtime;
@ -27,7 +26,7 @@ impl RunCommand {
// (dash) as the script name to run to the cli
let (script_display_name, script_contents) = if &self.script_path == "-" {
let mut stdin_contents = Vec::new();
stdin()
Unblock::new(stdin())
.read_to_end(&mut stdin_contents)
.await
.context("Failed to read script contents from stdin")?;

View file

@ -1,11 +1,10 @@
use std::{borrow::BorrowMut, env::current_dir, io::ErrorKind, path::PathBuf, process::ExitCode};
use anyhow::{Context, Result};
use async_fs as fs;
use clap::Parser;
use directories::UserDirs;
use futures_util::future::try_join_all;
use thiserror::Error;
use tokio::fs;
// TODO: Use a library that supports json with comments since VSCode settings may contain comments
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()));
}
// Write all dirs and files only when we know generation was successful
let futs_dirs = dirs_to_write
.drain(..)
.map(fs::create_dir_all)
.collect::<Vec<_>>();
let futs_files = files_to_write
.iter()
.map(|(_, path, contents)| fs::write(path, contents))
.collect::<Vec<_>>();
try_join_all(futs_dirs).await?;
try_join_all(futs_files).await?;
// Write all dirs and files
for dir in dirs_to_write {
fs::create_dir_all(dir).await?;
}
for (_name, path, contents) in files_to_write {
fs::write(path, contents).await?;
}
Ok(version_string.to_string())
}

View file

@ -1,11 +1,14 @@
#![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 async_fs as fs;
use console::Style;
use directories::UserDirs;
use tokio::{fs, io};
use futures_lite::prelude::*;
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 {
Ok(mut dir) => {
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?;
if meta.is_file() {
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();
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.")
}
Err(e) => {

View file

@ -9,8 +9,7 @@ pub(crate) mod standalone;
use lune_utils::fmt::Label;
#[tokio::main(flavor = "multi_thread")]
async fn main() -> ExitCode {
fn main() -> ExitCode {
tracing_subscriber::fmt()
.compact()
.with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env())
@ -20,24 +19,26 @@ async fn main() -> ExitCode {
.with_writer(stderr)
.init();
if let Some(bin) = standalone::check().await {
return standalone::run(bin).await.unwrap();
}
async_io::block_on(async {
if let Some(bin) = standalone::check().await {
return standalone::run(bin).await.unwrap();
}
#[cfg(feature = "cli")]
{
match cli::Cli::new().run().await {
Ok(code) => code,
Err(err) => {
eprintln!("{}\n{err:?}", Label::Error);
ExitCode::FAILURE
#[cfg(feature = "cli")]
{
match cli::Cli::new().run().await {
Ok(code) => code,
Err(err) => {
eprintln!("{}\n{err:?}", Label::Error);
ExitCode::FAILURE
}
}
}
}
#[cfg(not(feature = "cli"))]
{
eprintln!("{}\nCLI feature is disabled", Label::Error);
ExitCode::FAILURE
}
#[cfg(not(feature = "cli"))]
{
eprintln!("{}\nCLI feature is disabled", Label::Error);
ExitCode::FAILURE
}
})
}

View file

@ -1,8 +1,8 @@
use std::{env, path::PathBuf, sync::LazyLock};
use anyhow::{bail, Result};
use async_fs as fs;
use mlua::Compiler as LuaCompiler;
use tokio::fs;
pub static CURRENT_EXE: LazyLock<PathBuf> =
LazyLock::new(|| env::current_exe().expect("failed to get current exe"));

View file

@ -3,9 +3,9 @@ use std::path::PathBuf;
use std::process::ExitCode;
use anyhow::Result;
use async_fs::read_to_string;
use console::set_colors_enabled;
use console::set_colors_enabled_stderr;
use tokio::fs::read_to_string;
use lune_utils::path::clean_path_and_make_absolute;
@ -15,37 +15,39 @@ const ARGS: &[&str] = &["Foo", "Bar"];
macro_rules! create_tests {
($($name:ident: $value:expr,)*) => { $(
#[tokio::test(flavor = "multi_thread")]
async fn $name() -> Result<ExitCode> {
// We need to change the current directory to the workspace root since
// we are in a sub-crate and tests would run relative to the sub-crate
let workspace_dir_str = format!("{}/../../", env!("CARGO_MANIFEST_DIR"));
let workspace_dir = clean_path_and_make_absolute(PathBuf::from(workspace_dir_str));
set_current_dir(&workspace_dir)?;
#[test]
fn $name() -> Result<ExitCode> {
async_io::block_on(async {
// We need to change the current directory to the workspace root since
// we are in a sub-crate and tests would run relative to the sub-crate
let workspace_dir_str = format!("{}/../../", env!("CARGO_MANIFEST_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
// some tests rely on output not being styled
set_colors_enabled(false);
set_colors_enabled_stderr(false);
// Disable styling for stdout and stderr since
// some tests rely on output not being styled
set_colors_enabled(false);
set_colors_enabled_stderr(false);
// The rest of the test logic can continue as normal
let full_name = format!("{}/tests/{}.luau", workspace_dir.display(), $value);
let script = read_to_string(&full_name).await?;
let mut lune = Runtime::new()?
.with_jit(true)
.with_args(
ARGS
.clone()
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
);
let script_name = full_name
.trim_end_matches(".luau")
.trim_end_matches(".lua")
.to_string();
let script_values = lune.run(&script_name, &script).await?;
Ok(ExitCode::from(script_values.status()))
// The rest of the test logic can continue as normal
let full_name = format!("{}/tests/{}.luau", workspace_dir.display(), $value);
let script = read_to_string(&full_name).await?;
let mut lune = Runtime::new()?
.with_jit(true)
.with_args(
ARGS
.clone()
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
);
let script_name = full_name
.trim_end_matches(".luau")
.trim_end_matches(".lua")
.to_string();
let script_values = lune.run(&script_name, &script).await?;
Ok(ExitCode::from(script_values.status()))
})
}
)* }
}