zoi-lua 1.22.1

Advanced Package Manager & Environment Orchestrator
Documentation
use crate::functions;
use anyhow::{Result, anyhow};
use mlua::{self, Lua, LuaSerdeExt, Table, Value};
use std::fs;
use zoi_core::{types, utils};

pub fn parse_lua_package_for_platform(
    file_path: &str,
    platform: &str,
    version_override: Option<&str>,
    quiet: bool,
) -> Result<types::Package> {
    let lua_code = fs::read_to_string(file_path)?;
    let lua = Lua::new();

    let pkg_meta_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
    let pkg_deps_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
    let pkg_updates_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
    let pkg_hooks_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
    let pkg_service_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
    lua.globals()
        .set("__ZoiPackageMeta", pkg_meta_table)
        .map_err(|e| anyhow!(e.to_string()))?;
    lua.globals()
        .set("__ZoiPackageDeps", pkg_deps_table)
        .map_err(|e| anyhow!(e.to_string()))?;
    lua.globals()
        .set("__ZoiPackageUpdates", pkg_updates_table)
        .map_err(|e| anyhow!(e.to_string()))?;
    lua.globals()
        .set("__ZoiPackageHooks", pkg_hooks_table)
        .map_err(|e| anyhow!(e.to_string()))?;
    lua.globals()
        .set("__ZoiPackageService", pkg_service_table)
        .map_err(|e| anyhow!(e.to_string()))?;

    let pkg_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
    lua.globals()
        .set("PKG", pkg_table)
        .map_err(|e| anyhow!(e.to_string()))?;

    functions::setup_lua_environment(
        &lua,
        platform,
        version_override,
        Some(file_path),
        None,
        None,
        None,
        None,
        quiet,
    )
    .map_err(|e| anyhow!("Failed to setup Lua environment for '{}': {}", file_path, e))?;

    lua.load(&lua_code).exec().map_err(|e| {
        anyhow!(
            "Failed to execute Lua package file '{}':
{}",
            file_path,
            e
        )
    })?;

    let final_pkg_meta: Table = lua
        .globals()
        .get("__ZoiPackageMeta")
        .map_err(|e| anyhow!(e.to_string()))?;
    let final_pkg_deps: Table = lua
        .globals()
        .get("__ZoiPackageDeps")
        .map_err(|e| anyhow!(e.to_string()))?;
    let final_pkg_updates: Table = lua
        .globals()
        .get("__ZoiPackageUpdates")
        .map_err(|e| anyhow!(e.to_string()))?;
    let final_pkg_hooks: Table = lua
        .globals()
        .get("__ZoiPackageHooks")
        .map_err(|e| anyhow!(e.to_string()))?;
    let final_pkg_service: Table = lua
        .globals()
        .get("__ZoiPackageService")
        .map_err(|e| anyhow!(e.to_string()))?;

    let mut package: types::Package =
        lua.from_value(Value::Table(final_pkg_meta)).map_err(|e| {
            anyhow!(
                "Failed to parse 'metadata' block in package file '{}':
{}",
                file_path,
                e
            )
        })?;

    package.dependencies = if final_pkg_deps.is_empty() {
        None
    } else {
        Some(lua.from_value(Value::Table(final_pkg_deps)).map_err(|e| {
            anyhow!(
                "Failed to parse 'dependencies' block in package file '{}':
{}",
                file_path,
                e
            )
        })?)
    };

    package.updates = if final_pkg_updates.is_empty() {
        None
    } else {
        Some(
            lua.from_value(Value::Table(final_pkg_updates))
                .map_err(|e| {
                    anyhow!(
                        "Failed to parse 'updates' block in package file '{}':
{}",
                        file_path,
                        e
                    )
                })?,
        )
    };

    package.hooks = if final_pkg_hooks.is_empty() {
        None
    } else {
        Some(lua.from_value(Value::Table(final_pkg_hooks)).map_err(|e| {
            anyhow!(
                "Failed to parse 'hooks' block in package file '{}':
{}",
                file_path,
                e
            )
        })?)
    };

    package.service = if final_pkg_service.is_empty() {
        None
    } else {
        Some(
            lua.from_value(Value::Table(final_pkg_service))
                .map_err(|e| {
                    anyhow!(
                        "Failed to parse 'service' block in package file '{}':
{}",
                        file_path,
                        e
                    )
                })?,
        )
    };

    Ok(package)
}

pub fn parse_lua_package(
    file_path: &str,
    version_override: Option<&str>,
    quiet: bool,
) -> Result<types::Package> {
    let platform = utils::get_platform()?;
    parse_lua_package_for_platform(file_path, &platform, version_override, quiet)
}