phago_runtime/
project_context.rs1use std::path::{Path, PathBuf};
7
8#[derive(Debug, Clone)]
10pub struct SourceFile {
11 pub path: PathBuf,
12 pub relative_path: String,
13 pub extension: String,
14 pub size_bytes: u64,
15}
16
17pub fn scan_rust_files(root: &Path) -> Vec<SourceFile> {
19 let mut files = Vec::new();
20 scan_recursive(root, root, &mut files);
21 files.sort_by(|a, b| a.relative_path.cmp(&b.relative_path));
22 files
23}
24
25fn scan_recursive(root: &Path, dir: &Path, files: &mut Vec<SourceFile>) {
26 let entries = match std::fs::read_dir(dir) {
27 Ok(entries) => entries,
28 Err(_) => return,
29 };
30
31 for entry in entries.filter_map(|e| e.ok()) {
32 let path = entry.path();
33
34 if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
36 if name.starts_with('.') || name == "target" || name == "node_modules" {
37 continue;
38 }
39 }
40
41 if path.is_dir() {
42 scan_recursive(root, &path, files);
43 } else if path.extension().map_or(false, |ext| ext == "rs") {
44 let relative = path.strip_prefix(root)
45 .unwrap_or(&path)
46 .to_string_lossy()
47 .to_string();
48 let size = std::fs::metadata(&path).map(|m| m.len()).unwrap_or(0);
49
50 files.push(SourceFile {
51 path: path.clone(),
52 relative_path: relative,
53 extension: "rs".to_string(),
54 size_bytes: size,
55 });
56 }
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn scan_finds_rust_files() {
66 let root = Path::new(env!("CARGO_MANIFEST_DIR"))
67 .parent()
68 .unwrap()
69 .parent()
70 .unwrap();
71 let files = scan_rust_files(root);
72 assert!(!files.is_empty(), "Should find .rs files in the project");
73 assert!(files.iter().any(|f| f.relative_path.contains("colony.rs")));
74 }
75}