use heroforge_core::{Repository, Result};
use std::fs;
fn main() -> Result<()> {
let tmp_dir = std::env::temp_dir().join("heroforge_find_example");
let _ = fs::remove_dir_all(&tmp_dir);
fs::create_dir_all(&tmp_dir)?;
let repo_path = tmp_dir.join("project.forge");
println!("=== Advanced Find Operations Example ===\n");
let repo = Repository::init(&repo_path)?;
let _init_hash = repo
.commit_builder()
.message("Create project structure")
.author("developer")
.initial()
.file("README.md", b"# Project\n")
.file("Cargo.toml", b"[package]\nname = \"myproject\"\n")
.file("Cargo.lock", b"# lock file\n")
.file(".gitignore", b"target/\n*.log\n")
.file(".env", b"SECRET=abc123\n")
.file(".env.example", b"SECRET=\n")
.file("src/main.rs", b"fn main() {}\n")
.file("src/lib.rs", b"pub mod api;\npub mod db;\n")
.file("src/api/mod.rs", b"pub mod handlers;\npub mod routes;\n")
.file("src/api/handlers.rs", b"pub fn handle() {}\n")
.file("src/api/routes.rs", b"pub fn routes() {}\n")
.file("src/db/mod.rs", b"pub mod models;\npub mod queries;\n")
.file("src/db/models.rs", b"pub struct User {}\n")
.file("src/db/queries.rs", b"pub fn find_user() {}\n")
.file("tests/integration.rs", b"#[test] fn test() {}\n")
.file("tests/api_test.rs", b"#[test] fn api() {}\n")
.file("docs/README.md", b"# Documentation\n")
.file("docs/api/endpoints.md", b"# API Endpoints\n")
.file("docs/api/auth.md", b"# Authentication\n")
.file("docs/guides/setup.md", b"# Setup Guide\n")
.file("config/default.toml", b"[server]\nport = 8080\n")
.file("config/production.toml", b"[server]\nport = 80\n")
.file(
"target/debug/myproject",
b"binary content here which is larger than other files to test size filtering",
)
.file("target/debug/deps/lib.rlib", b"rlib content\n")
.file("node_modules/package/index.js", b"module.exports = {};\n")
.file("logs/app.log", b"2024-01-01 INFO: Started\n")
.file("logs/error.log", b"2024-01-01 ERROR: Something\n")
.file(".git/config", b"[core]\n")
.file(".vscode/settings.json", b"{}\n")
.execute()?;
println!(
"Created project with {} files\n",
repo.files().on_trunk().list()?.len()
);
println!("=== Basic Pattern Matching ===\n");
let rust_files = repo.fs().find().pattern("**/*.rs").execute()?;
println!("All Rust files ({} found):", rust_files.count);
for f in &rust_files.files {
println!(" {}", f.path);
}
println!();
let md_files = repo.fs().find().pattern("**/*.md").paths()?;
println!("All Markdown files ({} found):", md_files.len());
for p in &md_files {
println!(" {}", p);
}
println!();
let toml_count = repo.fs().find().pattern("**/*.toml").count()?;
println!("TOML files: {} found\n", toml_count);
println!("=== Ignore Patterns ===\n");
let src_no_tests = repo
.fs()
.find()
.pattern("**/*.rs")
.ignore("tests/**")
.paths()?;
println!("Rust files (excluding tests):");
for p in &src_no_tests {
println!(" {}", p);
}
println!();
let clean_files = repo
.fs()
.find()
.pattern("**/*")
.use_gitignore()
.ignore("*.lock")
.ignore("logs/**")
.paths()?;
println!(
"Files with gitignore defaults ({} found):",
clean_files.len()
);
for p in clean_files.iter().take(10) {
println!(" {}", p);
}
if clean_files.len() > 10 {
println!(" ... and {} more", clean_files.len() - 10);
}
println!();
println!("=== Hidden File Handling ===\n");
let all_files = repo.fs().find().pattern("**/*").count()?;
println!("All files: {}", all_files);
let visible_files = repo.fs().find().pattern("**/*").ignore_hidden().count()?;
println!("Visible files (no hidden): {}", visible_files);
let hidden_files = repo.fs().find().pattern("**/.*").paths()?;
println!("Hidden files ({} found):", hidden_files.len());
for p in &hidden_files {
println!(" {}", p);
}
println!();
println!("=== Directory Scoping ===\n");
let src_files = repo.fs().find().in_dir("src").pattern("**/*.rs").paths()?;
println!("Rust files in src/ ({} found):", src_files.len());
for p in &src_files {
println!(" {}", p);
}
println!();
let doc_files = repo.fs().find().in_dir("docs").pattern("**/*").paths()?;
println!("Files in docs/ ({} found):", doc_files.len());
for p in &doc_files {
println!(" {}", p);
}
println!();
println!("=== Depth Limiting ===\n");
let root_files = repo.fs().find().max_depth(0).pattern("*").paths()?;
println!("Root level files ({} found):", root_files.len());
for p in &root_files {
println!(" {}", p);
}
println!();
let shallow_files = repo.fs().find().max_depth(1).pattern("**/*").paths()?;
println!("Files up to depth 1 ({} found):", shallow_files.len());
for p in &shallow_files {
println!(" {}", p);
}
println!();
println!("=== Multiple Patterns ===\n");
let source_files = repo
.fs()
.find()
.patterns(&["**/*.rs", "**/*.toml"])
.ignore_hidden()
.paths()?;
println!("Rust and TOML files ({} found):", source_files.len());
for p in &source_files {
println!(" {}", p);
}
println!();
let clean_src = repo
.fs()
.find()
.pattern("**/*")
.ignore_patterns(&["target/**", "node_modules/**", "logs/**", "*.log", "*.lock"])
.ignore_hidden()
.paths()?;
println!("Clean source files ({} found):", clean_src.len());
for p in &clean_src {
println!(" {}", p);
}
println!();
println!("=== Case Insensitive Matching ===\n");
let readme_files = repo
.fs()
.find()
.pattern("**/readme*")
.ignore_case()
.paths()?;
println!("README files (case-insensitive):");
for p in &readme_files {
println!(" {}", p);
}
println!();
println!("=== Find with Metadata ===\n");
let result = repo
.fs()
.find()
.in_dir("src")
.pattern("**/*.rs")
.execute()?;
println!("Search results for src/**/*.rs:");
println!(" Files found: {}", result.count);
println!(" Directories traversed: {}", result.dirs_traversed);
println!(" Files:");
for f in &result.files {
println!(
" {} (hash: {}..., size: {:?})",
f.path,
&f.hash[..8],
f.size
);
}
println!();
println!("=== Practical Examples ===\n");
let api_files = repo.fs().find().pattern("**/*api*").ignore_case().paths()?;
println!("API-related files:");
for p in &api_files {
println!(" {}", p);
}
println!();
let config_files = repo
.fs()
.find()
.patterns(&["**/*.toml", "**/*.json", "**/config/**"])
.ignore_hidden()
.paths()?;
println!("Configuration files:");
for p in &config_files {
println!(" {}", p);
}
println!();
let should_ignore = repo
.fs()
.find()
.patterns(&["target/**", "node_modules/**", "*.log", "*.lock"])
.paths()?;
println!("Files that should typically be gitignored:");
for p in &should_ignore {
println!(" {}", p);
}
let _ = fs::remove_dir_all(&tmp_dir);
println!("\n=== Example completed successfully! ===");
Ok(())
}