use super::types::{AssetInfo, BinaryInfo, ConfigInfo, PackageConfig};
use super::utils;
use anyhow::Result;
use std::fs;
use std::path::Path;
pub(super) fn collect_binaries(project_root: &Path, config: &PackageConfig) -> Result<Vec<BinaryInfo>> {
let target_dir = project_root
.join("target")
.join(config.target_arch.as_str())
.join(&config.build_profile);
if !target_dir.exists() {
return Err(anyhow::anyhow!(
"Target directory not found: {}. Did the build succeed?",
target_dir.display()
));
}
let mut binaries = Vec::new();
for entry in fs::read_dir(&target_dir)? {
let entry = entry?;
let path = entry.path();
if path.is_file() && utils::is_executable(&path)? {
if let Some(filename) = path.file_name() {
let filename_str = filename.to_string_lossy();
if filename_str.starts_with('.') || filename_str.contains(".d") || filename_str.ends_with(".rlib") {
continue;
}
let metadata = path.metadata()?;
let checksum = utils::calculate_checksum(&path)?;
binaries.push(BinaryInfo {
name: filename_str.to_string(),
path: format!("bin/{}", filename_str),
size_bytes: metadata.len(),
checksum,
});
}
}
}
if binaries.is_empty() {
return Err(anyhow::anyhow!("No binaries found in target directory"));
}
Ok(binaries)
}
pub(super) fn collect_configs(project_root: &Path) -> Result<Vec<ConfigInfo>> {
let mut configs = Vec::new();
let config_dirs = vec![project_root.join("config"), project_root.join("configs")];
for config_root in config_dirs {
if config_root.exists() {
collect_configs_recursive(&config_root, &config_root, &mut configs)?;
}
}
Ok(configs)
}
fn collect_configs_recursive(base_dir: &Path, current_dir: &Path, configs: &mut Vec<ConfigInfo>) -> Result<()> {
for entry in fs::read_dir(current_dir)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
collect_configs_recursive(base_dir, &path, configs)?;
} else if path.is_file() {
let extension = path.extension().and_then(|e| e.to_str());
if matches!(extension, Some("json") | Some("yaml") | Some("yml") | Some("toml")) {
let relative_path = path.strip_prefix(base_dir)?;
let config_type = utils::determine_config_type(&path);
let checksum = utils::calculate_checksum(&path)?;
configs.push(ConfigInfo {
name: path.file_name().unwrap().to_string_lossy().to_string(),
path: format!("config/{}", relative_path.display()),
config_type,
checksum,
});
}
}
}
Ok(())
}
pub(super) fn collect_assets(project_root: &Path) -> Result<Vec<AssetInfo>> {
let mut assets = Vec::new();
let asset_dirs = vec![
project_root.join("assets"),
project_root.join("models"),
project_root.join("data"),
project_root.join("calibration"),
];
for asset_root in asset_dirs {
if asset_root.exists() {
collect_assets_recursive(&asset_root, &asset_root, &mut assets)?;
}
}
Ok(assets)
}
fn collect_assets_recursive(base_dir: &Path, current_dir: &Path, assets: &mut Vec<AssetInfo>) -> Result<()> {
for entry in fs::read_dir(current_dir)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
collect_assets_recursive(base_dir, &path, assets)?;
} else if path.is_file() {
let relative_path = path.strip_prefix(base_dir)?;
let asset_type = utils::determine_asset_type(&path);
let metadata = path.metadata()?;
let checksum = utils::calculate_checksum(&path)?;
assets.push(AssetInfo {
name: path.file_name().unwrap().to_string_lossy().to_string(),
path: format!("assets/{}", relative_path.display()),
asset_type,
size_bytes: metadata.len(),
checksum,
});
}
}
Ok(())
}