Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Lua module API #201

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
members = [
"rocks-lib",
"rocks-bin",
# "rocks-lua",
]
resolver = "2"
exclude = [
"rocks-lua"
]
23 changes: 23 additions & 0 deletions rocks-lib/src/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub(crate) mod utils; // Make build utilities available as a submodule
use indicatif::style::TemplateError;
use luarocks::LuarocksBuildError;
use make::MakeError;
use mlua::{LuaSerdeExt, Value};
use rust_mlua::RustError;
use thiserror::Error;
use utils::recursive_copy_dir;
Expand Down Expand Up @@ -66,6 +67,28 @@ impl From<bool> for BuildBehaviour {
}
}

impl mlua::IntoLua for BuildBehaviour {
fn into_lua(
self,
lua: &mlua::prelude::Lua,
) -> mlua::prelude::LuaResult<mlua::prelude::LuaValue> {
lua.to_value(&match self {
Self::Force => true,
Self::NoForce => false,
})
}
}

impl mlua::FromLua for BuildBehaviour {
fn from_lua(value: mlua::prelude::LuaValue, _lua: &mlua::prelude::Lua) -> mlua::prelude::LuaResult<Self> {
if let Value::Boolean(b) = value {
Ok(Self::from(b))
} else {
Err(mlua::Error::FromLuaConversionError { from: value.type_name(), to: "buildbehaviour".into(), message: None })
}
}
}

