Skip to main content

zoi_cli/cmd/
home.rs

1//! Logic for the `home` command.
2//!
3//! This module provides commands for managing user-specific declarative
4//! configuration, including dotfiles and user-level package installations.
5
6use anyhow::{Result, anyhow};
7use clap::{Parser, Subcommand};
8use colored::Colorize;
9use zoi_core::utils::is_zoios;
10use zoi_system::home::{apply_home_config, load_home_lua};
11
12/// The root home management command.
13#[derive(Parser, Debug)]
14pub struct HomeCommand {
15    /// The specific home subcommand to execute.
16    #[command(subcommand)]
17    pub command: HomeSubcommands
18}
19
20/// Available home subcommands.
21#[derive(Subcommand, Debug)]
22pub enum HomeSubcommands {
23    /// Apply a declarative user configuration from home.lua
24    Apply {
25        /// Path to the home configuration file
26        #[arg(short, long)]
27        file: Option<String>
28    }
29}
30
31/// Run the home management command.
32///
33/// # Errors
34///
35/// Returns an error if not on a `ZoiOS` system, if the home configuration
36/// cannot be loaded or applied, or if user packages fail to install.
37pub fn run(args: HomeCommand) -> Result<()> {
38    if !is_zoios() {
39        return Err(anyhow!(
40            "'zoi home' features are only available on ZoiOS systems."
41        ));
42    }
43
44    match args.command {
45        HomeSubcommands::Apply { file } => {
46            let config_path = if let Some(f) = file {
47                f
48            } else {
49                let mut p =
50                    crate::pkg::utils::get_user_home().ok_or_else(|| {
51                        anyhow!("Could not determine user home directory.")
52                    })?;
53                p.push(".config/zoi/home.lua");
54                p.to_string_lossy().to_string()
55            };
56
57            println!(
58                "Reading user configuration from {}...",
59                config_path.cyan()
60            );
61            let config = load_home_lua(&config_path)?;
62
63            // Install user packages
64            if !config.packages.is_empty() {
65                println!(
66                    "{} Installing {} user packages...",
67                    "::".bold().blue(),
68                    config.packages.len().to_string().cyan()
69                );
70
71                let project_config = zoi_project::config::ProjectConfig {
72                    name: "home".to_string(),
73                    registries: std::collections::HashMap::new(),
74                    packages: Vec::new(),
75                    pkgs: config.packages.clone(),
76                    pkgs_v2: config.packages_v2.clone(),
77                    config: zoi_project::config::ProjectLocalConfig::default(),
78                    commands: Vec::new(),
79                    environments: Vec::new(),
80                    shell: Some(zoi_project::config::ShellSpec::default())
81                };
82
83                crate::cmd::install::run(
84                    &config.packages,
85                    None,
86                    false,
87                    false,
88                    true, // yes
89                    Some(crate::cli::InstallScope::User),
90                    false,
91                    false,
92                    false,
93                    None,
94                    false,
95                    None,
96                    false,
97                    false,
98                    false,
99                    false,
100                    3,
101                    false,
102                    false,
103                    Some(project_config)
104                )?;
105            }
106
107            // Apply dotfiles and env
108            apply_home_config(&config)?;
109            println!("{}", "User environment applied successfully.".green());
110        }
111    }
112
113    Ok(())
114}