aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs64
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())
+}