use std::path::Path;
const MAX_PROJECT_TRAVERSAL_DEPTH: usize = 10;
pub fn find_project_root(file_path: &Path) -> Option<String> {
let mut current = file_path.parent();
let mut depth = 0;
while let Some(dir) = current {
if depth >= MAX_PROJECT_TRAVERSAL_DEPTH {
break;
}
depth += 1;
let zimignore_path = dir.join(".zimignore");
if zimignore_path.exists() {
if dir == Path::new(".") {
if let Ok(abs_path) = std::env::current_dir() {
return abs_path
.file_name()
.and_then(|name| name.to_str())
.map(|s| s.to_string());
}
}
return dir
.file_name()
.and_then(|name| name.to_str())
.map(|s| s.to_string());
}
current = dir.parent();
}
None
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::TempDir;
#[test]
fn test_find_project_root() {
let temp_dir = TempDir::new().unwrap();
let project_dir = temp_dir.path().join("my-project");
let mixes_dir = project_dir.join("mixes");
let nested_dir = mixes_dir.join("old");
fs::create_dir_all(&nested_dir).unwrap();
fs::write(project_dir.join(".zimignore"), "# test").unwrap();
let file_path = nested_dir.join("test.wav");
fs::write(&file_path, "").unwrap();
let result = find_project_root(&file_path);
assert_eq!(result, Some("my-project".to_string()));
}
#[test]
fn test_find_project_root_no_zimignore() {
let temp_dir = TempDir::new().unwrap();
let orphan_dir = temp_dir.path().join("orphan");
fs::create_dir_all(&orphan_dir).unwrap();
let orphan_file = orphan_dir.join("test.wav");
fs::write(&orphan_file, "").unwrap();
let result = find_project_root(&orphan_file);
assert_eq!(result, None);
}
#[test]
fn test_find_project_root_nested() {
let temp_dir = TempDir::new().unwrap();
let project_dir = temp_dir.path().join("test-project");
let mut nested = project_dir.join("a");
for _ in 0..3 {
nested = nested.join("nested");
}
fs::create_dir_all(&nested).unwrap();
fs::write(project_dir.join(".zimignore"), "# test").unwrap();
let file_path = nested.join("deep.wav");
fs::write(&file_path, "").unwrap();
let result = find_project_root(&file_path);
assert_eq!(result, Some("test-project".to_string()));
}
}