diff options
Diffstat (limited to 'src/state.rs')
-rw-r--r-- | src/state.rs | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/src/state.rs b/src/state.rs index 1a88929..475302b 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,24 +1,46 @@ -use std::io; -use std::path::Path; - -use async_std::prelude::*; -use async_std::fs::read_dir; +use std::fs::read_dir; +use std::path::{Path, PathBuf}; +use eyre::Result; use git2::Repository; pub struct State { + pub root: PathBuf, pub data: Vec<Repository>, } +// TODO figure out how to make this return impl Stream without living in actual hell +// Heartbreaking: E0733 +fn find_repos_in(dir: impl AsRef<Path>) -> Result<Vec<Repository>> { + let dir = dir.as_ref(); + let dir = read_dir(dir)?; + let mut result = vec![]; + for subdir in dir { + match subdir { + Ok(subdir) => { + match Repository::open_bare(subdir.path()) { + Ok(repo) => result.push(repo), + Err(err) if err.class() == git2::ErrorClass::Repository && err.code() == git2::ErrorCode::NotFound => { + result.extend(find_repos_in(subdir.path())?) + } + // TODO handle in a non-god-awful way + Err(err) => panic!("{}", err), + } + } + Err(_) => {}, + } + } + Ok(result) +} + impl State { - pub async fn discover(root: impl AsRef<Path>) -> io::Result<Self> { + pub async fn discover(root: impl AsRef<Path>) -> Result<Self> { let root = root.as_ref(); - let dir = read_dir(root).await?; - let data = dir - .filter_map(|subdir| { - subdir.ok().and_then(|subdir| Repository::open_bare(&subdir.path()).ok()) - }) - .collect().await; - Ok(Self { data }) + let data = find_repos_in(root)?; + Ok(Self { root: root.to_owned(), data }) + } + + pub fn relative_path<'a>(&'a self, subdir: &'a Path) -> &'a Path { + subdir.strip_prefix(&self.root).unwrap_or_else(|_| subdir.as_ref()) } } |