gritpack-searchlib 0.1.1

Compiler-facing resolver and grammar integration surface for Gritpack
Documentation
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('.')
}