-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bojangalic/merge stelae and git command #64
base: main
Are you sure you want to change the base?
Changes from 5 commits
77cb158
73925fd
651bbb4
98b132f
71ccad2
9f2660b
ba75f36
83eb359
e496668
b043e23
fb256c5
ea02fe0
7b51d53
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,10 +11,18 @@ use actix_service::ServiceFactory; | |
use actix_web::{ | ||
body::MessageBody, | ||
dev::{ServiceRequest, ServiceResponse}, | ||
guard, web, App, Error, Scope, | ||
guard, route, web, App, Error, HttpResponse, Responder, Scope, | ||
}; | ||
use serde::Deserialize; | ||
|
||
use super::state::App as AppState; | ||
use super::{serve::serve, state::Global, versions::versions}; | ||
use crate::utils::git::{Repo, GIT_REQUEST_NOT_FOUND}; | ||
use crate::utils::http::get_contenttype; | ||
use crate::utils::paths::clean_path; | ||
use git2::{self, ErrorCode}; | ||
|
||
use super::super::errors::HTTPError; | ||
|
||
/// Name of the header to guard current documents | ||
static HEADER_NAME: OnceLock<String> = OnceLock::new(); | ||
|
@@ -72,6 +80,10 @@ pub fn register_app< | |
) | ||
.app_data(web::Data::new(state.clone())); | ||
|
||
app = app | ||
.service(web::scope("/_git").service(get_blob)) | ||
.app_data(web::Data::new(state.clone())); | ||
|
||
app = register_dynamic_routes(app, state)?; | ||
Ok(app) | ||
} | ||
|
@@ -315,3 +327,63 @@ fn register_dependent_routes( | |
} | ||
Ok(()) | ||
} | ||
|
||
/// Structure for | ||
#[derive(Debug, Deserialize)] | ||
struct Info { | ||
/// commit of the repo | ||
commitish: String, | ||
/// path of the file | ||
remainder: Option<String>, | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: |
||
|
||
/// Return the content in the stelae archive in the `{namespace}/{name}` | ||
/// repo at the `commitish` commit at the `remainder` path. | ||
/// Return 404 if any are not found or there are any errors. | ||
#[route("/{namespace}/{name}", method = "GET", method = "HEAD")] | ||
#[tracing::instrument(name = "Retrieving a Git blob", skip(path, data, info))] | ||
#[expect( | ||
clippy::future_not_send, | ||
reason = "We don't worry about git2-rs not implementing `Send` trait" | ||
)] | ||
async fn get_blob( | ||
path: web::Path<(String, String)>, | ||
info: web::Query<Info>, | ||
data: web::Data<AppState>, | ||
) -> impl Responder { | ||
let (namespace, name) = path.into_inner(); | ||
let info_struct: Info = info.into_inner(); | ||
let commitish = info_struct.commitish; | ||
let remainder = info_struct.remainder.unwrap_or_default(); | ||
let archive_path = &data.archive_path; | ||
let blob = Repo::find_blob(archive_path, &namespace, &name, &remainder, &commitish); | ||
let blob_path = clean_path(&remainder); | ||
let contenttype = get_contenttype(&blob_path); | ||
match blob { | ||
Ok(content) => HttpResponse::Ok().insert_header(contenttype).body(content), | ||
Err(error) => blob_error_response(&error, &namespace, &name), | ||
} | ||
} | ||
|
||
/// A centralised place to match potentially unsafe internal errors to safe user-facing error responses | ||
#[expect(clippy::wildcard_enum_match_arm, reason = "Allows _ for enum matching")] | ||
#[tracing::instrument(name = "Error with Git blob request", skip(error, namespace, name))] | ||
fn blob_error_response(error: &anyhow::Error, namespace: &str, name: &str) -> HttpResponse { | ||
tracing::error!("{error}",); | ||
if let Some(git_error) = error.downcast_ref::<git2::Error>() { | ||
return match git_error.code() { | ||
// TODO: check this is the right error | ||
ErrorCode::NotFound => { | ||
HttpResponse::NotFound().body(format!("repo {namespace}/{name} does not exist")) | ||
} | ||
_ => HttpResponse::InternalServerError().body("Unexpected Git error"), | ||
}; | ||
} | ||
match error { | ||
// TODO: Obviously it's better to use custom `Error` types | ||
_ if error.to_string() == GIT_REQUEST_NOT_FOUND => { | ||
HttpResponse::NotFound().body(HTTPError::NotFound.to_string()) | ||
} | ||
_ => HttpResponse::InternalServerError().body(HTTPError::InternalServerError.to_string()), | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: move to |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,8 @@ pub trait Global { | |
fn archive(&self) -> &Archive; | ||
/// Database connection | ||
fn db(&self) -> &db::DatabaseConnection; | ||
/// path to the Stelae archive | ||
fn archive_path(&self) -> &PathBuf; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: we don't need this, I think. Can get path from |
||
} | ||
|
||
/// Application state | ||
|
@@ -22,6 +24,8 @@ pub struct App { | |
pub archive: Archive, | ||
/// Database connection | ||
pub db: db::DatabaseConnection, | ||
/// path to the Stelae archive | ||
pub archive_path: PathBuf, | ||
} | ||
|
||
impl Global for App { | ||
|
@@ -32,6 +36,10 @@ impl Global for App { | |
fn db(&self) -> &db::DatabaseConnection { | ||
&self.db | ||
} | ||
|
||
fn archive_path(&self) -> &PathBuf { | ||
&self.archive_path | ||
} | ||
} | ||
|
||
/// Repository to serve | ||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,5 +5,4 @@ | |
pub mod api; | ||
pub mod app; | ||
pub mod errors; | ||
pub mod git; | ||
pub mod tracing; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.