From d5c7a77716c3b1b01778903056819e809ada4edc Mon Sep 17 00:00:00 2001 From: Louis Knight-Webb Date: Thu, 19 Jun 2025 11:58:30 -0400 Subject: [PATCH] Task attempt 5d105b9b-dfe8-422b-b529-530cbf7e2dfe - Final changes --- backend/Cargo.toml | 1 + backend/src/routes/projects.rs | 107 ++++++++++++++++----------------- 2 files changed, 52 insertions(+), 56 deletions(-) diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 3f5bca6e..28695d92 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -32,6 +32,7 @@ rust-embed = "8.2" mime_guess = "2.0" directories = "6.0.0" open = "5.3.2" +ignore = "0.4" [build-dependencies] ts-rs = { version = "9.0", features = ["uuid-impl", "chrono-impl"] } diff --git a/backend/src/routes/projects.rs b/backend/src/routes/projects.rs index df9d2ca1..8007087a 100644 --- a/backend/src/routes/projects.rs +++ b/backend/src/routes/projects.rs @@ -286,6 +286,7 @@ async fn search_files_in_repo( repo_path: &str, query: &str, ) -> Result, Box> { + use ignore::WalkBuilder; use std::path::Path; let repo_path = Path::new(repo_path); @@ -297,71 +298,65 @@ async fn search_files_in_repo( let mut results = Vec::new(); let query_lower = query.to_lowercase(); - // Recursively search through the repository - fn walk_dir( - dir: &Path, - repo_root: &Path, - query: &str, - results: &mut Vec, - ) -> Result<(), Box> { - if dir.file_name().map_or(false, |name| name == ".git") { - return Ok(()); + // Use ignore::WalkBuilder to respect gitignore files + let walker = WalkBuilder::new(repo_path) + .git_ignore(true) + .git_global(true) + .git_exclude(true) + .hidden(false) + .build(); + + for result in walker { + let entry = result?; + let path = entry.path(); + + // Skip the root directory itself + if path == repo_path { + continue; } - for entry in std::fs::read_dir(dir)? { - let entry = entry?; - let path = entry.path(); + let relative_path = path.strip_prefix(repo_path)?; + + // Skip .git directory and its contents + if relative_path.components().any(|component| component.as_os_str() == ".git") { + continue; + } + let relative_path_str = relative_path.to_string_lossy().to_lowercase(); - // Skip .git directories - if path.is_dir() && path.file_name().map_or(false, |name| name == ".git") { - continue; - } + let file_name = path + .file_name() + .map(|name| name.to_string_lossy().to_lowercase()) + .unwrap_or_default(); - let relative_path = path.strip_prefix(repo_root)?; - let relative_path_str = relative_path.to_string_lossy().to_lowercase(); - - let file_name = path - .file_name() + // Check for matches + if file_name.contains(&query_lower) { + results.push(SearchResult { + path: relative_path.to_string_lossy().to_string(), + is_file: path.is_file(), + match_type: SearchMatchType::FileName, + }); + } else if relative_path_str.contains(&query_lower) { + // Check if it's a directory name match or full path match + let match_type = if path + .parent() + .and_then(|p| p.file_name()) .map(|name| name.to_string_lossy().to_lowercase()) - .unwrap_or_default(); + .unwrap_or_default() + .contains(&query_lower) + { + SearchMatchType::DirectoryName + } else { + SearchMatchType::FullPath + }; - // Check for matches - if file_name.contains(query) { - results.push(SearchResult { - path: relative_path.to_string_lossy().to_string(), - is_file: path.is_file(), - match_type: SearchMatchType::FileName, - }); - } else if relative_path_str.contains(query) { - // Check if it's a directory name match or full path match - let match_type = if path - .parent() - .and_then(|p| p.file_name()) - .map(|name| name.to_string_lossy().to_lowercase()) - .unwrap_or_default() - .contains(query) - { - SearchMatchType::DirectoryName - } else { - SearchMatchType::FullPath - }; - - results.push(SearchResult { - path: relative_path.to_string_lossy().to_string(), - is_file: path.is_file(), - match_type, - }); - } - - if path.is_dir() { - walk_dir(&path, repo_root, query, results)?; - } + results.push(SearchResult { + path: relative_path.to_string_lossy().to_string(), + is_file: path.is_file(), + match_type, + }); } - Ok(()) } - walk_dir(repo_path, repo_path, &query_lower, &mut results)?; - // Sort results by priority: FileName > DirectoryName > FullPath results.sort_by(|a, b| { use SearchMatchType::*;