use anyhow::{Context, Result};
use std::thread;
use std::time::Duration;
use crate::cli::app::AppOpenArgs;
use crate::runutil::{ManagedCommand, TimeoutClass, execute_checked_command};
use super::launch_plan::{current_executable_for_gui, plan_open_command};
use super::model::OpenCommandSpec;
use super::url_plan::{plan_url_command, resolve_workspace_path};
pub(super) fn execute_launch_command(spec: &OpenCommandSpec) -> Result<()> {
execute_checked_command(ManagedCommand::new(
spec.to_command(),
"launch macOS app",
TimeoutClass::AppLaunch,
))
.context("spawn macOS app launch command")?;
Ok(())
}
pub fn open(args: AppOpenArgs) -> Result<()> {
let cli_executable = current_executable_for_gui();
let Some(workspace_path) = resolve_workspace_path(&args)? else {
let open_spec =
plan_open_command(cfg!(target_os = "macos"), &args, cli_executable.as_deref())?;
execute_launch_command(&open_spec)?;
return Ok(());
};
let url_spec = plan_url_command(&workspace_path, &args, cli_executable.as_deref())?;
let mut last_error = None;
for attempt in 0..10 {
match execute_launch_command(&url_spec) {
Ok(()) => return Ok(()),
Err(error) => {
last_error = Some(error);
if attempt < 9 {
thread::sleep(Duration::from_millis(250));
}
}
}
}
Err(last_error.expect("url launch attempts should record an error"))
}