-
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?
Conversation
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.
Thanks for all your work on this! As we discussed after reviewing the code together, we still need to add a couple of tests to cover some edge cases. Also, since there are currently five commits, including one with unresolved conflicts, it’d be great to clean that up.
To keep the history tidy, you can run git rebase -i @~5
and squash the five commits down to two. Once that’s done, we should be in good shape.
src/server/api/routes.rs
Outdated
@@ -72,6 +80,10 @@ pub fn register_app< | |||
) | |||
.app_data(web::Data::new(state.clone())); | |||
|
|||
app = app | |||
.service(web::scope("/_git").service(get_blob)) |
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.
.service(web::scope("/_git").service(get_blob)) | |
.service(web::scope("/_stelae").service(get_blob)) |
src/server/api/routes.rs
Outdated
#[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 comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: move to api/stelae/mod.rs
src/server/api/routes.rs
Outdated
#[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 comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: api/stelae/requests/mod.rs
src/server/api/state.rs
Outdated
/// path to the Stelae archive | ||
fn archive_path(&self) -> &PathBuf; |
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.
suggestion: we don't need this, I think. Can get path from Archive
struct
tests/api/archive_basic_test.rs
Outdated
#[actix_web::test] | ||
async fn test_resolve_root_stele_all_repositories_request_with_full_path_expect_success() { | ||
let archive_path = |
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.
Although these tests initialize the basic archive, they also now test the _stelae
endpoint, while other tests test dynamic routes, which seems confusing.
suggestion: move new tests to a new test file
Also, please see our TESTING.md style guide for adding new tests. Usually we break down asserts into multiple tests. Ideally a single assert per test, but more realistically a single data repo per test in this case. But I wouldn't worry about this too much right now.
tests/api/archive_basic_test.rs
Outdated
|
||
// let git_repo = get_repository(&path, "law-html"); | ||
// let _ = git_repo.create_branch("test_branch"); | ||
println!("Testing law-html"); |
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.
suggestion: remove unnecessary comments and print statements
tests/api/archive_basic_test.rs
Outdated
|
||
let _ = git_repo.create_branch("test_branch"); | ||
|
||
let _ = git_repo.checkout("master"); |
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.
checking out master won't work in cases where a users' local default branch is configured to "main".
suggestion: use "default_branch" instead of "master" (and create it programmatically).
tests/api/archive_basic_test.rs
Outdated
.await; | ||
} | ||
|
||
async fn test_paths( |
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.
nitpick: test_stelae_paths
tests/api/archive_basic_test.rs
Outdated
} | ||
|
||
#[actix_web::test] | ||
async fn test_resolve_root_stele_law_html_file_content_with_different_branches_expect_success() { |
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.
suggestion: we'll also need a couple of tests when an archive is initialized as multihost, see test_archive_multihost.rs. so calling out to _stelae
endpont for stele_1
and stele_2
and expecting content to be resolved
suggestion 2: a test testing branch with a /
in it would also be useful, I think.
src/server/api/stelae/request/mod.rs
Outdated
@@ -0,0 +1,9 @@ | |||
use serde::Deserialize; | |||
/// Structure for |
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.
suggestion: please complete docstring
src/server/api/stelae/request/mod.rs
Outdated
/// Structure for | ||
#[derive(Debug, Deserialize)] | ||
pub struct StelaeQueryData { | ||
/// commit of the repo |
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.
/// commit of the repo | |
/// commit (or reference) to the repo. Can pass in `HEAD`, a branch ref (e.g. main), or a commit SHA. |
Description (e.g. "Related to ...", etc.)
Related to #54
Code review checklist (for code reviewer to complete)
Automated tests, benchmarks and linters
You can run the tests, lints and benchmarks that are run on CI locally with: