Skip to main content

zoi_lua/
functions.rs

1use crate::api;
2use mlua::Lua;
3use zoi_core::utils;
4
5/// Bootstraps the Lua environment for executing a package definition.
6///
7/// This function populates the global Lua scope with system information,
8/// directory paths, and utility functions that the `.pkg.lua` script
9/// expects to have available. It effectively creates the "sandbox" where
10/// package builds and installations are defined.
11pub fn setup_lua_environment(
12    lua: &Lua,
13    platform: &str,
14    version_override: Option<&str>,
15    file_path: Option<&str>,
16    create_pkg_dir: Option<&str>,
17    build_dir: Option<&str>,
18    staging_dir: Option<&str>,
19    sub_package: Option<&str>,
20    scope: Option<zoi_core::types::Scope>,
21    quiet: bool,
22) -> Result<(), mlua::Error> {
23    // Host System Information
24    // Exposes a 'SYSTEM' table containing OS, Architecture, Distro, etc.
25    // Allow maintainers to write platform-specific logic easily.
26    let system_table = lua.create_table()?;
27    let parts: Vec<&str> = platform.split('-').collect();
28    system_table.set("OS", *parts.first().unwrap_or(&""))?;
29    system_table.set("ARCH", *parts.get(1).unwrap_or(&""))?;
30    if let Some(distro) = utils::get_linux_distribution() {
31        system_table.set("DISTRO", distro)?;
32    }
33    if let Some(de) = utils::get_desktop_environment() {
34        system_table.set("DE", de)?;
35    }
36    if let Some(server) = utils::get_display_server() {
37        system_table.set("SERVER", server)?;
38    }
39    if let Some(dv) = utils::get_distro_version() {
40        system_table.set("DISTRO_VER", dv)?;
41    }
42    if let Some(kernel) = utils::get_kernel_version() {
43        system_table.set("KERNEL_VER", kernel)?;
44    }
45    if let Some(cpu) = utils::get_cpu_info() {
46        system_table.set("CPU", cpu)?;
47    }
48    if let Some(gpu) = utils::get_gpu_info() {
49        system_table.set("GPU", gpu)?;
50    }
51    if let Some(manager) = utils::get_native_package_manager() {
52        system_table.set("MANAGER", manager)?;
53    }
54    lua.globals().set("SYSTEM", system_table)?;
55
56    let zoi_table = lua.create_table()?;
57    if let Some(ver) = version_override {
58        zoi_table.set("VERSION", ver)?;
59    }
60
61    if let Some(s) = scope {
62        let scope_str = format!("{:?}", s).to_lowercase();
63        zoi_table.set("scope", scope_str)?;
64    }
65
66    if let Some(dir) = create_pkg_dir {
67        zoi_table.set("CREATE_PKG_DIR", dir)?;
68    }
69
70    if let Some(sub) = sub_package {
71        lua.globals().set("SUBPKG", sub)?;
72    }
73
74    let path_table = lua.create_table()?;
75    if let Some(home_dir) = home::home_dir() {
76        path_table.set("user", home_dir.join(".zoi").to_string_lossy().to_string())?;
77    }
78
79    let system_bin_path = if cfg!(target_os = "windows") {
80        "C:\\ProgramData\\zoi\\pkgs\\bin".to_string()
81    } else {
82        "/usr/local/bin".to_string()
83    };
84    path_table.set("system", system_bin_path)?;
85
86    zoi_table.set("PATH", path_table)?;
87
88    let pkg_table = lua.create_table()?;
89    if let Some(home_dir) = home::home_dir() {
90        pkg_table.set("home", home_dir.to_string_lossy().to_string())?;
91        pkg_table.set(
92            "store",
93            home_dir
94                .join(".zoi")
95                .join("pkgs")
96                .join("store")
97                .to_string_lossy()
98                .to_string(),
99        )?;
100    }
101
102    if let Ok(current_dir) = std::env::current_dir() {
103        pkg_table.set("template", current_dir.to_string_lossy().to_string())?;
104    }
105
106    let root = if cfg!(target_os = "windows") {
107        "C:\\"
108    } else {
109        "/"
110    };
111    pkg_table.set("root", root)?;
112
113    if let Some(path_str) = file_path {
114        let abs_path = if let Ok(p) = std::fs::canonicalize(path_str) {
115            p
116        } else {
117            std::path::Path::new(path_str).to_path_buf()
118        };
119        pkg_table.set("lua", abs_path.to_string_lossy().to_string())?;
120    }
121    zoi_table.set("PKG", pkg_table.clone())?;
122
123    let location_table = lua.create_table()?;
124    if let Some(sd) = staging_dir {
125        let staging_path = std::path::Path::new(sd);
126        location_table.set(
127            "PKGSTORE",
128            staging_path
129                .join("data/pkgstore")
130                .to_string_lossy()
131                .to_string(),
132        )?;
133        location_table.set(
134            "HOME",
135            staging_path
136                .join("data/usrhome")
137                .to_string_lossy()
138                .to_string(),
139        )?;
140        location_table.set(
141            "ROOT",
142            staging_path
143                .join("data/usrroot")
144                .to_string_lossy()
145                .to_string(),
146        )?;
147        location_table.set(
148            "TEMPLATE",
149            staging_path
150                .join("data/createpkgdir")
151                .to_string_lossy()
152                .to_string(),
153        )?;
154    } else {
155        if let Some(home_dir) = home::home_dir() {
156            location_table.set(
157                "PKGSTORE",
158                home_dir
159                    .join(".zoi")
160                    .join("pkgs")
161                    .join("store")
162                    .to_string_lossy()
163                    .to_string(),
164            )?;
165            location_table.set("HOME", home_dir.to_string_lossy().to_string())?;
166        }
167        let root = if cfg!(target_os = "windows") {
168            "C:\\"
169        } else {
170            "/"
171        };
172        location_table.set("ROOT", root.to_string())?;
173        if let Ok(current_dir) = std::env::current_dir() {
174            location_table.set("TEMPLATE", current_dir.to_string_lossy().to_string())?;
175        }
176    }
177    if let Some(path_str) = file_path {
178        let abs_path = if let Ok(p) = std::fs::canonicalize(path_str) {
179            p
180        } else {
181            std::path::Path::new(path_str).to_path_buf()
182        };
183        location_table.set(
184            "PKGLUADIR",
185            abs_path
186                .parent()
187                .unwrap_or(&abs_path)
188                .to_string_lossy()
189                .to_string(),
190        )?;
191    }
192    if let Some(bd) = build_dir {
193        location_table.set("BUILDDIR", bd)?;
194    }
195    if let Some(sd) = staging_dir {
196        location_table.set("STAGINGDIR", sd)?;
197    }
198    zoi_table.set("LOCATION", location_table)?;
199
200    lua.globals().set("ZOI", zoi_table)?;
201
202    let utils_table = lua.create_table()?;
203    lua.globals().set("UTILS", utils_table)?;
204
205    api::http::add_fetch_util(lua)?;
206    api::parse::add_parse_util(lua)?;
207    api::http::add_git_fetch_util(lua)?;
208    api::fs::add_file_util(lua)?;
209    api::fs::add_zcp(lua)?;
210    api::fs::add_zlicense(lua)?;
211    api::fs::add_zdoc(lua)?;
212    api::fs::add_zshell(lua)?;
213    api::fs::add_zsed(lua, quiet)?;
214    api::fs::add_zln(lua)?;
215    api::fs::add_zchmod(lua)?;
216    api::fs::add_zchown(lua)?;
217    api::fs::add_zmkdir(lua)?;
218    api::crypto::add_verify_hash(lua, quiet)?;
219    api::fs::add_zrm(lua)?;
220    api::system::add_cmd_util(lua, quiet)?;
221    api::system::add_zpatch(lua, quiet)?;
222    api::fs::add_fs_util(lua)?;
223    api::fs::add_find_util(lua)?;
224    api::archive::add_archive_util(lua)?;
225    api::archive::add_extract_util(lua, quiet)?;
226    api::crypto::add_verify_signature(lua, quiet)?;
227    api::crypto::add_add_pgp_key(lua, quiet)?;
228    api::lifecycle::add_package_lifecycle_functions(lua)?;
229
230    if let Some(path_str) = file_path {
231        let path = std::path::Path::new(path_str);
232        api::lifecycle::add_import_util(lua, path)?;
233        api::lifecycle::add_include_util(lua, path)?;
234    }
235
236    if let Some(sub) = sub_package {
237        lua.globals().set("SUBPKG", sub)?;
238    }
239
240    Ok(())
241}