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