Skip to main content

zoi_core/
sysroot.rs

1/// Manages the "Sysroot" (System Root) for Zoi operations.
2///
3/// A Sysroot allows Zoi to operate on an external directory as if it were the
4/// primary system root (`/`). This is a powerful feature for:
5/// - Bootstrapping: Creating a bootable OS image or container from the outside.
6/// - Cross-Installation: Installing packages for an embedded system or another partition.
7/// - Isolation: Testing installations without affecting the current host system.
8///
9/// When a sysroot is set, Zoi transparently redirects all absolute and relative
10/// paths to reside within this target directory.
11use std::path::PathBuf;
12use std::sync::{OnceLock, RwLock};
13
14fn sysroot_store() -> &'static RwLock<Option<PathBuf>> {
15    static SYSROOT: OnceLock<RwLock<Option<PathBuf>>> = OnceLock::new();
16    SYSROOT.get_or_init(|| RwLock::new(None))
17}
18
19/// Sets or replaces the global sysroot path.
20pub fn set_sysroot(path: PathBuf) {
21    if let Ok(mut guard) = sysroot_store().write() {
22        *guard = Some(path);
23    }
24}
25
26/// Clears the global sysroot path.
27pub fn clear_sysroot() {
28    if let Ok(mut guard) = sysroot_store().write() {
29        *guard = None;
30    }
31}
32
33/// Returns the global sysroot path if it has been set.
34pub fn get_sysroot() -> Option<PathBuf> {
35    sysroot_store().read().ok().and_then(|g| g.clone())
36}
37
38/// Prepends the sysroot to the given path if a sysroot is set.
39/// If the path is absolute, it is made relative to the current root before joining.
40pub fn apply_sysroot(path: impl Into<PathBuf>) -> PathBuf {
41    let path = path.into();
42    if let Some(root) = get_sysroot() {
43        if path.is_absolute() {
44            let mut components = path.components();
45            components.next();
46            root.join(components.as_path())
47        } else {
48            root.join(path)
49        }
50    } else {
51        path
52    }
53}