opencode_cloud_core/platform/
mod.rs1use std::path::PathBuf;
7
8use anyhow::Result;
9
10#[cfg(any(
11 target_os = "linux",
12 not(any(target_os = "linux", target_os = "macos"))
13))]
14use anyhow::anyhow;
15
16#[cfg(target_os = "linux")]
17mod systemd;
18
19#[cfg(target_os = "macos")]
20mod launchd;
21
22#[cfg(target_os = "linux")]
23pub use systemd::{SystemdManager, systemd_available};
24
25#[cfg(target_os = "macos")]
26pub use launchd::LaunchdManager;
27
28#[derive(Debug, Clone)]
30pub struct ServiceConfig {
31 pub executable_path: PathBuf,
33
34 pub restart_retries: u32,
36
37 pub restart_delay: u32,
39
40 pub boot_mode: String,
42}
43
44#[derive(Debug, Clone)]
46pub struct InstallResult {
47 pub service_file_path: PathBuf,
49
50 pub service_name: String,
52
53 pub started: bool,
55
56 pub requires_root: bool,
58}
59
60pub trait ServiceManager: Send + Sync {
65 fn install(&self, config: &ServiceConfig) -> Result<InstallResult>;
70
71 fn uninstall(&self) -> Result<()>;
75
76 fn is_installed(&self) -> Result<bool>;
78
79 fn service_file_path(&self) -> PathBuf;
81
82 fn service_name(&self) -> &str;
84}
85
86pub fn get_service_manager() -> Result<Box<dyn ServiceManager>> {
91 #[cfg(target_os = "linux")]
92 {
93 if !systemd::systemd_available() {
94 return Err(anyhow!(
95 "systemd not available on this system. \
96 Service registration requires systemd as the init system."
97 ));
98 }
99 Ok(Box::new(systemd::SystemdManager::new("user")))
100 }
101 #[cfg(target_os = "macos")]
102 {
103 Ok(Box::new(launchd::LaunchdManager::new("user")))
104 }
105 #[cfg(not(any(target_os = "linux", target_os = "macos")))]
106 {
107 Err(anyhow!("Unsupported platform for service registration"))
108 }
109}
110
111pub fn is_service_registration_supported() -> bool {
115 cfg!(any(target_os = "linux", target_os = "macos"))
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn test_service_config_creation() {
124 let config = ServiceConfig {
125 executable_path: PathBuf::from("/usr/local/bin/occ"),
126 restart_retries: 3,
127 restart_delay: 5,
128 boot_mode: "user".to_string(),
129 };
130
131 assert_eq!(config.executable_path, PathBuf::from("/usr/local/bin/occ"));
132 assert_eq!(config.restart_retries, 3);
133 assert_eq!(config.restart_delay, 5);
134 assert_eq!(config.boot_mode, "user");
135 }
136
137 #[test]
138 fn test_install_result_creation() {
139 let result = InstallResult {
140 service_file_path: PathBuf::from("/etc/systemd/user/opencode-cloud.service"),
141 service_name: "opencode-cloud".to_string(),
142 started: true,
143 requires_root: false,
144 };
145
146 assert_eq!(
147 result.service_file_path,
148 PathBuf::from("/etc/systemd/user/opencode-cloud.service")
149 );
150 assert_eq!(result.service_name, "opencode-cloud");
151 assert!(result.started);
152 assert!(!result.requires_root);
153 }
154
155 #[test]
156 fn test_is_service_registration_supported() {
157 #[cfg(any(target_os = "linux", target_os = "macos"))]
159 assert!(is_service_registration_supported());
160
161 #[cfg(not(any(target_os = "linux", target_os = "macos")))]
162 assert!(!is_service_registration_supported());
163 }
164
165 #[test]
166 fn test_get_service_manager_behavior() {
167 let result = get_service_manager();
168
169 #[cfg(target_os = "linux")]
174 {
175 let _ = result;
178 }
179 #[cfg(target_os = "macos")]
180 {
181 assert!(result.is_ok());
183 let manager = result.unwrap();
184 assert_eq!(manager.service_name(), "com.opencode-cloud.service");
185 }
186 #[cfg(not(any(target_os = "linux", target_os = "macos")))]
187 {
188 assert!(result.is_err());
189 }
190 }
191}