aboutsummaryrefslogtreecommitdiff
path: root/src/state.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/state.rs')
-rw-r--r--src/state.rs48
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())
}
}