use std::path::{Path, PathBuf};
use crate::models::{
CliError, ExecutableArtifactResponse, InstalledPackage,
};
pub(crate) fn installed_executable_path(
package: &InstalledPackage,
executable: &ExecutableArtifactResponse,
) -> Result<PathBuf, CliError> {
let relative = crate::sanitize_archive_path(Path::new(&executable.path))?;
let absolute = PathBuf::from(&package.install_path).join(relative);
if !absolute.exists() {
return Err(CliError::Message(format!(
"installed executable not found for {} {}: {}",
package.name,
executable.name,
absolute.display()
)));
}
Ok(absolute)
}
fn resolve_environment_command_token(
root_package: &InstalledPackage,
token: &str,
) -> Result<PathBuf, CliError> {
let path = Path::new(token);
if path.is_absolute() || !looks_like_relative_command_path(path) {
return Ok(PathBuf::from(token));
}
let relative = crate::sanitize_archive_path(path)?;
let resolved = PathBuf::from(&root_package.install_path).join(relative);
if !resolved.exists() {
return Err(CliError::Message(format!(
"stage entrypoint not found: {}",
resolved.display()
)));
}
Ok(resolved)
}
fn looks_like_relative_command_path(path: &Path) -> bool {
if path.is_absolute() {
return false;
}
let raw = path.as_os_str().to_string_lossy();
raw.contains('/') || raw.contains('\\') || raw.starts_with('.')
}