git_repos/
find.rs

1use std::{
2    fs,
3    path::{Path, PathBuf},
4};
5
6/// Finds repositories recursively, returning their path
7pub fn find_repo_paths(path: &Path) -> Result<Vec<PathBuf>, String> {
8    let mut repos = Vec::new();
9
10    let git_dir = path.join(".git");
11
12    if git_dir.exists() {
13        repos.push(path.to_path_buf());
14    } else {
15        match fs::read_dir(path) {
16            Ok(contents) => {
17                for content in contents {
18                    match content {
19                        Ok(entry) => {
20                            let path = entry.path();
21                            if path.is_symlink() {
22                                continue;
23                            }
24                            if path.is_dir() {
25                                match find_repo_paths(&path) {
26                                    Ok(ref mut r) => repos.append(r),
27                                    Err(error) => return Err(error),
28                                }
29                            }
30                        },
31                        Err(e) => {
32                            return Err(format!("Error accessing directory: {}", e));
33                        },
34                    };
35                }
36            },
37            Err(e) => {
38                return Err(format!("Failed to open \"{}\": {}", &path.display(), match e.kind() {
39                    std::io::ErrorKind::NotFound => String::from("not found"),
40                    _ => format!("{:?}", e.kind()),
41                }));
42            },
43        };
44    }
45
46    Ok(repos)
47}