1use crate::functions;
2use anyhow::{Result, anyhow};
3use mlua::{self, Lua, LuaSerdeExt, Table, Value};
4use std::fs;
5use zoi_core::{types, utils};
6
7pub fn parse_lua_package_for_platform(
8 file_path: &str,
9 platform: &str,
10 version_override: Option<&str>,
11 quiet: bool,
12) -> Result<types::Package> {
13 let lua_code = fs::read_to_string(file_path)?;
14 let lua = Lua::new();
15
16 let pkg_meta_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
17 let pkg_deps_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
18 let pkg_updates_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
19 let pkg_hooks_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
20 let pkg_service_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
21 lua.globals()
22 .set("__ZoiPackageMeta", pkg_meta_table)
23 .map_err(|e| anyhow!(e.to_string()))?;
24 lua.globals()
25 .set("__ZoiPackageDeps", pkg_deps_table)
26 .map_err(|e| anyhow!(e.to_string()))?;
27 lua.globals()
28 .set("__ZoiPackageUpdates", pkg_updates_table)
29 .map_err(|e| anyhow!(e.to_string()))?;
30 lua.globals()
31 .set("__ZoiPackageHooks", pkg_hooks_table)
32 .map_err(|e| anyhow!(e.to_string()))?;
33 lua.globals()
34 .set("__ZoiPackageService", pkg_service_table)
35 .map_err(|e| anyhow!(e.to_string()))?;
36
37 let pkg_table = lua.create_table().map_err(|e| anyhow!(e.to_string()))?;
38 lua.globals()
39 .set("PKG", pkg_table)
40 .map_err(|e| anyhow!(e.to_string()))?;
41
42 functions::setup_lua_environment(
43 &lua,
44 platform,
45 version_override,
46 Some(file_path),
47 None,
48 None,
49 None,
50 None,
51 quiet,
52 )
53 .map_err(|e| anyhow!("Failed to setup Lua environment for '{}': {}", file_path, e))?;
54
55 lua.load(&lua_code).exec().map_err(|e| {
56 anyhow!(
57 "Failed to execute Lua package file '{}':
58{}",
59 file_path,
60 e
61 )
62 })?;
63
64 let final_pkg_meta: Table = lua
65 .globals()
66 .get("__ZoiPackageMeta")
67 .map_err(|e| anyhow!(e.to_string()))?;
68 let final_pkg_deps: Table = lua
69 .globals()
70 .get("__ZoiPackageDeps")
71 .map_err(|e| anyhow!(e.to_string()))?;
72 let final_pkg_updates: Table = lua
73 .globals()
74 .get("__ZoiPackageUpdates")
75 .map_err(|e| anyhow!(e.to_string()))?;
76 let final_pkg_hooks: Table = lua
77 .globals()
78 .get("__ZoiPackageHooks")
79 .map_err(|e| anyhow!(e.to_string()))?;
80 let final_pkg_service: Table = lua
81 .globals()
82 .get("__ZoiPackageService")
83 .map_err(|e| anyhow!(e.to_string()))?;
84
85 let mut package: types::Package =
86 lua.from_value(Value::Table(final_pkg_meta)).map_err(|e| {
87 anyhow!(
88 "Failed to parse 'metadata' block in package file '{}':
89{}",
90 file_path,
91 e
92 )
93 })?;
94
95 package.dependencies = if final_pkg_deps.is_empty() {
96 None
97 } else {
98 Some(lua.from_value(Value::Table(final_pkg_deps)).map_err(|e| {
99 anyhow!(
100 "Failed to parse 'dependencies' block in package file '{}':
101{}",
102 file_path,
103 e
104 )
105 })?)
106 };
107
108 package.updates = if final_pkg_updates.is_empty() {
109 None
110 } else {
111 Some(
112 lua.from_value(Value::Table(final_pkg_updates))
113 .map_err(|e| {
114 anyhow!(
115 "Failed to parse 'updates' block in package file '{}':
116{}",
117 file_path,
118 e
119 )
120 })?,
121 )
122 };
123
124 package.hooks = if final_pkg_hooks.is_empty() {
125 None
126 } else {
127 Some(lua.from_value(Value::Table(final_pkg_hooks)).map_err(|e| {
128 anyhow!(
129 "Failed to parse 'hooks' block in package file '{}':
130{}",
131 file_path,
132 e
133 )
134 })?)
135 };
136
137 package.service = if final_pkg_service.is_empty() {
138 None
139 } else {
140 Some(
141 lua.from_value(Value::Table(final_pkg_service))
142 .map_err(|e| {
143 anyhow!(
144 "Failed to parse 'service' block in package file '{}':
145{}",
146 file_path,
147 e
148 )
149 })?,
150 )
151 };
152
153 Ok(package)
154}
155
156pub fn parse_lua_package(
157 file_path: &str,
158 version_override: Option<&str>,
159 quiet: bool,
160) -> Result<types::Package> {
161 let platform = utils::get_platform()?;
162 parse_lua_package_for_platform(file_path, &platform, version_override, quiet)
163}