mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-07 03:00:29 +00:00
79 lines
2.6 KiB
Rust
79 lines
2.6 KiB
Rust
use std::path::{Path, PathBuf};
|
|
|
|
use anyhow::Result;
|
|
|
|
use crate::asset_snapshot::AssetCollectionSummary;
|
|
|
|
/// An individual asset file discovered from a run's asset manifests.
|
|
#[derive(Debug, Clone, serde::Serialize)]
|
|
pub struct AssetEntry {
|
|
pub node_slug: String,
|
|
pub retry: u32,
|
|
pub relative_path: String,
|
|
#[serde(serialize_with = "serialize_path")]
|
|
pub absolute_path: PathBuf,
|
|
pub size: u64,
|
|
}
|
|
|
|
fn serialize_path<S: serde::Serializer>(path: &Path, serializer: S) -> Result<S::Ok, S::Error> {
|
|
serializer.serialize_str(&path.display().to_string())
|
|
}
|
|
|
|
/// Walk `{run_dir}/artifacts/assets/*/retry_*/manifest.json`, stat each file, and return entries.
|
|
pub fn scan_assets(run_dir: &Path, node_filter: Option<&str>) -> Result<Vec<AssetEntry>> {
|
|
let assets_dir = run_dir.join("artifacts/assets");
|
|
let nodes = match std::fs::read_dir(&assets_dir) {
|
|
Ok(read_dir) => read_dir,
|
|
Err(_) => return Ok(Vec::new()),
|
|
};
|
|
|
|
let mut entries = Vec::new();
|
|
for node_entry in nodes.flatten() {
|
|
if !node_entry.path().is_dir() {
|
|
continue;
|
|
}
|
|
let node_slug = node_entry.file_name().to_string_lossy().into_owned();
|
|
|
|
if let Some(filter) = node_filter {
|
|
if node_slug != filter {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
let Ok(retries) = std::fs::read_dir(node_entry.path()) else {
|
|
continue;
|
|
};
|
|
for retry_entry in retries.flatten() {
|
|
let retry_dir = retry_entry.path();
|
|
let dir_name = retry_entry.file_name().to_string_lossy().into_owned();
|
|
let retry: u32 = dir_name
|
|
.strip_prefix("retry_")
|
|
.and_then(|value| value.parse().ok())
|
|
.unwrap_or(0);
|
|
|
|
let manifest = retry_dir.join("manifest.json");
|
|
let Ok(contents) = std::fs::read_to_string(&manifest) else {
|
|
continue;
|
|
};
|
|
let Ok(summary) = serde_json::from_str::<AssetCollectionSummary>(&contents) else {
|
|
continue;
|
|
};
|
|
|
|
for relative_path in &summary.copied_paths {
|
|
let absolute_path = retry_dir.join(relative_path);
|
|
let size = std::fs::metadata(&absolute_path)
|
|
.map(|metadata| metadata.len())
|
|
.unwrap_or(0);
|
|
entries.push(AssetEntry {
|
|
node_slug: node_slug.clone(),
|
|
retry,
|
|
relative_path: relative_path.clone(),
|
|
absolute_path,
|
|
size,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(entries)
|
|
}
|