git_repos/
walkdir.rs

1use std::{
2    fs::{self, ReadDir},
3    path::PathBuf,
4};
5
6use nill::{Nil, NIL};
7
8use crate::common::{error::Result, utils::has_git_dir};
9
10#[derive(Debug, Default)]
11pub struct Options {
12    pub depth: u32,
13}
14
15#[derive(Debug, Default)]
16pub struct WalkDir {
17    pub path: PathBuf,
18    pub opts: Options,
19
20    pub rdirs: Vec<ReadDir>,
21    pub repos: Vec<PathBuf>,
22}
23
24impl WalkDir {
25    pub fn new<P: Into<PathBuf>>(path: P) -> Self {
26        WalkDir { path: path.into(), ..Default::default() }
27    }
28
29    #[inline]
30    fn find_next_dir(&mut self, mut rdir: ReadDir) -> Result<Nil> {
31        while let Some(entry) = rdir.next() {
32            let path = entry?.path();
33
34            if !path.is_dir() {
35                continue;
36            }
37
38            if has_git_dir(&path) {
39                self.repos.push(path);
40            } else {
41                self.rdirs.push(fs::read_dir(path)?);
42            }
43        }
44
45        Ok(NIL)
46    }
47
48    pub fn find_repo_dirs(&mut self) -> Result<&[PathBuf]> {
49        debug_assert_eq!(self.rdirs.len(), 0);
50        debug_assert_eq!(self.repos.len(), 0);
51
52        self.rdirs.push(fs::read_dir(&self.path)?);
53
54        while let Some(rdir) = self.rdirs.pop() {
55            self.find_next_dir(rdir)?;
56        }
57
58        Ok(&self.repos)
59    }
60}