async fn run_build(
rockspec: &Rockspec,
output_paths: &RockLayout,
Expand Down
105 changes: 103 additions & 2 deletions rocks-lib/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use directories::ProjectDirs;
use mlua::{ExternalResult, FromLua};
use std::{collections::HashMap, fmt::Display, io, path::PathBuf, str::FromStr, time::Duration};
use thiserror::Error;

Expand Down Expand Up @@ -134,7 +135,7 @@ impl Display for LuaVersion {
#[error("could not find a valid home directory")]
pub struct NoValidHomeDirectory;

#[derive(Debug, Clone)]
#[derive(Clone, Debug, FromLua)]
pub struct Config {
enable_development_rockspecs: bool,
server: String,
Expand All @@ -155,6 +156,25 @@ pub struct Config {
data_dir: PathBuf,
}

impl mlua::UserData for Config {
fn add_fields<F: mlua::prelude::LuaUserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_get("enable_development_rockspecs", |_lua, this| Ok(this.enable_development_rockspecs));
fields.add_field_method_get("server", |_lua, this| Ok(this.server.clone()));
fields.add_field_method_get("only_server", |_lua, this| Ok(this.only_server.clone()));
fields.add_field_method_get("only_sources", |_lua, this| Ok(this.only_sources.clone()));
fields.add_field_method_get("namespace", |_lua, this| Ok(this.namespace.clone()));
fields.add_field_method_get("lua_dir", |_lua, this| Ok(this.lua_dir.clone()));
fields.add_field_method_get("lua_version", |_lua, this| Ok(this.lua_version.clone().map(|v| v.to_string())));
fields.add_field_method_get("tree", |_lua, this| Ok(this.tree.clone()));
fields.add_field_method_get("no_project", |_lua, this| Ok(this.no_project));
fields.add_field_method_get("timeout", |_lua, this| Ok(this.timeout.as_secs()));
fields.add_field_method_get("make", |_lua, this| Ok(this.make.clone()));
fields.add_field_method_get("variables", |_lua, this| Ok(this.variables.clone()));
fields.add_field_method_get("cache_dir", |_lua, this| Ok(this.cache_dir.clone()));
fields.add_field_method_get("data_dir", |_lua, this| Ok(this.data_dir.clone()));
}
}

impl Config {
pub fn get_project_dirs() -> Result<ProjectDirs, NoValidHomeDirectory> {
directories::ProjectDirs::from("org", "neorocks", "rocks").ok_or(NoValidHomeDirectory)
Expand Down Expand Up @@ -264,7 +284,7 @@ pub enum ConfigError {
Project(#[from] ProjectError),
}

#[derive(Default)]
#[derive(Clone, Default)]
pub struct ConfigBuilder {
enable_development_rockspecs: Option<bool>,
server: Option<String>,
Expand Down Expand Up @@ -415,3 +435,84 @@ impl ConfigBuilder {
})
}
}

impl mlua::UserData for ConfigBuilder {
fn add_fields<F: mlua::prelude::LuaUserDataFields<Self>>(fields: &mut F) {
fields.add_field_method_set("enable_development_rockspecs", |_lua, this, enable_development_rockspecs| {
this.enable_development_rockspecs = enable_development_rockspecs;

Ok(())
});
fields.add_field_method_set("server", |_lua, this, server| {
this.server = server;

Ok(())
});
fields.add_field_method_set("only_server", |_lua, this, only_server| {
this.only_server = only_server;

Ok(())
});
fields.add_field_method_set("only_sources", |_lua, this, only_sources| {
this.only_sources = only_sources;

Ok(())
});
fields.add_field_method_set("namespace", |_lua, this, namespace| {
this.namespace = namespace;

Ok(())
});
fields.add_field_method_set("lua_dir", |_lua, this, lua_dir| {
this.lua_dir = lua_dir;

Ok(())
});
fields.add_field_method_set("lua_version", |_lua, this, lua_version: Option<String>| {
this.lua_version = lua_version.and_then(|v| v.parse().ok());

Ok(())
});
fields.add_field_method_set("tree", |_lua, this, tree| {
this.tree = tree;

Ok(())
});
fields.add_field_method_set("no_project", |_lua, this, no_project| {
this.no_project = no_project;

Ok(())
});
fields.add_field_method_set("timeout", |_lua, this, timeout: Option<_>| {
this.timeout = timeout.map(Duration::from_secs);

Ok(())
});
fields.add_field_method_set("make", |_lua, this, make| {
this.make = make;

Ok(())
});
fields.add_field_method_set("variables", |_lua, this, variables| {
this.variables = variables;

Ok(())
});
fields.add_field_method_set("cache_dir", |_lua, this, cache_dir| {
this.cache_dir = cache_dir;

Ok(())
});
fields.add_field_method_set("data_dir", |_lua, this, data_dir| {
this.data_dir = data_dir;

Ok(())
});
}

fn add_methods<M: mlua::prelude::LuaUserDataMethods<Self>>(methods: &mut M) {
methods.add_method("build", |_lua, this, ()| {
this.clone().build().into_lua_err()
})
}
}
39 changes: 39 additions & 0 deletions rocks-lib/src/lockfile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::io::{self, Write};
use std::{collections::HashMap, fs::File, io::ErrorKind, path::PathBuf};

use itertools::Itertools;
use mlua::{ExternalResult as _, LuaSerdeExt, Value};
use serde::{de, Deserialize, Serialize};
use sha2::{Digest, Sha256};
use ssri::Integrity;
Expand Down Expand Up @@ -41,6 +42,25 @@ impl PinnedState {
}
}

impl mlua::FromLua for PinnedState {
fn from_lua(value: Value, _lua: &mlua::prelude::Lua) -> mlua::prelude::LuaResult<Self> {
if let Value::Boolean(b) = value {
Ok(Self::from(b))
} else {
Err(mlua::Error::FromLuaConversionError { from: value.type_name(), to: "PinnedState".into(), message: None })
}
}
}

impl mlua::IntoLua for PinnedState {
fn into_lua(
self,
lua: &mlua::prelude::Lua,
) -> mlua::prelude::LuaResult<mlua::prelude::LuaValue> {
lua.to_value(&self)
}
}

impl Serialize for PinnedState {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
Expand Down Expand Up @@ -367,6 +387,25 @@ impl LockConstraint {
}
}

impl mlua::FromLua for LockConstraint {
fn from_lua(value: mlua::prelude::LuaValue, _lua: &mlua::prelude::Lua) -> mlua::prelude::LuaResult<Self> {
match value {
Value::Nil => Ok(LockConstraint::Unconstrained),
Value::String(str) => Ok(LockConstraint::Constrained(str.to_str().into_lua_err()?.parse().into_lua_err()?)),
_ => Err(mlua::Error::FromLuaConversionError { from: value.type_name(), to: "LockConstraint".into(), message: None })
}
}
}

impl mlua::IntoLua for LockConstraint {
fn into_lua(
self,
lua: &mlua::prelude::Lua,
) -> mlua::prelude::LuaResult<mlua::prelude::LuaValue> {
lua.to_value(&self.to_string_opt())
}
}

#[derive(Error, Debug)]
pub enum LockConstraintParseError {
#[error("Invalid constraint in LuaPackage: {0}")]
Expand Down
9 changes: 9 additions & 0 deletions rocks-lib/src/manifest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,15 @@ impl ManifestMetadata {
}
}

impl mlua::UserData for ManifestMetadata {
fn add_methods<M: mlua::prelude::LuaUserDataMethods<Self>>(methods: &mut M) {
methods.add_method("has_rock", |_lua, this, package_name: String| Ok(this.has_rock(&PackageName::new(package_name))));
methods.add_method("available_versions", |_lua, this, package_name: String| {
Ok(this.available_versions(&PackageName::new(package_name)).map(|val| val.into_iter().map(|version| version)))
});
}
}

#[derive(Clone, serde::Deserialize)]
pub struct ManifestRockEntry {
/// e.g. "linux-x86_64", "rockspec", "src", ...
Expand Down
13 changes: 12 additions & 1 deletion rocks-lib/src/rockspec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ mod test_spec;
use std::{collections::HashMap, io, path::PathBuf, str::FromStr};

use itertools::Itertools;
use mlua::{FromLua, Lua, LuaSerdeExt, Value};
use mlua::{ExternalResult, FromLua, Lua, LuaSerdeExt, Value};
use serde::{de::DeserializeOwned, Deserialize, Serialize};

pub use build::*;
Expand Down Expand Up @@ -146,6 +146,17 @@ impl Rockspec {
}
}

impl mlua::UserData for Rockspec {}
impl mlua::FromLua for Rockspec {
fn from_lua(value: Value, _lua: &Lua) -> mlua::prelude::LuaResult<Self> {
if let Value::String(str) = value {
Ok(Rockspec::new(&str.to_str().into_lua_err()?.to_string()).into_lua_err()?)
} else {
Err(mlua::Error::FromLuaConversionError { from: value.type_name(), to: "rockspec".into(), message: Some("a rockspec can only be constructed from a string".into()) })
}
}
}

fn latest_lua_version(dependencies: &PerPlatform<Vec<PackageReq>>) -> Option<LuaVersion> {
dependencies
.current_platform()
Expand Down
6 changes: 4 additions & 2 deletions rocks-lib/src/rockspec/platform.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use itertools::Itertools;
use mlua::{FromLua, Lua, LuaSerdeExt as _, Value};
use std::{cmp::Ordering, collections::HashMap, convert::Infallible, marker::PhantomData};
use mlua::{ExternalResult, FromLua, Lua, LuaSerdeExt as _, Value};
use std::{
cmp::Ordering, collections::HashMap, convert::Infallible, marker::PhantomData, str::FromStr,
};
use strum::IntoEnumIterator;
use strum_macros::EnumIter;
use thiserror::Error;
Expand Down
1 change: 1 addition & 0 deletions rocks-lib/src/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::{io, path::PathBuf};

#[cfg(feature = "lua")]
use mlua::ExternalResult as _;
use mlua::UserData;

mod list;

Expand Down
1 change: 1 addition & 0 deletions rocks-lua/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
Loading
Loading