| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- use tauri::Manager;
- const CLI_INSTALL_DIR: &str = ".opencode/bin";
- const CLI_BINARY_NAME: &str = "opencode";
- fn get_cli_install_path() -> Option<std::path::PathBuf> {
- std::env::var("HOME").ok().map(|home| {
- std::path::PathBuf::from(home)
- .join(CLI_INSTALL_DIR)
- .join(CLI_BINARY_NAME)
- })
- }
- pub fn get_sidecar_path(app: &tauri::AppHandle) -> std::path::PathBuf {
- // Get binary with symlinks support
- tauri::process::current_binary(&app.env())
- .expect("Failed to get current binary")
- .parent()
- .expect("Failed to get parent dir")
- .join("opencode-cli")
- }
- fn is_cli_installed() -> bool {
- get_cli_install_path()
- .map(|path| path.exists())
- .unwrap_or(false)
- }
- const INSTALL_SCRIPT: &str = include_str!("../../../../install");
- #[tauri::command]
- pub fn install_cli(app: tauri::AppHandle) -> Result<String, String> {
- if cfg!(not(unix)) {
- return Err("CLI installation is only supported on macOS & Linux".to_string());
- }
- let sidecar = get_sidecar_path(&app);
- if !sidecar.exists() {
- return Err("Sidecar binary not found".to_string());
- }
- let temp_script = std::env::temp_dir().join("opencode-install.sh");
- std::fs::write(&temp_script, INSTALL_SCRIPT)
- .map_err(|e| format!("Failed to write install script: {}", e))?;
- #[cfg(unix)]
- {
- use std::os::unix::fs::PermissionsExt;
- std::fs::set_permissions(&temp_script, std::fs::Permissions::from_mode(0o755))
- .map_err(|e| format!("Failed to set script permissions: {}", e))?;
- }
- let output = std::process::Command::new(&temp_script)
- .arg("--binary")
- .arg(&sidecar)
- .output()
- .map_err(|e| format!("Failed to run install script: {}", e))?;
- let _ = std::fs::remove_file(&temp_script);
- if !output.status.success() {
- let stderr = String::from_utf8_lossy(&output.stderr);
- return Err(format!("Install script failed: {}", stderr));
- }
- let install_path =
- get_cli_install_path().ok_or_else(|| "Could not determine install path".to_string())?;
- Ok(install_path.to_string_lossy().to_string())
- }
- pub fn sync_cli(app: tauri::AppHandle) -> Result<(), String> {
- if cfg!(debug_assertions) {
- println!("Skipping CLI sync for debug build");
- return Ok(());
- }
- if !is_cli_installed() {
- println!("No CLI installation found, skipping sync");
- return Ok(());
- }
- let cli_path =
- get_cli_install_path().ok_or_else(|| "Could not determine CLI install path".to_string())?;
- let output = std::process::Command::new(&cli_path)
- .arg("--version")
- .output()
- .map_err(|e| format!("Failed to get CLI version: {}", e))?;
- if !output.status.success() {
- return Err("Failed to get CLI version".to_string());
- }
- let cli_version_str = String::from_utf8_lossy(&output.stdout).trim().to_string();
- let cli_version = semver::Version::parse(&cli_version_str)
- .map_err(|e| format!("Failed to parse CLI version '{}': {}", cli_version_str, e))?;
- let app_version = app.package_info().version.clone();
- if cli_version >= app_version {
- println!(
- "CLI version {} is up to date (app version: {}), skipping sync",
- cli_version, app_version
- );
- return Ok(());
- }
- println!(
- "CLI version {} is older than app version {}, syncing",
- cli_version, app_version
- );
- install_cli(app)?;
- println!("Synced installed CLI");
- Ok(())
- }
|