diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/src/main.rs b/src/main.rs index 795cf41..b248ae7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +use std::path::Path; + use askama::Template; use async_std::sync::{Arc, Mutex}; use eyre::Result; @@ -31,16 +33,21 @@ async fn main() -> Result<()> { let state = State::discover(root).await?; // unfortunately, the State has to be both Send and Sync, but git2::Repository is not Sync // and even an Arc<RwLock<State>> isn't Sync if State isn't Sync, it has to be a Mutex to get Sync - // TODO do something smarter for that + // TODO do something smarter for that like maybe just a vec of repo paths let mut app = tide::with_state(Arc::new(Mutex::new(state))); app.at("/").get(index); - app.at("/*repo").get(|_| async { Ok("bruh") }); - app.at("/*repo/tree").get(|_| async { Ok("bruh tree") }); + { + let mut repo = app.at("/*repo"); + repo.get(about); + repo.at("/tree").get(|_| async { Ok("bruh tree") }); + } app.listen(("127.0.0.1", port)).await?; Ok(()) } -async fn index(req: tide::Request<Arc<Mutex<State>>>) -> tide::Result { +type Request = tide::Request<Arc<Mutex<State>>>; + +async fn index(req: Request) -> tide::Result { let state = req.state(); let state = state.lock_arc().await; for repo in &state.data { @@ -53,3 +60,52 @@ async fn index(req: tide::Request<Arc<Mutex<State>>>) -> tide::Result { } Ok(IndexTemplate { state: state.deref() }.into()) } + +async fn about(req: Request) -> tide::Result { + let repo_rel_path = req.param("repo").expect("no repo in repo-based URL?"); + let state = req.state(); + let state = state.lock_arc().await; + let repo = state.data.iter() + .find(|repo| state.relative_path(repo.path()) == Path::new(repo_rel_path)); + let repo = match repo { + Some(x) => x, + None => return Ok("bruh that's not a real repo".into()), + }; + + let head = repo.head(); + let head = match head { + Ok(x) => x, + Err(err) => return Ok(format!("bruh that repo has no HEAD: {}", err).into()), + }; + + let head_tree = head.peel_to_tree(); + let head_tree = match head_tree { + Ok(x) => x, + Err(err) => return Ok(format!("bruh that repo's HEAD has no tree: {}", err).into()), + }; + + let tree_readme = head_tree.get_path(Path::new("README.md")); + let tree_readme = match tree_readme { + Ok(x) => x, + Err(err) => return Ok(format!("that repo's HEAD tree has no README.md: {}", err).into()), + }; + + let tree_readme_object = tree_readme.to_object(repo); + let tree_readme_object = match tree_readme_object { + Ok(x) => x, + Err(err) => return Ok(format!("that repo's HEAD tree has no README.md: {}", err).into()), + }; + + let head_readme_blob = tree_readme_object.into_blob(); + let head_readme_blob = match head_readme_blob { + Ok(x) => x, + Err(_) => return Ok("somehow that README wasn't a file".into()), + }; + + let body = if head_readme_blob.is_binary() { + tide::Body::from(head_readme_blob.content()) + } else { + tide::Body::from(String::from_utf8_lossy(head_readme_blob.content()).into_owned()) + }; + Ok(body.into()) +} |