From b4c4b875784fa80fbd53b96976320fa858a84eaa Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Thu, 21 Jul 2022 23:05:18 +0100 Subject: [PATCH] Sled & CGI error handling --- src/git_cgi.rs | 19 ++++++++++++++----- src/syntax_highlight.rs | 4 +--- src/database/indexer.rs | 12 +++++++++--- src/methods/index.rs | 7 ++++--- src/methods/repo.rs | 15 ++++++++++----- src/database/schema/repository.rs | 20 ++++++++++++-------- 6 files changed, 44 insertions(+), 33 deletions(-) diff --git a/src/git_cgi.rs b/src/git_cgi.rs index 029971a..b425da9 100644 --- a/src/git_cgi.rs +++ a/src/git_cgi.rs @@ -1,25 +1,30 @@ +use anyhow::{bail, Context, Result}; use axum::body::{boxed, Body}; use axum::http::header::HeaderName; use axum::http::HeaderValue; use axum::response::Response; +use httparse::Status; use std::str::FromStr; // https://en.wikipedia.org/wiki/Common_Gateway_Interface -pub fn cgi_to_response(buffer: &[u8]) -> Response { +pub fn cgi_to_response(buffer: &[u8]) -> Result { let mut headers = [httparse::EMPTY_HEADER; 10]; - let (body_offset, headers) = httparse::parse_headers(buffer, &mut headers) - .unwrap() - .unwrap(); + let (body_offset, headers) = match httparse::parse_headers(buffer, &mut headers)? { + Status::Complete(v) => v, + Status::Partial => bail!("Git returned a partial response over CGI"), + }; let mut response = Response::new(boxed(Body::from(buffer[body_offset..].to_vec()))); // TODO: extract status header for header in headers { response.headers_mut().insert( - HeaderName::from_str(header.name).unwrap(), - HeaderValue::from_bytes(header.value).unwrap(), + HeaderName::from_str(header.name) + .context("Failed to parse header name from Git over CGI")?, + HeaderValue::from_bytes(header.value) + .context("Failed to parse header value from Git over CGI")?, ); } - response + Ok(response) } diff --git a/src/syntax_highlight.rs b/src/syntax_highlight.rs index c75068d..c3e1c1e 100644 --- a/src/syntax_highlight.rs +++ a/src/syntax_highlight.rs @@ -18,9 +18,7 @@ ClassedHTMLGenerator::new_with_class_style(syntax, self.syntax_set, ClassStyle::Spaced); for line in LinesWithEndings::from(code) { - html_generator - .parse_html_for_line_which_includes_newline(line) - .unwrap(); + let _ = html_generator.parse_html_for_line_which_includes_newline(line); } format!( diff --git a/src/database/indexer.rs b/src/database/indexer.rs index 29ff671..bb25b4c 100644 --- a/src/database/indexer.rs +++ a/src/database/indexer.rs @@ -21,8 +21,9 @@ for repository in discovered { let relative = get_relative_path(scan_path, &repository); - let id = - Repository::open(db, relative).map_or_else(|| RepositoryId::new(db), |v| v.get().id); + let id = Repository::open(db, relative) + .unwrap() + .map_or_else(|| RepositoryId::new(db), |v| v.get().id); let name = relative.file_name().unwrap().to_string_lossy(); let description = std::fs::read(repository.join("description")).unwrap_or_default(); let description = Some(String::from_utf8_lossy(&description)).filter(|v| !v.is_empty()); @@ -39,7 +40,7 @@ } fn update_repository_reflog(scan_path: &Path, db: &sled::Db) { - for (relative_path, db_repository) in Repository::fetch_all(db) { + for (relative_path, db_repository) in Repository::fetch_all(db).unwrap() { let git_repository = git2::Repository::open(scan_path.join(&relative_path)).unwrap(); for reference in git_repository.references().unwrap() { @@ -59,7 +60,10 @@ info!("Refreshing indexes"); - let commit_tree = db_repository.get().commit_tree(db, &reference_name); + let commit_tree = db_repository + .get() + .commit_tree(db, &reference_name) + .unwrap(); if let (Some(latest_indexed), Ok(latest_commit)) = (commit_tree.fetch_latest_one(), reference.peel_to_commit()) diff --git a/src/methods/index.rs b/src/methods/index.rs index 7c92cd9..46e2a64 100644 --- a/src/methods/index.rs +++ a/src/methods/index.rs @@ -1,3 +1,4 @@ +use anyhow::Context; use std::collections::BTreeMap; use askama::Template; @@ -14,12 +15,12 @@ pub repositories: BTreeMap, Vec<&'a Repository<'a>>>, } -pub async fn handle(Extension(db): Extension) -> Response { +pub async fn handle(Extension(db): Extension) -> Result { let mut repositories: BTreeMap, Vec<&Repository<'_>>> = BTreeMap::new(); let fetched = tokio::task::spawn_blocking(move || Repository::fetch_all(&db)) .await - .unwrap(); + .context("Failed to join Tokio task")??; for (k, v) in &fetched { // TODO: fixme let mut split: Vec<_> = k.split('/').collect(); @@ -30,5 +31,5 @@ k.push(v.get()); } - into_response(&View { repositories }) + Ok(into_response(&View { repositories })) } diff --git a/src/methods/repo.rs b/src/methods/repo.rs index 9fe2ea4..dd7cb13 100644 --- a/src/methods/repo.rs +++ a/src/methods/repo.rs @@ -1,3 +1,4 @@ +use anyhow::Context; use std::{ fmt::{Debug, Display, Formatter}, io::Write, @@ -175,8 +176,9 @@ let open_repo = git.repo(repository_path).await?; let refs = open_repo.refs().await?; - let repository = crate::database::schema::repository::Repository::open(&db, &*repo).unwrap(); - let commit_tree = repository.get().commit_tree(&db, "refs/heads/master"); + let repository = crate::database::schema::repository::Repository::open(&db, &*repo)? + .context("Repository does not exist")?; + let commit_tree = repository.get().commit_tree(&db, "refs/heads/master")?; let commits = commit_tree.fetch_latest(11, 0).await; let commit_list = commits.iter().map(Yoke::get).collect(); @@ -237,8 +239,9 @@ let offset = query.offset.unwrap_or(0); let reference = format!("refs/heads/{}", query.branch.as_deref().unwrap_or("master")); - let repository = crate::database::schema::repository::Repository::open(&db, &*repo).unwrap(); - let commit_tree = repository.get().commit_tree(&db, &reference); + let repository = crate::database::schema::repository::Repository::open(&db, &*repo)? + .context("Repository does not exist")?; + let commit_tree = repository.get().commit_tree(&db, &reference)?; let mut commits = commit_tree.fetch_latest(101, offset).await; let next_offset = if commits.len() == 101 { @@ -277,7 +280,7 @@ .output() .unwrap(); - Ok(crate::git_cgi::cgi_to_response(&out.stdout)) + Ok(crate::git_cgi::cgi_to_response(&out.stdout)?) } pub async fn handle_git_upload_pack( @@ -299,7 +302,7 @@ child.stdin.as_mut().unwrap().write_all(&body).unwrap(); let out = child.wait_with_output().unwrap(); - Ok(crate::git_cgi::cgi_to_response(&out.stdout)) + Ok(crate::git_cgi::cgi_to_response(&out.stdout)?) } #[derive(Template)] diff --git a/src/database/schema/repository.rs b/src/database/schema/repository.rs index b8e9046..2b61783 100644 --- a/src/database/schema/repository.rs +++ a/src/database/schema/repository.rs @@ -1,6 +1,7 @@ use crate::database::schema::commit::CommitTree; use crate::database::schema::prefixes::TreePrefix; use crate::database::schema::Yoked; +use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; use sled::IVec; use std::borrow::Cow; @@ -31,7 +32,7 @@ pub type YokedRepository = Yoked>; impl Repository<'_> { - pub fn fetch_all(database: &sled::Db) -> BTreeMap { + pub fn fetch_all(database: &sled::Db) -> Result> { database .scan_prefix([TreePrefix::Repository as u8]) .filter_map(Result::ok) @@ -45,10 +46,9 @@ let value = Box::new(value); let value = - Yoke::try_attach_to_cart(value, |data: &IVec| bincode::deserialize(data)) - .unwrap(); + Yoke::try_attach_to_cart(value, |data: &IVec| bincode::deserialize(data))?; - (key, value) + Ok((key, value)) }) .collect() } @@ -62,10 +62,10 @@ .unwrap(); } - pub fn open>(database: &sled::Db, path: P) -> Option { + pub fn open>(database: &sled::Db, path: P) -> Result> { database .get(TreePrefix::repository_id(path)) - .unwrap() + .context("Failed to open indexed repository")? .map(|value| { // internally value is an Arc so it should already be stablederef but because // of reasons unbeknownst to me, sled has its own Arc implementation so we need @@ -73,17 +73,17 @@ let value = Box::new(value); Yoke::try_attach_to_cart(value, |data: &IVec| bincode::deserialize(data)) + .context("Failed to deserialise indexed repository") }) .transpose() - .unwrap() } - pub fn commit_tree(&self, database: &sled::Db, reference: &str) -> CommitTree { + pub fn commit_tree(&self, database: &sled::Db, reference: &str) -> Result { let tree = database .open_tree(TreePrefix::commit_id(self.id, reference)) - .unwrap(); + .context("Failed to open commit tree")?; - CommitTree::new(tree) + Ok(CommitTree::new(tree)) } } -- rgit 0.1.3