Skip to main content

cli/sys/
mod.rs

1mod commands;
2mod detect;
3mod execution;
4mod managed;
5#[cfg(test)]
6mod manifest;
7mod model;
8mod profile_commands;
9mod recovery;
10mod render;
11mod run_manifest;
12mod selection;
13
14use model::{
15    LoadedSysPreset, ResolvedSelection, SysDetection, SysDetectionProbe, SysDriverKind, SysInstall,
16    SysInstalledRow, SysItem, SysItemMode, SysItemOutcome, SysItemStatus, SysPackageProvider,
17    SysUpdateRow, SysUpgradeReport,
18};
19
20use anyhow::{Context, Result};
21
22pub use commands::{handle_info, handle_init, handle_list, handle_status};
23pub use detect::detect_os_id;
24pub(crate) use managed::installed_managed;
25pub use managed::{
26    handle_apply, handle_apply_approved, handle_uninstall, handle_uninstall_approved,
27    handle_upgrade_managed, handle_upgrade_managed_target, managed_updates,
28};
29pub(crate) use managed::{
30    handle_upgrade_managed_target_with_result_approved, handle_upgrade_managed_with_result_prepared,
31};
32pub use profile_commands::{
33    handle_profile_disable, handle_profile_disable_approved, handle_profile_enable,
34    handle_profile_enable_approved,
35};
36pub use recovery::handle_recover_approved;
37
38const SYS_TEMPLATE: &str = r#"# System bootstrap preset metadata for shine (schema v2).
39version = 2
40description = "My system bootstrap."
41default_profile = "recommended"
42
43[[items]]
44id = "my-tool"
45label = "My Tool"
46description = "Install and configure my tool."
47default = true
48detect = { kind = "command", command = "my-tool", version_args = ["--version"] }
49# Keep scripts inside this category. For Windows, use a .ps1 script instead.
50install = { kind = "script", path = "install/my-tool.sh" }
51
52[items.permissions]
53schema_version = 1
54filesystem = [{ access = ["execute"], base = "preset", path = "install/my-tool.sh" }]
55# Add reviewed command, network, administrator, environment, and system identities used by the script.
56
57[profiles.recommended]
58items = ["my-tool"]
59"#;
60
61pub async fn handle_init_template(force: bool) -> Result<()> {
62    let dir = std::env::current_dir().context("reading current directory")?;
63    let (path, overwritten) =
64        shine_core::init_template::write_shine_toml_template(&dir, force, SYS_TEMPLATE)?;
65    if overwritten {
66        println!("Updated sys preset template: {}", path.display());
67    } else {
68        println!("Created sys preset template: {}", path.display());
69    }
70    Ok(())
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76
77    #[test]
78    fn init_template_contains_valid_permission_declaration() {
79        let manifest = manifest::parse_and_validate_manifest(SYS_TEMPLATE).unwrap();
80
81        assert_eq!(manifest.items.len(), 1);
82        assert_eq!(
83            manifest.items[0]
84                .permissions
85                .as_ref()
86                .map(|permissions| permissions.schema_version),
87            Some(1)
88        );
89    }
90}