use std::ffi::OsStr; use std::path::PathBuf; use std::process; enum AppData { Folder(PathBuf), Asar(PathBuf) } impl AppData { fn get_path(&self) -> &OsStr { match self { AppData::Folder(path) => path.as_ref(), AppData::Asar(path) => path.as_ref() } } } fn get_home() -> PathBuf { dirs::home_dir().unwrap_or(PathBuf::from("/")) } #[cfg(target_os = "macos")] fn get_home_search() -> PathBuf { let mut path = get_home(); path.push("/Library/Frameworks/AtomicRuntime.framework"); path } #[cfg(target_os = "linux")] fn get_home_search() -> PathBuf { let mut path = get_home(); path.push("/.local/share/atomic-runtime"); path } #[cfg(target_os = "windows")] fn get_home_search() -> PathBuf { let mut path = get_home(); path.push("\\AppData\\Local\\Atomic Runtime"); path } #[cfg(target_os = "macos")] fn get_search_paths() -> [PathBuf; 5] { [ PathBuf::from("/Library/Frameworks/AtomicRuntime.framework"), PathBuf::from("/System/Library/Frameworks/AtomicRuntime.framework"), PathBuf::from("/usr/local/lib/atomic-runtime"), PathBuf::from("/opt/atomic-runtime"), get_home_search(), ] } #[cfg(target_os = "linux")] fn get_search_paths() -> [PathBuf; 8] { [ PathBuf::from("/usr/local/lib/atomic-runtime"), PathBuf::from("/usr/local/lib64/atomic-runtime"), PathBuf::from("/usr/lib/atomic-runtime"), PathBuf::from("/usr/lib64/atomic-runtime"), PathBuf::from("/lib/atomic-runtime"), PathBuf::from("/lib64/atomic-runtime"), PathBuf::from("/opt/atomic-runtime"), get_home_search(), ] } #[cfg(target_os = "windows")] fn get_search_paths() -> [PathBuf; 29] { [ PathBuf::from("C:\\Program Files\\Common Files\\Equestria.dev\\AtomicRuntime"), PathBuf::from("C:\\Program Files\\Common Files\\Equestria.dev\\Atomic Runtime"), PathBuf::from("C:\\Program Files (x86)\\Common Files\\Equestria.dev\\AtomicRuntime"), PathBuf::from("C:\\Program Files (x86)\\Common Files\\Equestria.dev\\Atomic Runtime"), PathBuf::from("C:\\Program Files (Arm)\\Common Files\\Equestria.dev\\AtomicRuntime"), PathBuf::from("C:\\Program Files (Arm)\\Common Files\\Equestria.dev\\Atomic Runtime"), PathBuf::from("C:\\Program Files\\Common Files\\AtomicRuntime"), PathBuf::from("C:\\Program Files\\Common Files\\Atomic Runtime"), PathBuf::from("C:\\Program Files (x86)\\Common Files\\AtomicRuntime"), PathBuf::from("C:\\Program Files (x86)\\Common Files\\Atomic Runtime"), PathBuf::from("C:\\Program Files (Arm)\\Common Files\\AtomicRuntime"), PathBuf::from("C:\\Program Files (Arm)\\Common Files\\Atomic Runtime"), PathBuf::from("C:\\Windows\\AtomicRuntime"), PathBuf::from("C:\\Windows\\Atomic Runtime"), PathBuf::from("C:\\Program Files\\Equestria.dev\\AtomicRuntime"), PathBuf::from("C:\\Program Files\\Equestria.dev\\Atomic Runtime"), PathBuf::from("C:\\Program Files (x86)\\Equestria.dev\\AtomicRuntime"), PathBuf::from("C:\\Program Files (x86)\\Equestria.dev\\Atomic Runtime"), PathBuf::from("C:\\Program Files (Arm)\\Equestria.dev\\AtomicRuntime"), PathBuf::from("C:\\Program Files (Arm)\\Equestria.dev\\Atomic Runtime"), PathBuf::from("C:\\Program Files\\AtomicRuntime"), PathBuf::from("C:\\Program Files\\Atomic Runtime"), PathBuf::from("C:\\Program Files (x86)\\AtomicRuntime"), PathBuf::from("C:\\Program Files (x86)\\Atomic Runtime"), PathBuf::from("C:\\Program Files (Arm)\\AtomicRuntime"), PathBuf::from("C:\\Program Files (Arm)\\Atomic Runtime"), PathBuf::from("C:\\ProgramData\\AtomicRuntime"), PathBuf::from("C:\\ProgramData\\Atomic Runtime"), get_home_search(), ] } fn show_system_info() { println!( "atomic-launcher: Starting atomic-launcher {} on {} ({})", VERSION, std::env::consts::OS, std::env::consts::ARCH ); } // TODO: Rename these to "Atomic" #[cfg(target_os = "macos")] const BINARY_PATH: &str = "Contents/MacOS/Electron"; #[cfg(target_os = "linux")] const BINARY_PATH: &str = "electron"; #[cfg(target_os = "windows")] const BINARY_PATH: &str = "electron.exe"; #[cfg(target_os = "macos")] const APP_FOLDER_PATH: &str = "../Resources/app"; #[cfg(any(target_os = "linux", target_os = "windows"))] const APP_FOLDER_PATH: &str = "./resources/app"; #[cfg(target_os = "macos")] const APP_ASAR_PATH: &str = "../Resources/app.asar"; #[cfg(any(target_os = "linux", target_os = "windows"))] const APP_ASAR_PATH: &str = "./resources/app.asar"; const VERSION: &str = env!("CARGO_PKG_VERSION"); fn is_valid_path(mut path: PathBuf) -> Option { path.push(BINARY_PATH); let as_path = path.as_path(); if as_path.is_file() { Some(path) } else { None } } fn main() { show_system_info(); println!( "atomic-launcher: Compiled against rustc {}", rustc_version_runtime::version() ); let exec_path = std::env::current_exe().ok(); let work_dir = exec_path.as_ref().and_then(|p| p.parent()).unwrap(); println!( "atomic-launcher: Current directory: {}", work_dir.to_str().unwrap() ); let mut app_data: Option = None; let mut app_path_folder = PathBuf::from(work_dir); app_path_folder.push(APP_FOLDER_PATH); let mut app_path_asar = PathBuf::from(work_dir); app_path_asar.push(APP_ASAR_PATH); if app_path_folder.exists() { app_data = Some(AppData::Folder(app_path_folder)) } else if app_path_asar.exists() { app_data = Some(AppData::Asar(app_path_asar)) } else { println!( "atomic-launcher: Warning: Could not find Electron-compatible app.\ Looked in {} and {}. The default atomic-runtime application will be opened instead.", app_path_folder.to_str().unwrap(), app_path_asar.to_str().unwrap() ); } let runtime_search_paths = get_search_paths(); let runtime_search_paths_string = runtime_search_paths .iter() .map(|i| i.to_str().unwrap()) .collect::>() .join(", "); println!( "atomic-launcher: Looking for atomic-runtime in: {}", runtime_search_paths_string ); let runtime_path = runtime_search_paths.into_iter() .filter_map(is_valid_path) .next(); if let Some(path) = runtime_path { println!( "atomic-launcher: Found atomic-runtime at {}", path.to_str().unwrap() ); let mut cmd = process::Command::new(path); cmd.env("ATOMIC_LAUNCHER_VERSION", VERSION); println!("atomic-launcher: Executing: {:?}", cmd); if let Some(app_data) = app_data { cmd.arg(app_data.get_path()); } if let Ok(status) = cmd.status() { process::exit(status.code().unwrap_or(255)); } else { eprintln!("atomic-launcher: Application failed to start."); process::exit(3); } } else { eprintln!("atomic-launcher: Could not find a valid atomic-runtime path. Aborting."); process::exit(2); } }