feat(lib/git): add HTTP handler tree with routes and errors across analysis, archives, blobs, branches, commits, conflicts, content, diffs, hooks, lfs, logs, maintenance, packs, patches, pipelines, refs, remotes, repos, signatures, submodules, tags, trees
ZhenYi committed
Added lib/git/src/handler/analysis/code_activity.rs lib/git/src/handler/analysis/code_activity.rs +28 −0 View lib/git/src/handler/analysis/code_activity.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::analysis::CodeActivityDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct CodeActivityQuery {
12 #[serde(default)]
13 pub branch: Option<String>,
14}
15
16pub async fn code_activity(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<crate::handler::RepoPath>,
20 Query(q): Query<CodeActivityQuery>,
21) -> Result<AppResponseData<CodeActivityDto>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .analysis_code_activity(path.space_name, path.repo_name, q.branch)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/analysis/contributors.rs lib/git/src/handler/analysis/contributors.rs +21 −0 View lib/git/src/handler/analysis/contributors.rs
@@ -0,0 +1,21 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::analysis::ContributorStatDto;
9
10pub async fn contributors(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<crate::handler::RepoPath>,
14) -> Result<AppResponseData<Vec<ContributorStatDto>>, ApiError> {
15 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
16 let out = service
17 .analysis_contributors(path.space_name, path.repo_name)
18 .await
19 .map_err(GitApiError::from)?;
20 Ok(AppResponseData::ok(out))
21}
No newline at end of file
Added lib/git/src/handler/analysis/languages.rs lib/git/src/handler/analysis/languages.rs +21 −0 View lib/git/src/handler/analysis/languages.rs
@@ -0,0 +1,21 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::require_writer;
7use crate::service::GitService;
8use crate::service::analysis::LanguageStatDto;
9
10pub async fn languages(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<crate::handler::RepoPath>,
14) -> Result<AppResponseData<Vec<LanguageStatDto>>, ApiError> {
15 let (_ctx, _uid) = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
16 let out = service
17 .analysis_languages(path.space_name, path.repo_name)
18 .await
19 .map_err(GitApiError::from)?;
20 Ok(AppResponseData::ok(out))
21}
No newline at end of file
Added lib/git/src/handler/analysis/languages_read.rs lib/git/src/handler/analysis/languages_read.rs +21 −0 View lib/git/src/handler/analysis/languages_read.rs
@@ -0,0 +1,21 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::analysis::LanguageStatDto;
9
10pub async fn languages_read(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<crate::handler::RepoPath>,
14) -> Result<AppResponseData<Vec<LanguageStatDto>>, ApiError> {
15 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
16 let out = service
17 .analysis_languages_read(path.space_name, path.repo_name)
18 .await
19 .map_err(GitApiError::from)?;
20 Ok(AppResponseData::ok(out))
21}
No newline at end of file
Added lib/git/src/handler/analysis/mod.rs lib/git/src/handler/analysis/mod.rs +4 −0 View lib/git/src/handler/analysis/mod.rs
@@ -0,0 +1,4 @@
1pub mod code_activity;
2pub mod contributors;
3pub mod languages;
4pub mod languages_read;
No newline at end of file
Added lib/git/src/handler/archives/create.rs lib/git/src/handler/archives/create.rs +29 −0 View lib/git/src/handler/archives/create.rs
@@ -0,0 +1,29 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::{RepoPathRev, require_writer};
8use crate::service::GitService;
9use crate::service::archives::{ArchiveOptionsDto, ArchiveResultDto};
10
11pub async fn create(
12 State(service): State<GitService>,
13 session: Session,
14 Path(path): Path<RepoPathRev>,
15 Json(opts): Json<ArchiveOptionsDto>,
16) -> Result<AppResponseData<ArchiveResultDto>, ApiError> {
17 require_writer(
18 &service,
19 &session,
20 path.space_name.clone(),
21 path.repo_name.clone(),
22 )
23 .await?;
24 let out = service
25 .archive_create(path.space_name, path.repo_name, path.revision, opts)
26 .await
27 .map_err(GitApiError::from)?;
28 Ok(AppResponseData::ok(out))
29}
No newline at end of file
Added lib/git/src/handler/archives/create_bundle.rs lib/git/src/handler/archives/create_bundle.rs +21 −0 View lib/git/src/handler/archives/create_bundle.rs
@@ -0,0 +1,21 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::{RepoPath, require_writer};
7use crate::service::GitService;
8use crate::service::archives::ArchiveResultDto;
9
10pub async fn create_bundle(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<RepoPath>,
14) -> Result<AppResponseData<ArchiveResultDto>, ApiError> {
15 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
16 let out = service
17 .archive_create_bundle(path.space_name, path.repo_name)
18 .await
19 .map_err(GitApiError::from)?;
20 Ok(AppResponseData::ok(out))
21}
No newline at end of file
Added lib/git/src/handler/archives/download.rs lib/git/src/handler/archives/download.rs +28 −0 View lib/git/src/handler/archives/download.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::{RepoPathRev, resolve_reader};
7use crate::service::GitService;
8use crate::service::archives::{ArchiveOptionsDto, ArchiveResultDto};
9
10pub async fn download(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<RepoPathRev>,
14 Query(opts): Query<ArchiveOptionsDto>,
15) -> Result<AppResponseData<ArchiveResultDto>, ApiError> {
16 resolve_reader(
17 &service,
18 &session,
19 path.space_name.clone(),
20 path.repo_name.clone(),
21 )
22 .await?;
23 let out = service
24 .archive_download(path.space_name, path.repo_name, path.revision, opts)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/archives/mod.rs lib/git/src/handler/archives/mod.rs +3 −0 View lib/git/src/handler/archives/mod.rs
@@ -0,0 +1,3 @@
1pub mod create;
2pub mod create_bundle;
3pub mod download;
No newline at end of file
Added lib/git/src/handler/blobs/content.rs lib/git/src/handler/blobs/content.rs +28 −0 View lib/git/src/handler/blobs/content.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::blobs::BlobContentDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct BlobPath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub oid: String,
15}
16
17pub async fn blob_content(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<BlobPath>,
21) -> Result<AppResponseData<BlobContentDto>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .blob_content(path.space_name, path.repo_name, path.oid)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/blobs/list_lfs_pointers.rs lib/git/src/handler/blobs/list_lfs_pointers.rs +35 −0 View lib/git/src/handler/blobs/list_lfs_pointers.rs
@@ -0,0 +1,35 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::blobs::LfsPointerDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct RepoQuery {
12 pub space_name: String,
13 pub repo_name: String,
14}
15
16#[derive(Debug, Clone, serde::Deserialize)]
17pub struct LfsPointerQuery {
18 pub revision: String,
19 #[serde(default)]
20 pub limit: Option<u32>,
21}
22
23pub async fn list_lfs_pointers(
24 State(service): State<GitService>,
25 session: Session,
26 Path(path): Path<RepoQuery>,
27 Query(q): Query<LfsPointerQuery>,
28) -> Result<AppResponseData<Vec<LfsPointerDto>>, ApiError> {
29 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
30 let out = service
31 .list_lfs_pointers(path.space_name, path.repo_name, q.revision, q.limit)
32 .await
33 .map_err(GitApiError::from)?;
34 Ok(AppResponseData::ok(out))
35}
No newline at end of file
Added lib/git/src/handler/blobs/metadata.rs lib/git/src/handler/blobs/metadata.rs +28 −0 View lib/git/src/handler/blobs/metadata.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::blobs::BlobMetaDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct BlobPath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub oid: String,
15}
16
17pub async fn blob_metadata(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<BlobPath>,
21) -> Result<AppResponseData<BlobMetaDto>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .blob_metadata(path.space_name, path.repo_name, path.oid)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/blobs/mod.rs lib/git/src/handler/blobs/mod.rs +4 −0 View lib/git/src/handler/blobs/mod.rs
@@ -0,0 +1,4 @@
1pub mod content;
2pub mod list_lfs_pointers;
3pub mod metadata;
4pub mod raw_download;
No newline at end of file
Added lib/git/src/handler/blobs/raw_download.rs lib/git/src/handler/blobs/raw_download.rs +28 −0 View lib/git/src/handler/blobs/raw_download.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::blobs::RawDownloadDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct BlobPath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub oid: String,
15}
16
17pub async fn blob_raw_download(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<BlobPath>,
21) -> Result<AppResponseData<RawDownloadDto>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .blob_raw_download(path.space_name, path.repo_name, path.oid)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/branches/create.rs lib/git/src/handler/branches/create.rs +23 −0 View lib/git/src/handler/branches/create.rs
@@ -0,0 +1,23 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::require_writer;
8use crate::service::branches::{BranchDto, CreateBranchCmd};
9use crate::service::GitService;
10
11pub async fn create_branch(
12 State(service): State<GitService>,
13 session: Session,
14 Path(path): Path<crate::handler::RepoPath>,
15 Json(cmd): Json<CreateBranchCmd>,
16) -> Result<AppResponseData<BranchDto>, ApiError> {
17 let _ = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
18 let out = service
19 .create_branch(path.space_name, path.repo_name, cmd)
20 .await
21 .map_err(GitApiError::from)?;
22 Ok(AppResponseData::ok(out))
23}
No newline at end of file
Added lib/git/src/handler/branches/delete.rs lib/git/src/handler/branches/delete.rs +39 −0 View lib/git/src/handler/branches/delete.rs
@@ -0,0 +1,39 @@
1use axum::extract::{Path, Query, State};
2use export::rest::{AppResponseData, NoData};
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::require_writer;
7use crate::service::GitService;
8
9#[derive(Debug, Clone, serde::Deserialize)]
10pub struct BranchPath {
11 pub space_name: String,
12 pub repo_name: String,
13 pub name: String,
14}
15
16#[derive(Debug, Clone, serde::Deserialize)]
17pub struct DeleteBranchQuery {
18 #[serde(default)]
19 pub force: Option<bool>,
20}
21
22pub async fn delete_branch(
23 State(service): State<GitService>,
24 session: Session,
25 Path(path): Path<BranchPath>,
26 Query(query): Query<DeleteBranchQuery>,
27) -> Result<AppResponseData<NoData>, ApiError> {
28 let _ = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
29 service
30 .delete_branch(
31 path.space_name,
32 path.repo_name,
33 path.name,
34 query.force.unwrap_or(false),
35 )
36 .await
37 .map_err(GitApiError::from)?;
38 Ok(AppResponseData::ok(NoData))
39}
No newline at end of file
Added lib/git/src/handler/branches/get.rs lib/git/src/handler/branches/get.rs +28 −0 View lib/git/src/handler/branches/get.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::branches::BranchDto;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct BranchPath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub name: String,
15}
16
17pub async fn get_branch(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<BranchPath>,
21) -> Result<AppResponseData<BranchDto>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .get_branch(path.space_name, path.repo_name, path.name)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/branches/list.rs lib/git/src/handler/branches/list.rs +21 −0 View lib/git/src/handler/branches/list.rs
@@ -0,0 +1,21 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::branches::BranchDto;
8use crate::service::GitService;
9
10pub async fn list_branches(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<crate::handler::RepoPath>,
14) -> Result<AppResponseData<Vec<BranchDto>>, ApiError> {
15 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
16 let out = service
17 .list_branches(path.space_name, path.repo_name)
18 .await
19 .map_err(GitApiError::from)?;
20 Ok(AppResponseData::ok(out))
21}
No newline at end of file
Added lib/git/src/handler/branches/mod.rs lib/git/src/handler/branches/mod.rs +6 −0 View lib/git/src/handler/branches/mod.rs
@@ -0,0 +1,6 @@
1pub mod create;
2pub mod delete;
3pub mod get;
4pub mod list;
5pub mod rename;
6pub mod set_default;
No newline at end of file
Added lib/git/src/handler/branches/rename.rs lib/git/src/handler/branches/rename.rs +33 −0 View lib/git/src/handler/branches/rename.rs
@@ -0,0 +1,33 @@
1use axum::extract::{Path, Query, State};
2use export::rest::{AppResponseData, NoData};
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::require_writer;
7use crate::service::GitService;
8
9#[derive(Debug, Clone, serde::Deserialize)]
10pub struct RenameBranchPath {
11 pub space_name: String,
12 pub repo_name: String,
13 pub from: String,
14}
15
16#[derive(Debug, Clone, serde::Deserialize)]
17pub struct RenameBranchQuery {
18 pub to: String,
19}
20
21pub async fn rename_branch(
22 State(service): State<GitService>,
23 session: Session,
24 Path(path): Path<RenameBranchPath>,
25 Query(query): Query<RenameBranchQuery>,
26) -> Result<AppResponseData<NoData>, ApiError> {
27 let _ = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
28 service
29 .rename_branch(path.space_name, path.repo_name, path.from, query.to)
30 .await
31 .map_err(GitApiError::from)?;
32 Ok(AppResponseData::ok(NoData))
33}
No newline at end of file
Added lib/git/src/handler/branches/set_default.rs lib/git/src/handler/branches/set_default.rs +27 −0 View lib/git/src/handler/branches/set_default.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, State};
2use export::rest::{AppResponseData, NoData};
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::require_writer;
7use crate::service::GitService;
8
9#[derive(Debug, Clone, serde::Deserialize)]
10pub struct BranchPath {
11 pub space_name: String,
12 pub repo_name: String,
13 pub name: String,
14}
15
16pub async fn set_default_branch(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<BranchPath>,
20) -> Result<AppResponseData<NoData>, ApiError> {
21 let _ = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 service
23 .set_default_branch(path.space_name, path.repo_name, path.name)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(NoData))
27}
No newline at end of file
Added lib/git/src/handler/commits/get.rs lib/git/src/handler/commits/get.rs +28 −0 View lib/git/src/handler/commits/get.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use gitbaby::commit::types::CommitInfo;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct CommitPath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub revision: String,
15}
16
17pub async fn get_commit(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<CommitPath>,
21) -> Result<AppResponseData<CommitInfo>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .get_commit(path.space_name, path.repo_name, path.revision)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/commits/is_ancestor.rs lib/git/src/handler/commits/is_ancestor.rs +38 −0 View lib/git/src/handler/commits/is_ancestor.rs
@@ -0,0 +1,38 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use serde::Serialize;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct AncestorQuery {
12 pub ancestor: String,
13 pub descendant: String,
14}
15
16#[derive(Debug, Clone, Serialize)]
17pub struct IsAncestorResponse {
18 pub is_ancestor: bool,
19}
20
21pub async fn is_ancestor(
22 State(service): State<GitService>,
23 session: Session,
24 Path(path): Path<crate::handler::RepoPath>,
25 Query(query): Query<AncestorQuery>,
26) -> Result<AppResponseData<IsAncestorResponse>, ApiError> {
27 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
28 let is_ancestor = service
29 .is_ancestor(
30 path.space_name,
31 path.repo_name,
32 query.ancestor,
33 query.descendant,
34 )
35 .await
36 .map_err(GitApiError::from)?;
37 Ok(AppResponseData::ok(IsAncestorResponse { is_ancestor }))
38}
No newline at end of file
Added lib/git/src/handler/commits/list.rs lib/git/src/handler/commits/list.rs +23 −0 View lib/git/src/handler/commits/list.rs
@@ -0,0 +1,23 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use gitbaby::commit::types::CommitInfo;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9use crate::service::commits::ListCommitsCmd;
10
11pub async fn list_commits(
12 State(service): State<GitService>,
13 session: Session,
14 Path(path): Path<crate::handler::RepoPath>,
15 Query(cmd): Query<ListCommitsCmd>,
16) -> Result<AppResponseData<Vec<CommitInfo>>, ApiError> {
17 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
18 let out = service
19 .list_commits(path.space_name, path.repo_name, cmd)
20 .await
21 .map_err(GitApiError::from)?;
22 Ok(AppResponseData::ok(out))
23}
No newline at end of file
Added lib/git/src/handler/commits/list_commit_statuses.rs lib/git/src/handler/commits/list_commit_statuses.rs +28 −0 View lib/git/src/handler/commits/list_commit_statuses.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::commits::CommitStatusDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct StatusPath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub sha: String,
15}
16
17pub async fn list_commit_statuses(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<StatusPath>,
21) -> Result<AppResponseData<Vec<CommitStatusDto>>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .list_commit_statuses(path.space_name, path.repo_name, path.sha)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/commits/mod.rs lib/git/src/handler/commits/mod.rs +9 −0 View lib/git/src/handler/commits/mod.rs
@@ -0,0 +1,9 @@
1pub mod get;
2pub mod is_ancestor;
3pub mod list;
4pub mod list_commit_statuses;
5pub mod rev_parse;
6pub mod set_commit_status;
7pub mod stats;
8pub mod sync_commit;
9pub mod tree_entries;
No newline at end of file
Added lib/git/src/handler/commits/rev_parse.rs lib/git/src/handler/commits/rev_parse.rs +27 −0 View lib/git/src/handler/commits/rev_parse.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8
9#[derive(Debug, Clone, serde::Deserialize)]
10pub struct RevPath {
11 pub space_name: String,
12 pub repo_name: String,
13 pub revision: String,
14}
15
16pub async fn rev_parse(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<RevPath>,
20) -> Result<AppResponseData<String>, ApiError> {
21 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 let out = service
23 .rev_parse(path.space_name, path.repo_name, path.revision)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(out))
27}
No newline at end of file
Added lib/git/src/handler/commits/set_commit_status.rs lib/git/src/handler/commits/set_commit_status.rs +23 −0 View lib/git/src/handler/commits/set_commit_status.rs
@@ -0,0 +1,23 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::require_writer;
8use crate::service::GitService;
9use crate::service::commits::{CommitStatusDto, SetCommitStatusCmd};
10
11pub async fn set_commit_status(
12 State(service): State<GitService>,
13 session: Session,
14 Path(path): Path<crate::handler::RepoPath>,
15 Json(cmd): Json<SetCommitStatusCmd>,
16) -> Result<AppResponseData<CommitStatusDto>, ApiError> {
17 let (_ctx, uid) = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
18 let out = service
19 .set_commit_status(path.space_name, path.repo_name, uid, cmd)
20 .await
21 .map_err(GitApiError::from)?;
22 Ok(AppResponseData::ok(out))
23}
No newline at end of file
Added lib/git/src/handler/commits/stats.rs lib/git/src/handler/commits/stats.rs +36 −0 View lib/git/src/handler/commits/stats.rs
@@ -0,0 +1,36 @@
1use std::path::PathBuf;
2
3use axum::extract::{Path, Query, State};
4use export::rest::AppResponseData;
5use gitbaby::commit::types::CommitStats;
6use session::Session;
7
8use crate::errors::{ApiError, GitApiError};
9use crate::handler::resolve_reader;
10use crate::service::GitService;
11
12#[derive(Debug, Clone, serde::Deserialize)]
13pub struct StatsQuery {
14 pub revision: String,
15 #[serde(default)]
16 pub path: Option<String>,
17}
18
19pub async fn commit_stats(
20 State(service): State<GitService>,
21 session: Session,
22 Path(path): Path<crate::handler::RepoPath>,
23 Query(query): Query<StatsQuery>,
24) -> Result<AppResponseData<CommitStats>, ApiError> {
25 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
26 let out = service
27 .commit_stats(
28 path.space_name,
29 path.repo_name,
30 query.revision,
31 query.path.map(PathBuf::from),
32 )
33 .await
34 .map_err(GitApiError::from)?;
35 Ok(AppResponseData::ok(out))
36}
No newline at end of file
Added lib/git/src/handler/commits/sync_commit.rs lib/git/src/handler/commits/sync_commit.rs +37 −0 View lib/git/src/handler/commits/sync_commit.rs
@@ -0,0 +1,37 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use serde::Serialize;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::require_writer;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct CommitPath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub revision: String,
15}
16
17#[derive(Debug, Clone, Serialize)]
18pub struct CommitSyncResponse {
19 pub repo_id: String,
20 pub sha: String,
21}
22
23pub async fn sync_commit(
24 State(service): State<GitService>,
25 session: Session,
26 Path(path): Path<CommitPath>,
27) -> Result<AppResponseData<CommitSyncResponse>, ApiError> {
28 let (ctx, _uid) = require_writer(&service, &session, path.space_name, path.repo_name).await?;
29 let row = service
30 .sync_commit(&ctx, &path.revision)
31 .await
32 .map_err(GitApiError::from)?;
33 Ok(AppResponseData::ok(CommitSyncResponse {
34 repo_id: row.repo_id.to_string(),
35 sha: row.sha,
36 }))
37}
No newline at end of file
Added lib/git/src/handler/commits/tree_entries.rs lib/git/src/handler/commits/tree_entries.rs +42 −0 View lib/git/src/handler/commits/tree_entries.rs
@@ -0,0 +1,42 @@
1use std::path::PathBuf;
2
3use axum::extract::{Path, Query, State};
4use export::rest::AppResponseData;
5use gitbaby::commit::types::TreeEntry;
6use session::Session;
7
8use crate::errors::{ApiError, GitApiError};
9use crate::handler::resolve_reader;
10use crate::service::GitService;
11
12#[derive(Debug, Clone, serde::Deserialize)]
13pub struct TreePath {
14 pub space_name: String,
15 pub repo_name: String,
16 pub revision: String,
17}
18
19#[derive(Debug, Clone, Default, serde::Deserialize)]
20pub struct TreeQuery {
21 #[serde(default)]
22 pub path: Option<String>,
23}
24
25pub async fn get_tree_entries(
26 State(service): State<GitService>,
27 session: Session,
28 Path(path): Path<TreePath>,
29 Query(query): Query<TreeQuery>,
30) -> Result<AppResponseData<Vec<TreeEntry>>, ApiError> {
31 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
32 let out = service
33 .get_tree_entries(
34 path.space_name,
35 path.repo_name,
36 path.revision,
37 query.path.map(PathBuf::from).unwrap_or_default(),
38 )
39 .await
40 .map_err(GitApiError::from)?;
41 Ok(AppResponseData::ok(out))
42}
No newline at end of file
Added lib/git/src/handler/conflicts/check.rs lib/git/src/handler/conflicts/check.rs +28 −0 View lib/git/src/handler/conflicts/check.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::conflicts::MergeStatusDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct ConflictBaseHeadQuery {
12 pub base: String,
13 pub head: String,
14}
15
16pub async fn conflict_check(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<crate::handler::RepoPath>,
20 Query(q): Query<ConflictBaseHeadQuery>,
21) -> Result<AppResponseData<MergeStatusDto>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .conflict_check(path.space_name, path.repo_name, q.base, q.head)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/conflicts/check_threeway.rs lib/git/src/handler/conflicts/check_threeway.rs +36 −0 View lib/git/src/handler/conflicts/check_threeway.rs
@@ -0,0 +1,36 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9use crate::service::conflicts::MergeStatusDto;
10
11#[derive(Debug, Clone, serde::Deserialize)]
12pub struct ConflictCheckThreewayBody {
13 pub ours: String,
14 pub theirs: String,
15 pub ancestor: String,
16}
17
18pub async fn conflict_check_threeway(
19 State(service): State<GitService>,
20 session: Session,
21 Path(path): Path<crate::handler::RepoPath>,
22 Json(body): Json<ConflictCheckThreewayBody>,
23) -> Result<AppResponseData<MergeStatusDto>, ApiError> {
24 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
25 let out = service
26 .conflict_check_threeway(
27 path.space_name,
28 path.repo_name,
29 body.ours,
30 body.theirs,
31 body.ancestor,
32 )
33 .await
34 .map_err(GitApiError::from)?;
35 Ok(AppResponseData::ok(out))
36}
No newline at end of file
Added lib/git/src/handler/conflicts/conflicted_files.rs lib/git/src/handler/conflicts/conflicted_files.rs +27 −0 View lib/git/src/handler/conflicts/conflicted_files.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8
9#[derive(Debug, Clone, serde::Deserialize)]
10pub struct ConflictBaseHeadQuery {
11 pub base: String,
12 pub head: String,
13}
14
15pub async fn conflicted_files(
16 State(service): State<GitService>,
17 session: Session,
18 Path(path): Path<crate::handler::RepoPath>,
19 Query(q): Query<ConflictBaseHeadQuery>,
20) -> Result<AppResponseData<Vec<String>>, ApiError> {
21 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 let out = service
23 .conflict_conflicted_files(path.space_name, path.repo_name, q.base, q.head)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(out))
27}
No newline at end of file
Added lib/git/src/handler/conflicts/detail.rs lib/git/src/handler/conflicts/detail.rs +29 −0 View lib/git/src/handler/conflicts/detail.rs
@@ -0,0 +1,29 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::conflicts::ConflictDetailDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct ConflictDetailQuery {
12 pub base: String,
13 pub head: String,
14 pub path: String,
15}
16
17pub async fn conflict_detail(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<crate::handler::RepoPath>,
21 Query(q): Query<ConflictDetailQuery>,
22) -> Result<AppResponseData<ConflictDetailDto>, ApiError> {
23 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
24 let out = service
25 .conflict_detail(path.space_name, path.repo_name, q.base, q.head, q.path)
26 .await
27 .map_err(GitApiError::from)?;
28 Ok(AppResponseData::ok(out))
29}
No newline at end of file
Added lib/git/src/handler/conflicts/mod.rs lib/git/src/handler/conflicts/mod.rs +4 −0 View lib/git/src/handler/conflicts/mod.rs
@@ -0,0 +1,4 @@
1pub mod check;
2pub mod check_threeway;
3pub mod conflicted_files;
4pub mod detail;
No newline at end of file
Added lib/git/src/handler/content/caller_signature.rs lib/git/src/handler/content/caller_signature.rs +29 −0 View lib/git/src/handler/content/caller_signature.rs
@@ -0,0 +1,29 @@
1use axum::Json;
2use axum::extract::State;
3use export::rest::AppResponseData;
4use session::Session;
5use time::OffsetDateTime;
6
7use crate::errors::{ApiError, GitApiError};
8use crate::handler::ensure_caller;
9use crate::service::GitService;
10use crate::service::content::SignatureDto;
11
12#[derive(Debug, Clone, serde::Deserialize)]
13pub struct CallerSignatureBody {
14 #[serde(default)]
15 pub when: Option<String>,
16}
17
18pub async fn caller_signature(
19 State(service): State<GitService>,
20 session: Session,
21 Json(_body): Json<CallerSignatureBody>,
22) -> Result<AppResponseData<SignatureDto>, ApiError> {
23 let caller = ensure_caller(&session)?;
24 let out = service
25 .caller_signature(caller, OffsetDateTime::now_utc())
26 .await
27 .map_err(GitApiError::from)?;
28 Ok(AppResponseData::ok(out))
29}
No newline at end of file
Added lib/git/src/handler/content/commit_object.rs lib/git/src/handler/content/commit_object.rs +42 −0 View lib/git/src/handler/content/commit_object.rs
@@ -0,0 +1,42 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::{RepoPath, require_writer};
8use crate::service::GitService;
9use crate::service::content::{ObjectKind, SignatureDto, WriteObjectResultDto};
10
11#[derive(Debug, Clone, serde::Deserialize)]
12pub struct CommitObjectBody {
13 pub kind: ObjectKind,
14 pub parents: Vec<String>,
15 pub tree: String,
16 pub message: String,
17 pub author: SignatureDto,
18 pub committer: SignatureDto,
19}
20
21pub async fn commit_object(
22 State(service): State<GitService>,
23 session: Session,
24 Path(path): Path<RepoPath>,
25 Json(body): Json<CommitObjectBody>,
26) -> Result<AppResponseData<WriteObjectResultDto>, ApiError> {
27 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
28 let out = service
29 .commit_object(
30 path.space_name,
31 path.repo_name,
32 body.kind,
33 body.parents,
34 body.tree,
35 body.message,
36 body.author,
37 body.committer,
38 )
39 .await
40 .map_err(GitApiError::from)?;
41 Ok(AppResponseData::ok(out))
42}
No newline at end of file
Added lib/git/src/handler/content/mod.rs lib/git/src/handler/content/mod.rs +4 −0 View lib/git/src/handler/content/mod.rs
@@ -0,0 +1,4 @@
1pub mod caller_signature;
2pub mod commit_object;
3pub mod write_blob;
4pub mod write_tree_from_files;
No newline at end of file
Added lib/git/src/handler/content/write_blob.rs lib/git/src/handler/content/write_blob.rs +28 −0 View lib/git/src/handler/content/write_blob.rs
@@ -0,0 +1,28 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::{RepoPath, require_writer};
8use crate::service::GitService;
9use crate::service::content::WriteObjectResultDto;
10
11#[derive(Debug, Clone, serde::Deserialize)]
12pub struct WriteBlobBody {
13 pub data: String,
14}
15
16pub async fn write_blob(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<RepoPath>,
20 Json(body): Json<WriteBlobBody>,
21) -> Result<AppResponseData<WriteObjectResultDto>, ApiError> {
22 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .write_blob(path.space_name, path.repo_name, body.data.into_bytes())
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
Added lib/git/src/handler/content/write_tree_from_files.rs lib/git/src/handler/content/write_tree_from_files.rs +28 −0 View lib/git/src/handler/content/write_tree_from_files.rs
@@ -0,0 +1,28 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::{RepoPath, require_writer};
8use crate::service::GitService;
9use crate::service::content::{FileEntryDto, WriteObjectResultDto};
10
11#[derive(Debug, Clone, serde::Deserialize)]
12pub struct WriteTreeBody {
13 pub files: Vec<FileEntryDto>,
14}
15
16pub async fn write_tree_from_files(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<RepoPath>,
20 Json(body): Json<WriteTreeBody>,
21) -> Result<AppResponseData<WriteObjectResultDto>, ApiError> {
22 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .write_tree_from_files(path.space_name, path.repo_name, body.files)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/diffs/files.rs lib/git/src/handler/diffs/files.rs +35 −0 View lib/git/src/handler/diffs/files.rs
@@ -0,0 +1,35 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use gitbaby::diff::types::ChangedPathDiff;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9use crate::service::diffs::DiffOptionsDto;
10
11#[derive(Debug, Clone, serde::Deserialize)]
12pub struct DiffBaseHeadQuery {
13 pub base: String,
14 pub head: String,
15}
16
17pub async fn diff_files(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<crate::handler::RepoPath>,
21 Query(q): Query<DiffBaseHeadQuery>,
22) -> Result<AppResponseData<Vec<ChangedPathDiff>>, ApiError> {
23 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
24 let out = service
25 .diff_files(
26 path.space_name,
27 path.repo_name,
28 q.base,
29 q.head,
30 DiffOptionsDto::default(),
31 )
32 .await
33 .map_err(GitApiError::from)?;
34 Ok(AppResponseData::ok(out))
35}
No newline at end of file
Added lib/git/src/handler/diffs/files_changed_between.rs lib/git/src/handler/diffs/files_changed_between.rs +27 −0 View lib/git/src/handler/diffs/files_changed_between.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8
9#[derive(Debug, Clone, serde::Deserialize)]
10pub struct DiffBaseHeadQuery {
11 pub base: String,
12 pub head: String,
13}
14
15pub async fn files_changed_between(
16 State(service): State<GitService>,
17 session: Session,
18 Path(path): Path<crate::handler::RepoPath>,
19 Query(q): Query<DiffBaseHeadQuery>,
20) -> Result<AppResponseData<Vec<String>>, ApiError> {
21 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 let out = service
23 .diff_files_changed_between(path.space_name, path.repo_name, q.base, q.head)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(out))
27}
No newline at end of file
Added lib/git/src/handler/diffs/for_commit.rs lib/git/src/handler/diffs/for_commit.rs +28 −0 View lib/git/src/handler/diffs/for_commit.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use gitbaby::diff::types::ChangedPath;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct CommitPath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub commit: String,
15}
16
17pub async fn diff_for_commit(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<CommitPath>,
21) -> Result<AppResponseData<Vec<ChangedPath>>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .diff_for_commit(path.space_name, path.repo_name, path.commit)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/diffs/mod.rs lib/git/src/handler/diffs/mod.rs +8 −0 View lib/git/src/handler/diffs/mod.rs
@@ -0,0 +1,8 @@
1pub mod files;
2pub mod files_changed_between;
3pub mod for_commit;
4pub mod range_diff;
5pub mod raw;
6pub mod short_stat;
7pub mod stats;
8pub mod tree;
No newline at end of file
Added lib/git/src/handler/diffs/range_diff.rs lib/git/src/handler/diffs/range_diff.rs +23 −0 View lib/git/src/handler/diffs/range_diff.rs
@@ -0,0 +1,23 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use gitbaby::diff::types::RangeDiffSpec;
5use session::Session;
6
7use crate::errors::{ApiError, GitApiError};
8use crate::handler::resolve_reader;
9use crate::service::GitService;
10
11pub async fn range_diff(
12 State(service): State<GitService>,
13 session: Session,
14 Path(path): Path<crate::handler::RepoPath>,
15 Json(body): Json<RangeDiffSpec>,
16) -> Result<AppResponseData<String>, ApiError> {
17 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
18 let out = service
19 .range_diff(path.space_name, path.repo_name, body)
20 .await
21 .map_err(GitApiError::from)?;
22 Ok(AppResponseData::ok(out))
23}
No newline at end of file
Added lib/git/src/handler/diffs/raw.rs lib/git/src/handler/diffs/raw.rs +27 −0 View lib/git/src/handler/diffs/raw.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8
9#[derive(Debug, Clone, serde::Deserialize)]
10pub struct DiffBaseHeadQuery {
11 pub base: String,
12 pub head: String,
13}
14
15pub async fn diff_raw(
16 State(service): State<GitService>,
17 session: Session,
18 Path(path): Path<crate::handler::RepoPath>,
19 Query(q): Query<DiffBaseHeadQuery>,
20) -> Result<AppResponseData<String>, ApiError> {
21 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 let out = service
23 .diff_raw(path.space_name, path.repo_name, q.base, q.head)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(out))
27}
No newline at end of file
Added lib/git/src/handler/diffs/short_stat.rs lib/git/src/handler/diffs/short_stat.rs +28 −0 View lib/git/src/handler/diffs/short_stat.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use gitbaby::diff::types::ShortStat;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct DiffBaseHeadQuery {
12 pub base: String,
13 pub head: String,
14}
15
16pub async fn diff_short_stat(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<crate::handler::RepoPath>,
20 Query(q): Query<DiffBaseHeadQuery>,
21) -> Result<AppResponseData<ShortStat>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .diff_short_stat(path.space_name, path.repo_name, q.base, q.head)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/diffs/stats.rs lib/git/src/handler/diffs/stats.rs +35 −0 View lib/git/src/handler/diffs/stats.rs
@@ -0,0 +1,35 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use gitbaby::diff::types::NumStat;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9use crate::service::diffs::DiffOptionsDto;
10
11#[derive(Debug, Clone, serde::Deserialize)]
12pub struct DiffBaseHeadQuery {
13 pub base: String,
14 pub head: String,
15}
16
17pub async fn diff_stats(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<crate::handler::RepoPath>,
21 Query(q): Query<DiffBaseHeadQuery>,
22) -> Result<AppResponseData<Vec<NumStat>>, ApiError> {
23 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
24 let out = service
25 .diff_stats(
26 path.space_name,
27 path.repo_name,
28 q.base,
29 q.head,
30 DiffOptionsDto::default(),
31 )
32 .await
33 .map_err(GitApiError::from)?;
34 Ok(AppResponseData::ok(out))
35}
No newline at end of file
Added lib/git/src/handler/diffs/tree.rs lib/git/src/handler/diffs/tree.rs +36 −0 View lib/git/src/handler/diffs/tree.rs
@@ -0,0 +1,36 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::diffs::DiffTreeRecordDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct DiffTreeQuery {
12 pub base: String,
13 pub head: String,
14 #[serde(default)]
15 pub use_merge_base: Option<bool>,
16}
17
18pub async fn diff_tree(
19 State(service): State<GitService>,
20 session: Session,
21 Path(path): Path<crate::handler::RepoPath>,
22 Query(q): Query<DiffTreeQuery>,
23) -> Result<AppResponseData<Vec<DiffTreeRecordDto>>, ApiError> {
24 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
25 let out = service
26 .diff_tree(
27 path.space_name,
28 path.repo_name,
29 q.base,
30 q.head,
31 q.use_merge_base.unwrap_or(false),
32 )
33 .await
34 .map_err(GitApiError::from)?;
35 Ok(AppResponseData::ok(out))
36}
No newline at end of file
Added lib/git/src/handler/hooks/execute_script.rs lib/git/src/handler/hooks/execute_script.rs +36 −0 View lib/git/src/handler/hooks/execute_script.rs
@@ -0,0 +1,36 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::require_writer;
8use crate::service::GitService;
9use crate::service::hooks::ScriptOutputDto;
10
11#[derive(Debug, Clone, serde::Deserialize)]
12pub struct HookScriptPath {
13 pub space_name: String,
14 pub repo_name: String,
15 pub script: String,
16}
17
18#[derive(Debug, Clone, serde::Deserialize)]
19pub struct HookExecBody {
20 #[serde(default)]
21 pub args: Vec<String>,
22}
23
24pub async fn execute_script(
25 State(service): State<GitService>,
26 session: Session,
27 Path(path): Path<HookScriptPath>,
28 Json(body): Json<HookExecBody>,
29) -> Result<AppResponseData<ScriptOutputDto>, ApiError> {
30 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
31 let out = service
32 .hook_execute_script(path.space_name, path.repo_name, path.script, body.args)
33 .await
34 .map_err(GitApiError::from)?;
35 Ok(AppResponseData::ok(out))
36}
No newline at end of file
Added lib/git/src/handler/hooks/mod.rs lib/git/src/handler/hooks/mod.rs +3 −0 View lib/git/src/handler/hooks/mod.rs
@@ -0,0 +1,3 @@
1pub mod execute_script;
2pub mod post_receive;
3pub mod pre_receive;
No newline at end of file
Added lib/git/src/handler/hooks/post_receive.rs lib/git/src/handler/hooks/post_receive.rs +18 −0 View lib/git/src/handler/hooks/post_receive.rs
@@ -0,0 +1,18 @@
1use axum::Json;
2use axum::extract::State;
3use export::rest::AppResponseData;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::service::GitService;
7use crate::service::hooks::{HookEventDto, HookResultDto};
8
9pub async fn post_receive(
10 State(service): State<GitService>,
11 Json(event): Json<HookEventDto>,
12) -> Result<AppResponseData<HookResultDto>, ApiError> {
13 let out = service
14 .hook_post_receive(event)
15 .await
16 .map_err(GitApiError::from)?;
17 Ok(AppResponseData::ok(out))
18}
No newline at end of file
Added lib/git/src/handler/hooks/pre_receive.rs lib/git/src/handler/hooks/pre_receive.rs +18 −0 View lib/git/src/handler/hooks/pre_receive.rs
@@ -0,0 +1,18 @@
1use axum::Json;
2use axum::extract::State;
3use export::rest::AppResponseData;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::service::GitService;
7use crate::service::hooks::{HookEventDto, HookResultDto};
8
9pub async fn pre_receive(
10 State(service): State<GitService>,
11 Json(event): Json<HookEventDto>,
12) -> Result<AppResponseData<HookResultDto>, ApiError> {
13 let out = service
14 .hook_pre_receive(event)
15 .await
16 .map_err(GitApiError::from)?;
17 Ok(AppResponseData::ok(out))
18}
No newline at end of file
Added lib/git/src/handler/lfs/cleanup_unreferenced.rs lib/git/src/handler/lfs/cleanup_unreferenced.rs +25 −0 View lib/git/src/handler/lfs/cleanup_unreferenced.rs
@@ -0,0 +1,25 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::{RepoPath, require_writer};
7use crate::service::GitService;
8
9#[derive(Debug, Clone, serde::Serialize)]
10pub struct LfsCleanupResponse {
11 pub removed: i64,
12}
13
14pub async fn cleanup_unreferenced(
15 State(service): State<GitService>,
16 session: Session,
17 Path(path): Path<RepoPath>,
18) -> Result<AppResponseData<LfsCleanupResponse>, ApiError> {
19 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
20 let removed = service
21 .lfs_cleanup_unreferenced(path.space_name, path.repo_name)
22 .await
23 .map_err(GitApiError::from)?;
24 Ok(AppResponseData::ok(LfsCleanupResponse { removed }))
25}
No newline at end of file
Added lib/git/src/handler/lfs/list_locks.rs lib/git/src/handler/lfs/list_locks.rs +41 −0 View lib/git/src/handler/lfs/list_locks.rs
@@ -0,0 +1,41 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::{RepoPath, resolve_reader};
7use crate::service::GitService;
8use crate::service::lfs::LfsLockListResponse;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct LfsListLocksQuery {
12 #[serde(default)]
13 pub cursor: Option<String>,
14 #[serde(default)]
15 pub limit: Option<u64>,
16}
17
18pub async fn list_locks(
19 State(service): State<GitService>,
20 session: Session,
21 Path(path): Path<RepoPath>,
22 Query(query): Query<LfsListLocksQuery>,
23) -> Result<AppResponseData<LfsLockListResponse>, ApiError> {
24 resolve_reader(
25 &service,
26 &session,
27 path.space_name.clone(),
28 path.repo_name.clone(),
29 )
30 .await?;
31 let out = service
32 .lfs_list_locks(
33 path.space_name,
34 path.repo_name,
35 query.cursor,
36 query.limit.unwrap_or(0),
37 )
38 .await
39 .map_err(GitApiError::from)?;
40 Ok(AppResponseData::ok(out))
41}
No newline at end of file
Added lib/git/src/handler/lfs/lock.rs lib/git/src/handler/lfs/lock.rs +30 −0 View lib/git/src/handler/lfs/lock.rs
@@ -0,0 +1,30 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::{RepoPath, require_writer};
8use crate::service::GitService;
9use crate::service::lfs::LfsLock;
10
11#[derive(Debug, Clone, serde::Deserialize)]
12pub struct LfsLockBody {
13 pub path: String,
14 #[serde(default)]
15 pub oid: Option<String>,
16}
17
18pub async fn lock(
19 State(service): State<GitService>,
20 session: Session,
21 Path(path): Path<RepoPath>,
22 Json(body): Json<LfsLockBody>,
23) -> Result<AppResponseData<LfsLock>, ApiError> {
24 let (_ctx, uid) = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
25 let out = service
26 .lfs_lock(path.space_name, path.repo_name, uid, body.path, body.oid)
27 .await
28 .map_err(GitApiError::from)?;
29 Ok(AppResponseData::ok(out))
30}
No newline at end of file
Added lib/git/src/handler/lfs/mod.rs lib/git/src/handler/lfs/mod.rs +6 −0 View lib/git/src/handler/lfs/mod.rs
@@ -0,0 +1,6 @@
1pub mod cleanup_unreferenced;
2pub mod list_locks;
3pub mod lock;
4pub mod unlock;
5pub mod unlock_by_id;
6pub mod verify_locks;
No newline at end of file
Added lib/git/src/handler/lfs/unlock.rs lib/git/src/handler/lfs/unlock.rs +29 −0 View lib/git/src/handler/lfs/unlock.rs
@@ -0,0 +1,29 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::{AppResponseData, NoData};
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::{RepoPath, require_writer};
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct LfsUnlockBody {
12 pub path: String,
13 #[serde(default)]
14 pub force: Option<bool>,
15}
16
17pub async fn unlock(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<RepoPath>,
21 Json(body): Json<LfsUnlockBody>,
22) -> Result<AppResponseData<NoData>, ApiError> {
23 let (_ctx, uid) = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
24 service
25 .lfs_unlock(path.space_name, path.repo_name, uid, body.path, body.force.unwrap_or(false))
26 .await
27 .map_err(GitApiError::from)?;
28 Ok(AppResponseData::ok(NoData))
29}
No newline at end of file
Added lib/git/src/handler/lfs/unlock_by_id.rs lib/git/src/handler/lfs/unlock_by_id.rs +41 −0 View lib/git/src/handler/lfs/unlock_by_id.rs
@@ -0,0 +1,41 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::{AppResponseData, NoData};
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::require_writer;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct LfsLockIdPath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub lock_id: String,
15}
16
17#[derive(Debug, Clone, serde::Deserialize)]
18pub struct LfsUnlockByIdBody {
19 #[serde(default)]
20 pub force: Option<bool>,
21}
22
23pub async fn unlock_by_id(
24 State(service): State<GitService>,
25 session: Session,
26 Path(path): Path<LfsLockIdPath>,
27 Json(body): Json<LfsUnlockByIdBody>,
28) -> Result<AppResponseData<NoData>, ApiError> {
29 let (_ctx, uid) = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
30 service
31 .lfs_unlock_by_id(
32 path.space_name,
33 path.repo_name,
34 uid,
35 path.lock_id,
36 body.force.unwrap_or(false),
37 )
38 .await
39 .map_err(GitApiError::from)?;
40 Ok(AppResponseData::ok(NoData))
41}
No newline at end of file
Added lib/git/src/handler/lfs/verify_locks.rs lib/git/src/handler/lfs/verify_locks.rs +33 −0 View lib/git/src/handler/lfs/verify_locks.rs
@@ -0,0 +1,33 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::{RepoPath, require_writer};
7use crate::service::GitService;
8use crate::service::lfs::LfsVerifyLocksResponse;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct LfsVerifyLocksQuery {
12 #[serde(default)]
13 pub limit: Option<u64>,
14}
15
16pub async fn verify_locks(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<RepoPath>,
20 Query(query): Query<LfsVerifyLocksQuery>,
21) -> Result<AppResponseData<LfsVerifyLocksResponse>, ApiError> {
22 let (_ctx, uid) = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .lfs_verify_locks(
25 path.space_name,
26 path.repo_name,
27 uid,
28 query.limit.unwrap_or(0),
29 )
30 .await
31 .map_err(GitApiError::from)?;
32 Ok(AppResponseData::ok(out))
33}
No newline at end of file
Added lib/git/src/handler/logs/commits_between.rs lib/git/src/handler/logs/commits_between.rs +36 −0 View lib/git/src/handler/logs/commits_between.rs
@@ -0,0 +1,36 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::logs::LogListDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct BetweenQuery {
12 pub after: String,
13 pub before: String,
14 #[serde(default)]
15 pub limit: Option<u64>,
16}
17
18pub async fn log_commits_between(
19 State(service): State<GitService>,
20 session: Session,
21 Path(path): Path<crate::handler::RepoPath>,
22 Query(query): Query<BetweenQuery>,
23) -> Result<AppResponseData<LogListDto>, ApiError> {
24 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
25 let out = service
26 .log_commits_between(
27 path.space_name,
28 path.repo_name,
29 query.after,
30 query.before,
31 query.limit.unwrap_or(50),
32 )
33 .await
34 .map_err(GitApiError::from)?;
35 Ok(AppResponseData::ok(out))
36}
No newline at end of file
Added lib/git/src/handler/logs/graph.rs lib/git/src/handler/logs/graph.rs +22 −0 View lib/git/src/handler/logs/graph.rs
@@ -0,0 +1,22 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::logs::{GraphNode, LogOptions};
9
10pub async fn log_graph(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<crate::handler::RepoPath>,
14 Query(opts): Query<LogOptions>,
15) -> Result<AppResponseData<Vec<GraphNode>>, ApiError> {
16 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
17 let out = service
18 .log_graph(path.space_name, path.repo_name, opts)
19 .await
20 .map_err(GitApiError::from)?;
21 Ok(AppResponseData::ok(out))
22}
No newline at end of file
Added lib/git/src/handler/logs/last_commit.rs lib/git/src/handler/logs/last_commit.rs +27 −0 View lib/git/src/handler/logs/last_commit.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use gitbaby::commit::types::CommitInfo;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct LastCommitQuery {
12 pub branch: String,
13}
14
15pub async fn log_last_commit(
16 State(service): State<GitService>,
17 session: Session,
18 Path(path): Path<crate::handler::RepoPath>,
19 Query(query): Query<LastCommitQuery>,
20) -> Result<AppResponseData<CommitInfo>, ApiError> {
21 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 let out = service
23 .log_last_commit(path.space_name, path.repo_name, query.branch)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(out))
27}
No newline at end of file
Added lib/git/src/handler/logs/list.rs lib/git/src/handler/logs/list.rs +22 −0 View lib/git/src/handler/logs/list.rs
@@ -0,0 +1,22 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::logs::{LogListDto, LogOptions};
9
10pub async fn log_list(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<crate::handler::RepoPath>,
14 Query(opts): Query<LogOptions>,
15) -> Result<AppResponseData<LogListDto>, ApiError> {
16 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
17 let out = service
18 .log_list(path.space_name, path.repo_name, opts)
19 .await
20 .map_err(GitApiError::from)?;
21 Ok(AppResponseData::ok(out))
22}
No newline at end of file
Added lib/git/src/handler/logs/mod.rs lib/git/src/handler/logs/mod.rs +4 −0 View lib/git/src/handler/logs/mod.rs
@@ -0,0 +1,4 @@
1pub mod commits_between;
2pub mod graph;
3pub mod last_commit;
4pub mod list;
No newline at end of file
Added lib/git/src/handler/maintenance/fsck.rs lib/git/src/handler/maintenance/fsck.rs +21 −0 View lib/git/src/handler/maintenance/fsck.rs
@@ -0,0 +1,21 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::{RepoPath, require_writer};
7use crate::service::GitService;
8use crate::service::maintenance::FsckDto;
9
10pub async fn fsck(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<RepoPath>,
14) -> Result<AppResponseData<FsckDto>, ApiError> {
15 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
16 let out = service
17 .maintenance_fsck(path.space_name, path.repo_name)
18 .await
19 .map_err(GitApiError::from)?;
20 Ok(AppResponseData::ok(out))
21}
No newline at end of file
Added lib/git/src/handler/maintenance/mod.rs lib/git/src/handler/maintenance/mod.rs +2 −0 View lib/git/src/handler/maintenance/mod.rs
@@ -0,0 +1,2 @@
1pub mod fsck;
2pub mod prune;
No newline at end of file
Added lib/git/src/handler/maintenance/prune.rs lib/git/src/handler/maintenance/prune.rs +21 −0 View lib/git/src/handler/maintenance/prune.rs
@@ -0,0 +1,21 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::{RepoPath, require_writer};
7use crate::service::GitService;
8use crate::service::maintenance::PruneResultDto;
9
10pub async fn prune(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<RepoPath>,
14) -> Result<AppResponseData<PruneResultDto>, ApiError> {
15 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
16 let out = service
17 .maintenance_prune(path.space_name, path.repo_name)
18 .await
19 .map_err(GitApiError::from)?;
20 Ok(AppResponseData::ok(out))
21}
No newline at end of file
Added lib/git/src/handler/packs/ingest.rs lib/git/src/handler/packs/ingest.rs +23 −0 View lib/git/src/handler/packs/ingest.rs
@@ -0,0 +1,23 @@
1use axum::body::Bytes;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::{RepoPath, require_writer};
8use crate::service::GitService;
9use crate::service::packs::IngestPackDto;
10
11pub async fn ingest(
12 State(service): State<GitService>,
13 session: Session,
14 Path(path): Path<RepoPath>,
15 body: Bytes,
16) -> Result<AppResponseData<IngestPackDto>, ApiError> {
17 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
18 let out = service
19 .pack_ingest(path.space_name, path.repo_name, body.to_vec())
20 .await
21 .map_err(GitApiError::from)?;
22 Ok(AppResponseData::ok(out))
23}
No newline at end of file
Added lib/git/src/handler/packs/mod.rs lib/git/src/handler/packs/mod.rs +3 −0 View lib/git/src/handler/packs/mod.rs
@@ -0,0 +1,3 @@
1pub mod ingest;
2pub mod repack;
3pub mod stats;
No newline at end of file
Added lib/git/src/handler/packs/repack.rs lib/git/src/handler/packs/repack.rs +20 −0 View lib/git/src/handler/packs/repack.rs
@@ -0,0 +1,20 @@
1use axum::extract::{Path, State};
2use export::rest::{AppResponseData, NoData};
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::{RepoPath, require_writer};
7use crate::service::GitService;
8
9pub async fn repack(
10 State(service): State<GitService>,
11 session: Session,
12 Path(path): Path<RepoPath>,
13) -> Result<AppResponseData<NoData>, ApiError> {
14 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
15 service
16 .pack_repack(path.space_name, path.repo_name)
17 .await
18 .map_err(GitApiError::from)?;
19 Ok(AppResponseData::ok(NoData))
20}
No newline at end of file
Added lib/git/src/handler/packs/stats.rs lib/git/src/handler/packs/stats.rs +27 −0 View lib/git/src/handler/packs/stats.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::{RepoPath, resolve_reader};
7use crate::service::GitService;
8use crate::service::packs::PackStatsDto;
9
10pub async fn stats(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<RepoPath>,
14) -> Result<AppResponseData<PackStatsDto>, ApiError> {
15 resolve_reader(
16 &service,
17 &session,
18 path.space_name.clone(),
19 path.repo_name.clone(),
20 )
21 .await?;
22 let out = service
23 .pack_stats(path.space_name, path.repo_name)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(out))
27}
No newline at end of file
Added lib/git/src/handler/patches/apply.rs lib/git/src/handler/patches/apply.rs +29 −0 View lib/git/src/handler/patches/apply.rs
@@ -0,0 +1,29 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9use crate::service::patches::AppliedPatchDto;
10
11#[derive(Debug, Clone, serde::Deserialize)]
12pub struct PatchApplyBody {
13 pub patch: String,
14 pub base: String,
15}
16
17pub async fn patch_apply(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<crate::handler::RepoPath>,
21 Json(body): Json<PatchApplyBody>,
22) -> Result<AppResponseData<AppliedPatchDto>, ApiError> {
23 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
24 let out = service
25 .patch_apply(path.space_name, path.repo_name, body.patch, body.base)
26 .await
27 .map_err(GitApiError::from)?;
28 Ok(AppResponseData::ok(out))
29}
No newline at end of file
Added lib/git/src/handler/patches/generate.rs lib/git/src/handler/patches/generate.rs +28 −0 View lib/git/src/handler/patches/generate.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::patches::PatchDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct PatchGenerateQuery {
12 pub base: String,
13 pub head: String,
14}
15
16pub async fn patch_generate(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<crate::handler::RepoPath>,
20 Query(q): Query<PatchGenerateQuery>,
21) -> Result<AppResponseData<PatchDto>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .patch_generate(path.space_name, path.repo_name, q.base, q.head)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/patches/mod.rs lib/git/src/handler/patches/mod.rs +3 −0 View lib/git/src/handler/patches/mod.rs
@@ -0,0 +1,3 @@
1pub mod apply;
2pub mod generate;
3pub mod parse;
No newline at end of file
Added lib/git/src/handler/patches/parse.rs lib/git/src/handler/patches/parse.rs +20 −0 View lib/git/src/handler/patches/parse.rs
@@ -0,0 +1,20 @@
1use axum::Json;
2use axum::extract::State;
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::service::GitService;
8use crate::service::patches::ParsedPatchDto;
9
10pub async fn patch_parse(
11 State(service): State<GitService>,
12 _session: Session,
13 Json(content): Json<String>,
14) -> Result<AppResponseData<ParsedPatchDto>, ApiError> {
15 let out = service
16 .patch_parse(content)
17 .await
18 .map_err(GitApiError::from)?;
19 Ok(AppResponseData::ok(out))
20}
No newline at end of file
Added lib/git/src/handler/pipelines/cancel.rs lib/git/src/handler/pipelines/cancel.rs +22 −0 View lib/git/src/handler/pipelines/cancel.rs
@@ -0,0 +1,22 @@
1use axum::Json;
2use axum::extract::State;
3use export::rest::{AppResponseData, NoData};
4
5use crate::errors::{ApiError, GitApiError};
6use crate::service::GitService;
7
8#[derive(Debug, Clone, serde::Deserialize)]
9pub struct PipelineCancelBody {
10 pub job_id: String,
11}
12
13pub async fn cancel(
14 State(service): State<GitService>,
15 Json(body): Json<PipelineCancelBody>,
16) -> Result<AppResponseData<NoData>, ApiError> {
17 service
18 .pipeline_cancel(body.job_id)
19 .await
20 .map_err(GitApiError::from)?;
21 Ok(AppResponseData::ok(NoData))
22}
No newline at end of file
Added lib/git/src/handler/pipelines/mod.rs lib/git/src/handler/pipelines/mod.rs +3 −0 View lib/git/src/handler/pipelines/mod.rs
@@ -0,0 +1,3 @@
1pub mod cancel;
2pub mod schedule;
3pub mod trigger;
No newline at end of file
Added lib/git/src/handler/pipelines/schedule.rs lib/git/src/handler/pipelines/schedule.rs +34 −0 View lib/git/src/handler/pipelines/schedule.rs
@@ -0,0 +1,34 @@
1use axum::Json;
2use axum::extract::{Path, Query, State};
3use export::rest::{AppResponseData, NoData};
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::{RepoPath, require_writer};
8use crate::service::GitService;
9use crate::service::pipelines::JobDto;
10
11#[derive(Debug, Clone, serde::Deserialize)]
12pub struct PipelineScheduleQuery {
13 pub commit: String,
14}
15
16#[derive(Debug, Clone, serde::Deserialize)]
17pub struct PipelineScheduleBody {
18 pub job: JobDto,
19}
20
21pub async fn schedule(
22 State(service): State<GitService>,
23 session: Session,
24 Path(path): Path<RepoPath>,
25 Query(query): Query<PipelineScheduleQuery>,
26 Json(body): Json<PipelineScheduleBody>,
27) -> Result<AppResponseData<NoData>, ApiError> {
28 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
29 service
30 .pipeline_schedule(path.space_name, path.repo_name, query.commit, body.job)
31 .await
32 .map_err(GitApiError::from)?;
33 Ok(AppResponseData::ok(NoData))
34}
No newline at end of file
Added lib/git/src/handler/pipelines/trigger.rs lib/git/src/handler/pipelines/trigger.rs +28 −0 View lib/git/src/handler/pipelines/trigger.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::{RepoPath, require_writer};
7use crate::service::GitService;
8use crate::service::pipelines::TriggerResultDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct PipelineTriggerQuery {
12 pub commit: String,
13 pub branch: String,
14}
15
16pub async fn trigger(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<RepoPath>,
20 Query(query): Query<PipelineTriggerQuery>,
21) -> Result<AppResponseData<TriggerResultDto>, ApiError> {
22 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .pipeline_trigger(path.space_name, path.repo_name, query.commit, query.branch)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/refs/branches.rs lib/git/src/handler/refs/branches.rs +35 −0 View lib/git/src/handler/refs/branches.rs
@@ -0,0 +1,35 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::refs::BranchInfoDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct RefsBranchesQuery {
12 #[serde(default)]
13 pub skip: Option<u64>,
14 #[serde(default)]
15 pub limit: Option<u64>,
16}
17
18pub async fn refs_branches(
19 State(service): State<GitService>,
20 session: Session,
21 Path(path): Path<crate::handler::RepoPath>,
22 Query(query): Query<RefsBranchesQuery>,
23) -> Result<AppResponseData<Vec<BranchInfoDto>>, ApiError> {
24 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
25 let out = service
26 .refs_branches(
27 path.space_name,
28 path.repo_name,
29 query.skip.unwrap_or(0),
30 query.limit.unwrap_or(0),
31 )
32 .await
33 .map_err(GitApiError::from)?;
34 Ok(AppResponseData::ok(out))
35}
No newline at end of file
Added lib/git/src/handler/refs/delete.rs lib/git/src/handler/refs/delete.rs +27 −0 View lib/git/src/handler/refs/delete.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, State};
2use export::rest::{AppResponseData, NoData};
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::require_writer;
7use crate::service::GitService;
8
9#[derive(Debug, Clone, serde::Deserialize)]
10pub struct RefPath {
11 pub space_name: String,
12 pub repo_name: String,
13 pub name: String,
14}
15
16pub async fn refs_delete(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<RefPath>,
20) -> Result<AppResponseData<NoData>, ApiError> {
21 let _ = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 service
23 .refs_delete(path.space_name, path.repo_name, path.name)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(NoData))
27}
No newline at end of file
Added lib/git/src/handler/refs/filtered.rs lib/git/src/handler/refs/filtered.rs +27 −0 View lib/git/src/handler/refs/filtered.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use gitbaby::refs::types::RefInfo;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct RefsFilteredQuery {
12 pub pattern: String,
13}
14
15pub async fn refs_list_filtered(
16 State(service): State<GitService>,
17 session: Session,
18 Path(path): Path<crate::handler::RepoPath>,
19 Query(query): Query<RefsFilteredQuery>,
20) -> Result<AppResponseData<Vec<RefInfo>>, ApiError> {
21 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 let out = service
23 .refs_list_filtered(path.space_name, path.repo_name, query.pattern)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(out))
27}
No newline at end of file
Added lib/git/src/handler/refs/get.rs lib/git/src/handler/refs/get.rs +28 −0 View lib/git/src/handler/refs/get.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use gitbaby::refs::types::RefInfo;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct RefPath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub name: String,
15}
16
17pub async fn refs_get(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<RefPath>,
21) -> Result<AppResponseData<RefInfo>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .refs_get(path.space_name, path.repo_name, path.name)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/refs/head.rs lib/git/src/handler/refs/head.rs +21 −0 View lib/git/src/handler/refs/head.rs
@@ -0,0 +1,21 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::refs::HeadInfoDto;
9
10pub async fn refs_head(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<crate::handler::RepoPath>,
14) -> Result<AppResponseData<HeadInfoDto>, ApiError> {
15 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
16 let out = service
17 .refs_head(path.space_name, path.repo_name)
18 .await
19 .map_err(GitApiError::from)?;
20 Ok(AppResponseData::ok(out))
21}
No newline at end of file
Added lib/git/src/handler/refs/is_object_in_ref.rs lib/git/src/handler/refs/is_object_in_ref.rs +33 −0 View lib/git/src/handler/refs/is_object_in_ref.rs
@@ -0,0 +1,33 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use serde::Serialize;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct ContainsQuery {
12 pub object: String,
13 pub refname: String,
14}
15
16#[derive(Debug, Clone, Serialize)]
17pub struct IsObjectInRefResponse {
18 pub contains: bool,
19}
20
21pub async fn refs_is_object_in_ref(
22 State(service): State<GitService>,
23 session: Session,
24 Path(path): Path<crate::handler::RepoPath>,
25 Query(query): Query<ContainsQuery>,
26) -> Result<AppResponseData<IsObjectInRefResponse>, ApiError> {
27 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
28 let contains = service
29 .refs_is_object_in_ref(path.space_name, path.repo_name, query.object, query.refname)
30 .await
31 .map_err(GitApiError::from)?;
32 Ok(AppResponseData::ok(IsObjectInRefResponse { contains }))
33}
No newline at end of file
Added lib/git/src/handler/refs/list.rs lib/git/src/handler/refs/list.rs +21 −0 View lib/git/src/handler/refs/list.rs
@@ -0,0 +1,21 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use gitbaby::refs::types::RefInfo;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9
10pub async fn refs_list(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<crate::handler::RepoPath>,
14) -> Result<AppResponseData<Vec<RefInfo>>, ApiError> {
15 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
16 let out = service
17 .refs_list(path.space_name, path.repo_name)
18 .await
19 .map_err(GitApiError::from)?;
20 Ok(AppResponseData::ok(out))
21}
No newline at end of file
Added lib/git/src/handler/refs/mod.rs lib/git/src/handler/refs/mod.rs +9 −0 View lib/git/src/handler/refs/mod.rs
@@ -0,0 +1,9 @@
1pub mod branches;
2pub mod delete;
3pub mod filtered;
4pub mod get;
5pub mod head;
6pub mod is_object_in_ref;
7pub mod list;
8pub mod resolve;
9pub mod update;
No newline at end of file
Added lib/git/src/handler/refs/resolve.rs lib/git/src/handler/refs/resolve.rs +27 −0 View lib/git/src/handler/refs/resolve.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8
9#[derive(Debug, Clone, serde::Deserialize)]
10pub struct RefPath {
11 pub space_name: String,
12 pub repo_name: String,
13 pub name: String,
14}
15
16pub async fn refs_resolve(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<RefPath>,
20) -> Result<AppResponseData<String>, ApiError> {
21 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 let out = service
23 .refs_resolve(path.space_name, path.repo_name, path.name)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(out))
27}
No newline at end of file
Added lib/git/src/handler/refs/update.rs lib/git/src/handler/refs/update.rs +43 −0 View lib/git/src/handler/refs/update.rs
@@ -0,0 +1,43 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use serde::{Deserialize, Serialize};
5use session::Session;
6
7use crate::errors::{ApiError, GitApiError};
8use crate::handler::require_writer;
9use crate::service::GitService;
10use crate::service::refs::UpdateRefResultDto;
11
12#[derive(Debug, Clone, serde::Deserialize)]
13pub struct RefPath {
14 pub space_name: String,
15 pub repo_name: String,
16 pub name: String,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct RefUpdateBody {
21 pub new_oid: String,
22 pub expected_oid: Option<String>,
23}
24
25pub async fn refs_update(
26 State(service): State<GitService>,
27 session: Session,
28 Path(path): Path<RefPath>,
29 Json(body): Json<RefUpdateBody>,
30) -> Result<AppResponseData<UpdateRefResultDto>, ApiError> {
31 let _ = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
32 let out = service
33 .refs_update(
34 path.space_name,
35 path.repo_name,
36 path.name,
37 body.new_oid,
38 body.expected_oid,
39 )
40 .await
41 .map_err(GitApiError::from)?;
42 Ok(AppResponseData::ok(out))
43}
No newline at end of file
Added lib/git/src/handler/remotes/add.rs lib/git/src/handler/remotes/add.rs +34 −0 View lib/git/src/handler/remotes/add.rs
@@ -0,0 +1,34 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::{AppResponseData, NoData};
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::require_writer;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct RemotePath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub name: String,
15}
16
17#[derive(Debug, Clone, serde::Deserialize)]
18pub struct RemoteAddBody {
19 pub url: String,
20}
21
22pub async fn add(
23 State(service): State<GitService>,
24 session: Session,
25 Path(path): Path<RemotePath>,
26 Json(body): Json<RemoteAddBody>,
27) -> Result<AppResponseData<NoData>, ApiError> {
28 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
29 service
30 .remote_add(path.space_name, path.repo_name, path.name, body.url)
31 .await
32 .map_err(GitApiError::from)?;
33 Ok(AppResponseData::ok(NoData))
34}
No newline at end of file
Added lib/git/src/handler/remotes/clone_import.rs lib/git/src/handler/remotes/clone_import.rs +30 −0 View lib/git/src/handler/remotes/clone_import.rs
@@ -0,0 +1,30 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::{RepoPath, require_writer};
8use crate::service::GitService;
9use crate::service::remotes::{ImportResultDto, RemoteAuthDto};
10
11#[derive(Debug, Clone, serde::Deserialize)]
12pub struct RemoteImportBody {
13 pub url: String,
14 #[serde(default)]
15 pub auth: Option<RemoteAuthDto>,
16}
17
18pub async fn clone_import(
19 State(service): State<GitService>,
20 session: Session,
21 Path(path): Path<RepoPath>,
22 Json(body): Json<RemoteImportBody>,
23) -> Result<AppResponseData<ImportResultDto>, ApiError> {
24 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
25 let out = service
26 .remote_clone_import(path.space_name, path.repo_name, body.url, body.auth)
27 .await
28 .map_err(GitApiError::from)?;
29 Ok(AppResponseData::ok(out))
30}
No newline at end of file
Added lib/git/src/handler/remotes/fetch.rs lib/git/src/handler/remotes/fetch.rs +30 −0 View lib/git/src/handler/remotes/fetch.rs
@@ -0,0 +1,30 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::{RepoPath, require_writer};
8use crate::service::GitService;
9use crate::service::remotes::{FetchResultDto, RemoteAuthDto};
10
11#[derive(Debug, Clone, serde::Deserialize)]
12pub struct RemoteFetchBody {
13 pub remote: String,
14 #[serde(default)]
15 pub auth: Option<RemoteAuthDto>,
16}
17
18pub async fn fetch(
19 State(service): State<GitService>,
20 session: Session,
21 Path(path): Path<RepoPath>,
22 Json(body): Json<RemoteFetchBody>,
23) -> Result<AppResponseData<FetchResultDto>, ApiError> {
24 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
25 let out = service
26 .remote_fetch(path.space_name, path.repo_name, body.remote, body.auth)
27 .await
28 .map_err(GitApiError::from)?;
29 Ok(AppResponseData::ok(out))
30}
No newline at end of file
Added lib/git/src/handler/remotes/mod.rs lib/git/src/handler/remotes/mod.rs +5 −0 View lib/git/src/handler/remotes/mod.rs
@@ -0,0 +1,5 @@
1pub mod add;
2pub mod clone_import;
3pub mod fetch;
4pub mod push;
5pub mod remove;
No newline at end of file
Added lib/git/src/handler/remotes/push.rs lib/git/src/handler/remotes/push.rs +38 −0 View lib/git/src/handler/remotes/push.rs
@@ -0,0 +1,38 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::{RepoPath, require_writer};
8use crate::service::GitService;
9use crate::service::remotes::{PushResultDto, RemoteAuthDto};
10
11#[derive(Debug, Clone, serde::Deserialize)]
12pub struct RemotePushBody {
13 pub remote: String,
14 #[serde(default)]
15 pub refspec: Option<String>,
16 #[serde(default)]
17 pub auth: Option<RemoteAuthDto>,
18}
19
20pub async fn push(
21 State(service): State<GitService>,
22 session: Session,
23 Path(path): Path<RepoPath>,
24 Json(body): Json<RemotePushBody>,
25) -> Result<AppResponseData<PushResultDto>, ApiError> {
26 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
27 let out = service
28 .remote_push(
29 path.space_name,
30 path.repo_name,
31 body.remote,
32 body.refspec,
33 body.auth,
34 )
35 .await
36 .map_err(GitApiError::from)?;
37 Ok(AppResponseData::ok(out))
38}
No newline at end of file
Added lib/git/src/handler/remotes/remove.rs lib/git/src/handler/remotes/remove.rs +27 −0 View lib/git/src/handler/remotes/remove.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, State};
2use export::rest::{AppResponseData, NoData};
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::require_writer;
7use crate::service::GitService;
8
9#[derive(Debug, Clone, serde::Deserialize)]
10pub struct RemotePath {
11 pub space_name: String,
12 pub repo_name: String,
13 pub name: String,
14}
15
16pub async fn remove(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<RemotePath>,
20) -> Result<AppResponseData<NoData>, ApiError> {
21 require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 service
23 .remote_remove(path.space_name, path.repo_name, path.name)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(NoData))
27}
No newline at end of file
Added lib/git/src/handler/repos/archive.rs lib/git/src/handler/repos/archive.rs +21 −0 View lib/git/src/handler/repos/archive.rs
@@ -0,0 +1,21 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::{RepoPath, ensure_caller};
7use crate::service::GitService;
8use crate::service::repos::RepoDto;
9
10pub async fn archive_repo(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<RepoPath>,
14) -> Result<AppResponseData<RepoDto>, ApiError> {
15 let caller = ensure_caller(&session)?;
16 let out = service
17 .archive_repo(path.space_name, path.repo_name, caller)
18 .await
19 .map_err(GitApiError::from)?;
20 Ok(AppResponseData::ok(out))
21}
No newline at end of file
Added lib/git/src/handler/repos/create.rs lib/git/src/handler/repos/create.rs +29 −0 View lib/git/src/handler/repos/create.rs
@@ -0,0 +1,29 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5use uuid::Uuid;
6
7use crate::errors::{ApiError, GitApiError};
8use crate::handler::ensure_caller;
9use crate::service::GitService;
10use crate::service::repos::{CreateRepoCmd, RepoDto};
11
12#[derive(Debug, Clone, serde::Deserialize)]
13pub struct SpacePath {
14 pub space_name: String,
15}
16
17pub async fn create_repo(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<SpacePath>,
21 Json(cmd): Json<CreateRepoCmd>,
22) -> Result<AppResponseData<RepoDto>, ApiError> {
23 let caller: Uuid = ensure_caller(&session)?;
24 let out = service
25 .create_repo(path.space_name, caller, cmd)
26 .await
27 .map_err(GitApiError::from)?;
28 Ok(AppResponseData::ok(out))
29}
No newline at end of file
Added lib/git/src/handler/repos/get.rs lib/git/src/handler/repos/get.rs +27 −0 View lib/git/src/handler/repos/get.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::{RepoPath, resolve_reader};
7use crate::service::GitService;
8use crate::service::repos::RepoDto;
9
10pub async fn get_repo(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<RepoPath>,
14) -> Result<AppResponseData<RepoDto>, ApiError> {
15 resolve_reader(
16 &service,
17 &session,
18 path.space_name.clone(),
19 path.repo_name.clone(),
20 )
21 .await?;
22 let out = service
23 .get_repo(path.space_name, path.repo_name)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(out))
27}
No newline at end of file
Added lib/git/src/handler/repos/list.rs lib/git/src/handler/repos/list.rs +24 −0 View lib/git/src/handler/repos/list.rs
@@ -0,0 +1,24 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::service::GitService;
7use crate::service::repos::RepoDto;
8
9#[derive(Debug, Clone, serde::Deserialize)]
10pub struct SpacePath {
11 pub space_name: String,
12}
13
14pub async fn list_repos(
15 State(service): State<GitService>,
16 _session: Session,
17 Path(path): Path<SpacePath>,
18) -> Result<AppResponseData<Vec<RepoDto>>, ApiError> {
19 let out = service
20 .list_repos(path.space_name)
21 .await
22 .map_err(GitApiError::from)?;
23 Ok(AppResponseData::ok(out))
24}
No newline at end of file
Added lib/git/src/handler/repos/mod.rs lib/git/src/handler/repos/mod.rs +5 −0 View lib/git/src/handler/repos/mod.rs
@@ -0,0 +1,5 @@
1pub mod archive;
2pub mod create;
3pub mod get;
4pub mod list;
5pub mod update;
No newline at end of file
Added lib/git/src/handler/repos/update.rs lib/git/src/handler/repos/update.rs +23 −0 View lib/git/src/handler/repos/update.rs
@@ -0,0 +1,23 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::{RepoPath, ensure_caller};
8use crate::service::GitService;
9use crate::service::repos::{RepoDto, UpdateRepoCmd};
10
11pub async fn update_repo(
12 State(service): State<GitService>,
13 session: Session,
14 Path(path): Path<RepoPath>,
15 Json(cmd): Json<UpdateRepoCmd>,
16) -> Result<AppResponseData<RepoDto>, ApiError> {
17 let caller = ensure_caller(&session)?;
18 let out = service
19 .update_repo(path.space_name, path.repo_name, caller, cmd)
20 .await
21 .map_err(GitApiError::from)?;
22 Ok(AppResponseData::ok(out))
23}
No newline at end of file
Added lib/git/src/handler/signatures/mod.rs lib/git/src/handler/signatures/mod.rs +2 −0 View lib/git/src/handler/signatures/mod.rs
@@ -0,0 +1,2 @@
1pub mod verify_commit;
2pub mod verify_tag;
No newline at end of file
Added lib/git/src/handler/signatures/verify_commit.rs lib/git/src/handler/signatures/verify_commit.rs +28 −0 View lib/git/src/handler/signatures/verify_commit.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::signatures::VerifyResultDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct CommitShaPath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub sha: String,
15}
16
17pub async fn verify_commit(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<CommitShaPath>,
21) -> Result<AppResponseData<VerifyResultDto>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .signature_verify_commit(path.space_name, path.repo_name, path.sha)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/signatures/verify_tag.rs lib/git/src/handler/signatures/verify_tag.rs +28 −0 View lib/git/src/handler/signatures/verify_tag.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::signatures::VerifyResultDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct TagNamePath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub name: String,
15}
16
17pub async fn verify_tag(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<TagNamePath>,
21) -> Result<AppResponseData<VerifyResultDto>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .signature_verify_tag(path.space_name, path.repo_name, path.name)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/submodules/list.rs lib/git/src/handler/submodules/list.rs +27 −0 View lib/git/src/handler/submodules/list.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::submodules::SubmoduleDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct SubmoduleListQuery {
12 pub revision: String,
13}
14
15pub async fn submodule_list(
16 State(service): State<GitService>,
17 session: Session,
18 Path(path): Path<crate::handler::RepoPath>,
19 Query(q): Query<SubmoduleListQuery>,
20) -> Result<AppResponseData<Vec<SubmoduleDto>>, ApiError> {
21 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 let out = service
23 .submodule_list(path.space_name, path.repo_name, q.revision)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(out))
27}
No newline at end of file
Added lib/git/src/handler/submodules/mod.rs lib/git/src/handler/submodules/mod.rs +2 −0 View lib/git/src/handler/submodules/mod.rs
@@ -0,0 +1,2 @@
1pub mod list;
2pub mod resolve;
No newline at end of file
Added lib/git/src/handler/submodules/resolve.rs lib/git/src/handler/submodules/resolve.rs +27 −0 View lib/git/src/handler/submodules/resolve.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8
9#[derive(Debug, Clone, serde::Deserialize)]
10pub struct SubmoduleResolveQuery {
11 pub revision: String,
12 pub path: String,
13}
14
15pub async fn submodule_resolve(
16 State(service): State<GitService>,
17 session: Session,
18 Path(path): Path<crate::handler::RepoPath>,
19 Query(q): Query<SubmoduleResolveQuery>,
20) -> Result<AppResponseData<String>, ApiError> {
21 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 let out = service
23 .submodule_resolve(path.space_name, path.repo_name, q.revision, q.path)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(out))
27}
No newline at end of file
Added lib/git/src/handler/tags/create.rs lib/git/src/handler/tags/create.rs +23 −0 View lib/git/src/handler/tags/create.rs
@@ -0,0 +1,23 @@
1use axum::Json;
2use axum::extract::{Path, State};
3use export::rest::AppResponseData;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::require_writer;
8use crate::service::GitService;
9use crate::service::tags::{CreateTagCmd, TagDto};
10
11pub async fn create_tag(
12 State(service): State<GitService>,
13 session: Session,
14 Path(path): Path<crate::handler::RepoPath>,
15 Json(cmd): Json<CreateTagCmd>,
16) -> Result<AppResponseData<TagDto>, ApiError> {
17 let _ = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
18 let out = service
19 .create_tag(path.space_name, path.repo_name, cmd)
20 .await
21 .map_err(GitApiError::from)?;
22 Ok(AppResponseData::ok(out))
23}
No newline at end of file
Added lib/git/src/handler/tags/delete.rs lib/git/src/handler/tags/delete.rs +27 −0 View lib/git/src/handler/tags/delete.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, State};
2use export::rest::{AppResponseData, NoData};
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::require_writer;
7use crate::service::GitService;
8
9#[derive(Debug, Clone, serde::Deserialize)]
10pub struct TagPath {
11 pub space_name: String,
12 pub repo_name: String,
13 pub name: String,
14}
15
16pub async fn delete_tag(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<TagPath>,
20) -> Result<AppResponseData<NoData>, ApiError> {
21 let _ = require_writer(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 service
23 .delete_tag(path.space_name, path.repo_name, path.name)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(NoData))
27}
No newline at end of file
Added lib/git/src/handler/tags/get.rs lib/git/src/handler/tags/get.rs +28 −0 View lib/git/src/handler/tags/get.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::tags::TagDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct TagPath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub name: String,
15}
16
17pub async fn get_tag(
18 State(service): State<GitService>,
19 session: Session,
20 Path(path): Path<TagPath>,
21) -> Result<AppResponseData<TagDto>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .get_tag(path.space_name, path.repo_name, path.name)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/tags/list.rs lib/git/src/handler/tags/list.rs +21 −0 View lib/git/src/handler/tags/list.rs
@@ -0,0 +1,21 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::tags::TagDto;
9
10pub async fn list_tags(
11 State(service): State<GitService>,
12 session: Session,
13 Path(path): Path<crate::handler::RepoPath>,
14) -> Result<AppResponseData<Vec<TagDto>>, ApiError> {
15 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
16 let out = service
17 .list_tags(path.space_name, path.repo_name)
18 .await
19 .map_err(GitApiError::from)?;
20 Ok(AppResponseData::ok(out))
21}
No newline at end of file
Added lib/git/src/handler/tags/mod.rs lib/git/src/handler/tags/mod.rs +5 −0 View lib/git/src/handler/tags/mod.rs
@@ -0,0 +1,5 @@
1pub mod create;
2pub mod delete;
3pub mod get;
4pub mod list;
5pub mod verify;
No newline at end of file
Added lib/git/src/handler/tags/verify.rs lib/git/src/handler/tags/verify.rs +41 −0 View lib/git/src/handler/tags/verify.rs
@@ -0,0 +1,41 @@
1use axum::extract::{Path, State};
2use export::rest::AppResponseData;
3use serde::Serialize;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct TagPath {
12 pub space_name: String,
13 pub repo_name: String,
14 pub name: String,
15}
16
17#[derive(Debug, Clone, Serialize)]
18pub struct TagVerifyDto {
19 pub valid: bool,
20 pub signer: Option<String>,
21 pub fingerprint: Option<String>,
22 pub error_message: Option<String>,
23}
24
25pub async fn verify_tag(
26 State(service): State<GitService>,
27 session: Session,
28 Path(path): Path<TagPath>,
29) -> Result<AppResponseData<TagVerifyDto>, ApiError> {
30 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
31 let out = service
32 .verify_tag(path.space_name, path.repo_name, path.name)
33 .await
34 .map_err(GitApiError::from)?;
35 Ok(AppResponseData::ok(TagVerifyDto {
36 valid: out.valid,
37 signer: out.signer,
38 fingerprint: out.fingerprint,
39 error_message: out.error_message,
40 }))
41}
No newline at end of file
Added lib/git/src/handler/trees/follow.rs lib/git/src/handler/trees/follow.rs +39 −0 View lib/git/src/handler/trees/follow.rs
@@ -0,0 +1,39 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use gitbaby::commit::types::TreeEntry;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Serialize)]
11pub struct TreeFollowResponse {
12 pub entry: TreeEntry,
13 pub symlink_target: Option<String>,
14 pub target_entry: Option<TreeEntry>,
15}
16
17#[derive(Debug, Clone, serde::Deserialize)]
18pub struct TreeFollowQuery {
19 pub revision: String,
20 pub path: String,
21}
22
23pub async fn tree_follow(
24 State(service): State<GitService>,
25 session: Session,
26 Path(path): Path<crate::handler::RepoPath>,
27 Query(q): Query<TreeFollowQuery>,
28) -> Result<AppResponseData<TreeFollowResponse>, ApiError> {
29 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
30 let (entry, symlink_target, target_entry) = service
31 .tree_follow(path.space_name, path.repo_name, q.revision, q.path)
32 .await
33 .map_err(GitApiError::from)?;
34 Ok(AppResponseData::ok(TreeFollowResponse {
35 entry,
36 symlink_target,
37 target_entry,
38 }))
39}
No newline at end of file
Added lib/git/src/handler/trees/last_updated.rs lib/git/src/handler/trees/last_updated.rs +27 −0 View lib/git/src/handler/trees/last_updated.rs
@@ -0,0 +1,27 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::trees::PathLastUpdated;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct TreeLastUpdatedQuery {
12 pub revision: String,
13}
14
15pub async fn tree_last_updated(
16 State(service): State<GitService>,
17 session: Session,
18 Path(path): Path<crate::handler::RepoPath>,
19 Query(q): Query<TreeLastUpdatedQuery>,
20) -> Result<AppResponseData<Vec<PathLastUpdated>>, ApiError> {
21 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
22 let out = service
23 .tree_last_updated(path.space_name, path.repo_name, q.revision)
24 .await
25 .map_err(GitApiError::from)?;
26 Ok(AppResponseData::ok(out))
27}
No newline at end of file
Added lib/git/src/handler/trees/mod.rs lib/git/src/handler/trees/mod.rs +5 −0 View lib/git/src/handler/trees/mod.rs
@@ -0,0 +1,5 @@
1pub mod follow;
2pub mod last_updated;
3pub mod read;
4pub mod resolve_path;
5pub mod walk;
No newline at end of file
Added lib/git/src/handler/trees/read.rs lib/git/src/handler/trees/read.rs +42 −0 View lib/git/src/handler/trees/read.rs
@@ -0,0 +1,42 @@
1use std::path::PathBuf;
2
3use axum::extract::{Path, Query, State};
4use export::rest::AppResponseData;
5use gitbaby::commit::types::TreeEntry;
6use session::Session;
7
8use crate::errors::{ApiError, GitApiError};
9use crate::handler::resolve_reader;
10use crate::service::GitService;
11
12#[derive(Debug, Clone, serde::Deserialize)]
13pub struct TreePath {
14 pub space_name: String,
15 pub repo_name: String,
16 pub revision: String,
17}
18
19#[derive(Debug, Clone, serde::Deserialize)]
20pub struct TreeReadQuery {
21 #[serde(default)]
22 pub path: Option<String>,
23}
24
25pub async fn tree_read(
26 State(service): State<GitService>,
27 session: Session,
28 Path(path): Path<TreePath>,
29 Query(q): Query<TreeReadQuery>,
30) -> Result<AppResponseData<Vec<TreeEntry>>, ApiError> {
31 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
32 let out = service
33 .tree_read(
34 path.space_name,
35 path.repo_name,
36 path.revision,
37 PathBuf::from(q.path.unwrap_or_default()),
38 )
39 .await
40 .map_err(GitApiError::from)?;
41 Ok(AppResponseData::ok(out))
42}
No newline at end of file
Added lib/git/src/handler/trees/resolve_path.rs lib/git/src/handler/trees/resolve_path.rs +28 −0 View lib/git/src/handler/trees/resolve_path.rs
@@ -0,0 +1,28 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use gitbaby::commit::types::TreeEntry;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct TreeResolveQuery {
12 pub revision: String,
13 pub path: String,
14}
15
16pub async fn tree_resolve_path(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<crate::handler::RepoPath>,
20 Query(q): Query<TreeResolveQuery>,
21) -> Result<AppResponseData<TreeEntry>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
23 let out = service
24 .tree_resolve_path(path.space_name, path.repo_name, q.revision, q.path)
25 .await
26 .map_err(GitApiError::from)?;
27 Ok(AppResponseData::ok(out))
28}
No newline at end of file
Added lib/git/src/handler/trees/walk.rs lib/git/src/handler/trees/walk.rs +37 −0 View lib/git/src/handler/trees/walk.rs
@@ -0,0 +1,37 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use gitbaby::commit::types::TreeEntry;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct TreeWalkQuery {
12 pub revision: String,
13 #[serde(default)]
14 pub recurse: Option<bool>,
15 #[serde(default)]
16 pub show_trees: Option<bool>,
17}
18
19pub async fn tree_walk(
20 State(service): State<GitService>,
21 session: Session,
22 Path(path): Path<crate::handler::RepoPath>,
23 Query(q): Query<TreeWalkQuery>,
24) -> Result<AppResponseData<Vec<TreeEntry>>, ApiError> {
25 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone()).await?;
26 let out = service
27 .tree_walk(
28 path.space_name,
29 path.repo_name,
30 q.revision,
31 q.recurse.unwrap_or(false),
32 q.show_trees.unwrap_or(false),
33 )
34 .await
35 .map_err(GitApiError::from)?;
36 Ok(AppResponseData::ok(out))
37}
No newline at end of file
Added lib/git/src/handler/blame.rs lib/git/src/handler/blame.rs +40 −0 View lib/git/src/handler/blame.rs
@@ -0,0 +1,40 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::blame::BlameRangeDto;
8use crate::service::GitService;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct BlameQuery {
12 pub revision: String,
13 pub path: String,
14 #[serde(default)]
15 pub range_start: Option<u32>,
16 #[serde(default)]
17 pub range_end: Option<u32>,
18}
19
20pub async fn blame(
21 State(service): State<GitService>,
22 session: Session,
23 Path(path): Path<crate::handler::RepoPath>,
24 Query(q): Query<BlameQuery>,
25) -> Result<AppResponseData<Vec<BlameRangeDto>>, ApiError> {
26 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone())
27 .await?;
28 let ranges = service
29 .blame(
30 path.space_name,
31 path.repo_name,
32 q.revision,
33 std::path::PathBuf::from(q.path),
34 q.range_start,
35 q.range_end,
36 )
37 .await
38 .map_err(GitApiError::from)?;
39 Ok(AppResponseData::ok(ranges))
40}
No newline at end of file
Added lib/git/src/handler/graphql.rs lib/git/src/handler/graphql.rs +30 −0 View lib/git/src/handler/graphql.rs
@@ -0,0 +1,30 @@
1use axum::Json;
2use axum::extract::State;
3use axum::response::IntoResponse;
4
5use crate::errors::ApiError;
6use crate::graphql::{build_schema, GitSchema};
7use crate::service::GitService;
8
9pub async fn graphql_post(
10 State(_service): State<GitService>,
11 schema: axum::extract::Extension<GitSchema>,
12 Json(request): Json<async_graphql::Request>,
13) -> Result<axum::response::Response, ApiError> {
14 let response = schema.execute(request).await;
15 Ok(Json(response).into_response())
16}
17
18pub async fn graphql_get(
19 State(_service): State<GitService>,
20 schema: axum::extract::Extension<GitSchema>,
21) -> Result<axum::response::Response, ApiError> {
22 let request = async_graphql::Request::new("{ __typename }");
23 let response = schema.execute(request).await;
24 Ok(Json(response).into_response())
25}
26
27#[allow(dead_code)]
28pub fn build_schema_for(service: GitService) -> GitSchema {
29 build_schema(service.state)
30}
No newline at end of file
Added lib/git/src/handler/mod.rs lib/git/src/handler/mod.rs +28 −0 View lib/git/src/handler/mod.rs
@@ -0,0 +1,28 @@
1pub mod analysis;
2pub mod archives;
3pub mod blame;
4pub mod blobs;
5pub mod branches;
6pub mod commits;
7pub mod conflicts;
8pub mod content;
9pub mod diffs;
10pub mod graphql;
11pub mod hooks;
12pub mod lfs;
13pub mod logs;
14pub mod maintenance;
15pub mod packs;
16pub mod patches;
17pub mod path_log;
18pub mod pipelines;
19pub mod refs;
20pub mod remotes;
21pub mod repos;
22pub mod share;
23pub mod signatures;
24pub mod submodules;
25pub mod tags;
26pub mod trees;
27
28pub use share::{RepoPath, RepoPathRev, ensure_caller, require_writer, resolve_reader};
No newline at end of file
Added lib/git/src/handler/path_log.rs lib/git/src/handler/path_log.rs +34 −0 View lib/git/src/handler/path_log.rs
@@ -0,0 +1,34 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use session::Session;
4
5use crate::errors::{ApiError, GitApiError};
6use crate::handler::resolve_reader;
7use crate::service::GitService;
8use crate::service::path_log::PathLogEntryDto;
9
10#[derive(Debug, Clone, serde::Deserialize)]
11pub struct PathLogQuery {
12 pub commit_hash: String,
13 pub target_dir: String,
14}
15
16pub async fn path_log(
17 State(service): State<GitService>,
18 session: Session,
19 Path(path): Path<crate::handler::RepoPath>,
20 Query(q): Query<PathLogQuery>,
21) -> Result<AppResponseData<Vec<PathLogEntryDto>>, ApiError> {
22 let _ = resolve_reader(&service, &session, path.space_name.clone(), path.repo_name.clone())
23 .await?;
24 let entries = service
25 .path_log(
26 path.space_name,
27 path.repo_name,
28 q.commit_hash,
29 std::path::PathBuf::from(q.target_dir),
30 )
31 .await
32 .map_err(GitApiError::from)?;
33 Ok(AppResponseData::ok(entries))
34}
No newline at end of file
Added lib/git/src/handler/share.rs lib/git/src/handler/share.rs +95 −0 View lib/git/src/handler/share.rs
@@ -0,0 +1,95 @@
1use axum::extract::{FromRequestParts, Path};
2use axum::http::request::Parts;
3use serde::Deserialize;
4use session::{Session, SessionUser};
5use utoipa::IntoParams;
6use uuid::Uuid;
7
8use crate::errors::ApiError;
9use crate::service::GitService;
10use crate::share::access::authorize_repo_access;
11
12#[derive(Debug, Clone, Deserialize, IntoParams)]
13pub struct RepoPath {
14 pub space_name: String,
15 pub repo_name: String,
16}
17
18#[derive(Debug, Clone, Deserialize, IntoParams)]
19pub struct RepoPathRev {
20 pub space_name: String,
21 pub repo_name: String,
22 pub revision: String,
23}
24
25impl<S> FromRequestParts<S> for RepoPath
26where
27 S: Send + Sync,
28{
29 type Rejection = ApiError;
30
31 async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
32 Path::<RepoPath>::from_request_parts(parts, state)
33 .await
34 .map(|Path(p)| p)
35 .map_err(|_| ApiError::bad_request())
36 }
37}
38
39pub fn ensure_caller(session: &Session) -> Result<Uuid, ApiError> {
40 session.uid().ok_or(ApiError::unauthorized())
41}
42
43pub async fn resolve_reader(
44 service: &GitService,
45 session: &Session,
46 space_name: String,
47 repo_name: String,
48) -> Result<(crate::context::facade::GitContext, Option<Uuid>), ApiError> {
49 let ctx = service
50 .context(space_name, repo_name)
51 .await
52 .map_err(super::super::errors::GitApiError::from)?;
53 if ctx.model.is_private {
54 let uid = session.uid().ok_or(ApiError::unauthorized())?;
55 authorize_repo_access(service, uid, &ctx, false, false)
56 .await
57 .map_err(super::super::errors::GitApiError::from)?;
58 Ok((ctx, Some(uid)))
59 } else {
60 Ok((ctx, session.uid()))
61 }
62}
63
64pub async fn ensure_read_access(
65 service: &GitService,
66 session: &Session,
67 ctx: &crate::context::facade::GitContext,
68) -> Result<Option<Uuid>, ApiError> {
69 if ctx.model.is_private {
70 let uid = session.uid().ok_or(ApiError::unauthorized())?;
71 authorize_repo_access(service, uid, ctx, false, false)
72 .await
73 .map_err(super::super::errors::GitApiError::from)?;
74 Ok(Some(uid))
75 } else {
76 Ok(session.uid())
77 }
78}
79
80pub async fn require_writer(
81 service: &GitService,
82 session: &Session,
83 space_name: String,
84 repo_name: String,
85) -> Result<(crate::context::facade::GitContext, Uuid), ApiError> {
86 let ctx = service
87 .context(space_name, repo_name)
88 .await
89 .map_err(super::super::errors::GitApiError::from)?;
90 let uid = session.uid().ok_or(ApiError::unauthorized())?;
91 authorize_repo_access(service, uid, &ctx, true, false)
92 .await
93 .map_err(super::super::errors::GitApiError::from)?;
94 Ok((ctx, uid))
95}
No newline at end of file
Added lib/git/src/errors.rs lib/git/src/errors.rs +169 −0 View lib/git/src/errors.rs
@@ -0,0 +1,169 @@
1use std::fmt;
2
3use axum::extract::rejection::{PathRejection, QueryRejection};
4use axum::http::StatusCode;
5use axum::response::{IntoResponse, Response};
6use axum::Json;
7use export::rest::{AppResponseData, NoData};
8use utoipa::IntoResponses;
9
10use crate::share::errors::GitError;
11
12#[derive(Debug)]
13pub enum GitApiError {
14 BadRequest(String),
15 Unauthorized,
16 Forbidden,
17 NotFound,
18 Conflict(String),
19 Internal(String),
20}
21
22impl fmt::Display for GitApiError {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 match self {
25 Self::BadRequest(message) => write!(f, "{message}"),
26 Self::Unauthorized => write!(f, "unauthorized"),
27 Self::Forbidden => write!(f, "forbidden"),
28 Self::NotFound => write!(f, "not found"),
29 Self::Conflict(message) => write!(f, "{message}"),
30 Self::Internal(message) => write!(f, "{message}"),
31 }
32 }
33}
34
35impl std::error::Error for GitApiError {}
36
37impl From<GitError> for GitApiError {
38 fn from(error: GitError) -> Self {
39 match error {
40 GitError::NotFound => Self::NotFound,
41 GitError::Unauthorized => Self::Unauthorized,
42 GitError::Forbidden => Self::Forbidden,
43 GitError::Conflict(msg) => Self::Conflict(msg),
44 GitError::InvalidArgument(msg) => Self::BadRequest(msg),
45 GitError::Cache(_) | GitError::Git(_) | GitError::Internal(_) => {
46 tracing::warn!(error = %error, "git handler failed");
47 Self::Internal("internal server error".to_string())
48 }
49 }
50 }
51}
52
53impl From<sea_orm::DbErr> for GitApiError {
54 fn from(error: sea_orm::DbErr) -> Self {
55 if is_unique_violation(&error) {
56 return Self::Conflict("resource already exists".to_string());
57 }
58 Self::Internal(format!("database error: {error}"))
59 }
60}
61
62impl From<serde_json::Error> for GitApiError {
63 fn from(error: serde_json::Error) -> Self {
64 Self::BadRequest(format!("invalid payload: {error}"))
65 }
66}
67
68fn is_unique_violation(err: &sea_orm::DbErr) -> bool {
69 let msg = err.to_string().to_lowercase();
70 msg.contains("unique") || msg.contains("duplicate") || msg.contains("23505")
71}
72
73#[derive(Debug, IntoResponses)]
74pub enum ApiError {
75 #[response(status = 400, description = "request failed validation")]
76 BadRequest(#[to_schema] AppResponseData<NoData>),
77 #[response(status = 401, description = "authentication required")]
78 Unauthorized(#[to_schema] AppResponseData<NoData>),
79 #[response(status = 403, description = "operation not allowed")]
80 Forbidden(#[to_schema] AppResponseData<NoData>),
81 #[response(status = 404, description = "resource not found")]
82 NotFound(#[to_schema] AppResponseData<NoData>),
83 #[response(status = 409, description = "resource conflict")]
84 Conflict(#[to_schema] AppResponseData<NoData>),
85 #[response(status = 500, description = "internal server error")]
86 Internal(#[to_schema] AppResponseData<NoData>),
87}
88
89impl ApiError {
90 fn payload(code: i32, message: &'static str) -> AppResponseData<NoData> {
91 AppResponseData::err(code, message)
92 }
93
94 fn decompose(self) -> (u16, AppResponseData<NoData>) {
95 match self {
96 Self::BadRequest(envelope) => (400, envelope),
97 Self::Unauthorized(envelope) => (401, envelope),
98 Self::Forbidden(envelope) => (403, envelope),
99 Self::NotFound(envelope) => (404, envelope),
100 Self::Conflict(envelope) => (409, envelope),
101 Self::Internal(envelope) => (500, envelope),
102 }
103 }
104}
105
106impl ApiError {
107 pub fn bad_request() -> Self {
108 Self::BadRequest(Self::payload(400, "bad request"))
109 }
110
111 pub fn unauthorized() -> Self {
112 Self::Unauthorized(Self::payload(401, "unauthorized"))
113 }
114
115 pub fn forbidden() -> Self {
116 Self::Forbidden(Self::payload(403, "forbidden"))
117 }
118
119 pub fn not_found() -> Self {
120 Self::NotFound(Self::payload(404, "not found"))
121 }
122
123 pub fn conflict(message: impl Into<String>) -> Self {
124 Self::Conflict(AppResponseData::err(409, message))
125 }
126
127 pub fn internal() -> Self {
128 Self::Internal(Self::payload(500, "internal server error"))
129 }
130}
131
132impl IntoResponse for ApiError {
133 fn into_response(self) -> Response {
134 let (code, envelope) = self.decompose();
135 let status = match StatusCode::from_u16(code) {
136 Ok(status) => status,
137 Err(_) => StatusCode::INTERNAL_SERVER_ERROR,
138 };
139 (status, Json(envelope)).into_response()
140 }
141}
142
143impl From<GitApiError> for ApiError {
144 fn from(error: GitApiError) -> Self {
145 match error {
146 GitApiError::BadRequest(msg) => Self::BadRequest(AppResponseData::err(400, msg)),
147 GitApiError::Unauthorized => Self::Unauthorized(Self::payload(401, "unauthorized")),
148 GitApiError::Forbidden => Self::Forbidden(Self::payload(403, "forbidden")),
149 GitApiError::NotFound => Self::NotFound(Self::payload(404, "not found")),
150 GitApiError::Conflict(msg) => Self::Conflict(AppResponseData::err(409, msg)),
151 GitApiError::Internal(message) => {
152 tracing::warn!(error = %message, "git handler failed");
153 Self::Internal(Self::payload(500, "internal server error"))
154 }
155 }
156 }
157}
158
159impl From<PathRejection> for ApiError {
160 fn from(_error: PathRejection) -> Self {
161 Self::BadRequest(Self::payload(400, "bad request"))
162 }
163}
164
165impl From<QueryRejection> for ApiError {
166 fn from(_error: QueryRejection) -> Self {
167 Self::BadRequest(Self::payload(400, "bad request"))
168 }
169}
No newline at end of file
Modified lib/git/src/lib.rs lib/git/src/lib.rs +3 −0 View lib/git/src/lib.rs
@@ -1,6 +1,9 @@
11pub mod context;
2pub mod errors;
23pub mod graphql;
4pub mod handler;
35pub mod lfs;
6pub mod routes;
47pub mod service;
58pub mod share;
69pub mod smart;
Added lib/git/src/routes.rs lib/git/src/routes.rs +433 −0 View lib/git/src/routes.rs
@@ -0,0 +1,433 @@
1use axum::routing::{delete, get, patch, post};
2use axum::{Extension, Router};
3use crate::handler::analysis::code_activity::code_activity;
4use crate::handler::analysis::contributors::contributors;
5use crate::handler::analysis::languages::languages;
6use crate::handler::analysis::languages_read::languages_read;
7use crate::handler::archives::create::create as archive_create;
8use crate::handler::archives::create_bundle::create_bundle;
9use crate::handler::archives::download::download as archive_download;
10use crate::handler::blame::blame as blame_handler;
11use crate::handler::blobs::content::blob_content;
12use crate::handler::blobs::list_lfs_pointers::list_lfs_pointers;
13use crate::handler::blobs::metadata::blob_metadata;
14use crate::handler::blobs::raw_download::blob_raw_download as blob_raw;
15use crate::handler::branches::create::create_branch as branch_create;
16use crate::handler::branches::delete::delete_branch as branch_delete;
17use crate::handler::branches::get::get_branch as branch_get;
18use crate::handler::branches::list::list_branches as branch_list;
19use crate::handler::branches::rename::rename_branch as branch_rename;
20use crate::handler::branches::set_default::set_default_branch as branch_set_default;
21use crate::handler::commits::get::get_commit;
22use crate::handler::commits::is_ancestor::is_ancestor;
23use crate::handler::commits::list::list_commits;
24use crate::handler::commits::list_commit_statuses::list_commit_statuses;
25use crate::handler::commits::rev_parse::rev_parse;
26use crate::handler::commits::set_commit_status::set_commit_status;
27use crate::handler::commits::stats::commit_stats;
28use crate::handler::commits::sync_commit::sync_commit;
29use crate::handler::commits::tree_entries::get_tree_entries as commit_tree_entries;
30use crate::handler::conflicts::check::conflict_check;
31use crate::handler::conflicts::check_threeway::conflict_check_threeway;
32use crate::handler::conflicts::conflicted_files::conflicted_files;
33use crate::handler::conflicts::detail::conflict_detail;
34use crate::handler::content::caller_signature::caller_signature;
35use crate::handler::content::commit_object::commit_object;
36use crate::handler::content::write_blob::write_blob;
37use crate::handler::content::write_tree_from_files::write_tree_from_files;
38use crate::handler::diffs::files::diff_files;
39use crate::handler::diffs::files_changed_between::files_changed_between;
40use crate::handler::diffs::for_commit::diff_for_commit;
41use crate::handler::diffs::range_diff::range_diff;
42use crate::handler::diffs::raw::diff_raw;
43use crate::handler::diffs::short_stat::diff_short_stat;
44use crate::handler::diffs::stats::diff_stats;
45use crate::handler::diffs::tree::diff_tree;
46use crate::handler::graphql::graphql_get;
47use crate::handler::graphql::graphql_post;
48use crate::handler::hooks::execute_script::execute_script;
49use crate::handler::hooks::post_receive::post_receive as hook_post_receive;
50use crate::handler::hooks::pre_receive::pre_receive as hook_pre_receive;
51use crate::handler::logs::commits_between::log_commits_between;
52use crate::handler::logs::graph::log_graph;
53use crate::handler::logs::last_commit::log_last_commit as log_last;
54use crate::handler::logs::list::log_list as log_list_handler;
55use crate::handler::lfs::cleanup_unreferenced::cleanup_unreferenced;
56use crate::handler::lfs::list_locks::list_locks;
57use crate::handler::lfs::lock::lock;
58use crate::handler::lfs::unlock::unlock;
59use crate::handler::lfs::unlock_by_id::unlock_by_id;
60use crate::handler::lfs::verify_locks::verify_locks;
61use crate::handler::maintenance::fsck::fsck;
62use crate::handler::maintenance::prune::prune;
63use crate::handler::packs::ingest::ingest as pack_ingest;
64use crate::handler::packs::repack::repack as pack_repack;
65use crate::handler::packs::stats::stats as pack_stats;
66use crate::handler::patches::apply::patch_apply;
67use crate::handler::patches::generate::patch_generate;
68use crate::handler::patches::parse::patch_parse;
69use crate::handler::path_log::path_log;
70use crate::handler::pipelines::cancel::cancel;
71use crate::handler::pipelines::schedule::schedule;
72use crate::handler::pipelines::trigger::trigger;
73use crate::handler::refs::branches::refs_branches;
74use crate::handler::refs::delete::refs_delete;
75use crate::handler::refs::filtered::refs_list_filtered as filtered;
76use crate::handler::refs::get::refs_get;
77use crate::handler::refs::head::refs_head;
78use crate::handler::refs::is_object_in_ref::refs_is_object_in_ref as is_object_in_ref;
79use crate::handler::refs::list::refs_list;
80use crate::handler::refs::resolve::refs_resolve;
81use crate::handler::refs::update::refs_update;
82use crate::handler::remotes::add::add as remote_add;
83use crate::handler::remotes::clone_import::clone_import as remote_clone_import;
84use crate::handler::remotes::fetch::fetch as remote_fetch;
85use crate::handler::remotes::push::push as remote_push;
86use crate::handler::remotes::remove::remove as remote_remove;
87use crate::handler::repos::archive::archive_repo as repo_archive;
88use crate::handler::repos::create::create_repo as repo_create;
89use crate::handler::repos::get::get_repo as repo_get;
90use crate::handler::repos::list::list_repos as repo_list;
91use crate::handler::repos::update::update_repo as repo_update;
92use crate::handler::signatures::verify_commit::verify_commit;
93use crate::handler::signatures::verify_tag::verify_tag;
94use crate::handler::submodules::list::submodule_list as submodules_list;
95use crate::handler::submodules::resolve::submodule_resolve as submodules_resolve;
96use crate::handler::tags::create::create_tag as tag_create;
97use crate::handler::tags::delete::delete_tag as tag_delete;
98use crate::handler::tags::get::get_tag as tag_get;
99use crate::handler::tags::list::list_tags as tag_list;
100use crate::handler::tags::verify::verify_tag as tag_verify;
101use crate::handler::trees::follow::tree_follow;
102use crate::handler::trees::last_updated::tree_last_updated;
103use crate::handler::trees::read::tree_read;
104use crate::handler::trees::resolve_path::tree_resolve_path;
105use crate::handler::trees::walk::tree_walk;
106use crate::service::GitService;
107
108/// Build the git-data API router (`/repos/...` + `/graphql`).
109/// The GraphQL schema is constructed once and exposed via `Extension`.
110pub fn router(service: GitService) -> Router<GitService> {
111 let schema = crate::graphql::build_schema(service.state.clone());
112
113 Router::new()
114 .route("/graphql", post(graphql_post).get(graphql_get))
115 .nest("/repos", repos_router())
116 .layer(Extension(schema))
117 .with_state(service)
118}
119
120fn repos_router() -> Router<GitService> {
121 Router::new()
122 .route("/:space_name", post(repo_create).get(repo_list))
123 .route(
124 "/:space_name/:repo_name",
125 get(repo_get).patch(repo_update).delete(repo_archive),
126 )
127 .route("/:space_name/:repo_name/archive", post(repo_archive))
128 .route("/:space_name/:repo_name/branches", get(branch_list).post(branch_create))
129 .route(
130 "/:space_name/:repo_name/branches/:name",
131 get(branch_get).delete(branch_delete),
132 )
133 .route(
134 "/:space_name/:repo_name/branches/:from",
135 patch(branch_rename),
136 )
137 .route(
138 "/:space_name/:repo_name/branches/:name/default",
139 post(branch_set_default),
140 )
141 .route("/:space_name/:repo_name/tags", get(tag_list).post(tag_create))
142 .route(
143 "/:space_name/:repo_name/tags/:name",
144 get(tag_get).delete(tag_delete),
145 )
146 .route(
147 "/:space_name/:repo_name/tags/:name/verify",
148 get(tag_verify),
149 )
150 .route("/:space_name/:repo_name/refs", get(refs_list))
151 .route("/:space_name/:repo_name/refs/head", get(refs_head))
152 .route(
153 "/:space_name/:repo_name/refs/branches",
154 get(refs_branches),
155 )
156 .route("/:space_name/:repo_name/refs/filtered", get(filtered))
157 .route(
158 "/:space_name/:repo_name/refs/contains",
159 get(is_object_in_ref),
160 )
161 .route(
162 "/:space_name/:repo_name/refs/:name",
163 get(refs_get).patch(refs_update).delete(refs_delete),
164 )
165 .route(
166 "/:space_name/:repo_name/refs/:name/resolve",
167 get(refs_resolve),
168 )
169 .route(
170 "/:space_name/:repo_name/commits",
171 get(list_commits),
172 )
173 .route(
174 "/:space_name/:repo_name/commits/:revision",
175 get(get_commit),
176 )
177 .route(
178 "/:space_name/:repo_name/commits/stats",
179 get(commit_stats),
180 )
181 .route(
182 "/:space_name/:repo_name/commits/:revision/tree",
183 get(commit_tree_entries),
184 )
185 .route(
186 "/:space_name/:repo_name/commits/ancestor",
187 get(is_ancestor),
188 )
189 .route(
190 "/:space_name/:repo_name/commits/:revision/sync",
191 post(sync_commit),
192 )
193 .route(
194 "/:space_name/:repo_name/rev/:revision",
195 get(rev_parse),
196 )
197 .route(
198 "/:space_name/:repo_name/commit-statuses",
199 post(set_commit_status),
200 )
201 .route(
202 "/:space_name/:repo_name/commit-statuses/:sha",
203 get(list_commit_statuses),
204 )
205 .route("/:space_name/:repo_name/logs", get(log_list_handler))
206 .route(
207 "/:space_name/:repo_name/logs/between",
208 get(log_commits_between),
209 )
210 .route("/:space_name/:repo_name/logs/last", get(log_last))
211 .route("/:space_name/:repo_name/logs/graph", get(log_graph))
212 .route(
213 "/:space_name/:repo_name/path-log",
214 get(path_log),
215 )
216 .route(
217 "/:space_name/:repo_name/blobs/:oid/metadata",
218 get(blob_metadata),
219 )
220 .route(
221 "/:space_name/:repo_name/blobs/:oid/content",
222 get(blob_content),
223 )
224 .route(
225 "/:space_name/:repo_name/blobs/:oid/raw",
226 get(blob_raw),
227 )
228 .route(
229 "/:space_name/:repo_name/lfs-pointers",
230 get(list_lfs_pointers),
231 )
232 .route(
233 "/:space_name/:repo_name/tree/:revision",
234 get(tree_read),
235 )
236 .route("/:space_name/:repo_name/tree/resolve", get(tree_resolve_path))
237 .route("/:space_name/:repo_name/tree/walk", get(tree_walk))
238 .route("/:space_name/:repo_name/tree/follow", get(tree_follow))
239 .route(
240 "/:space_name/:repo_name/tree/last-updated",
241 get(tree_last_updated),
242 )
243 .route("/:space_name/:repo_name/blame", get(blame_handler))
244 .route(
245 "/:space_name/:repo_name/submodules",
246 get(submodules_list),
247 )
248 .route(
249 "/:space_name/:repo_name/submodules/resolve",
250 get(submodules_resolve),
251 )
252 .route(
253 "/:space_name/:repo_name/signatures/commit/:sha",
254 get(verify_commit),
255 )
256 .route(
257 "/:space_name/:repo_name/signatures/tag/:name",
258 get(verify_tag),
259 )
260 .route(
261 "/:space_name/:repo_name/diff/raw",
262 get(diff_raw),
263 )
264 .route(
265 "/:space_name/:repo_name/diff/files",
266 get(files_changed_between),
267 )
268 .route(
269 "/:space_name/:repo_name/diff/shortstat",
270 get(diff_short_stat),
271 )
272 .route(
273 "/:space_name/:repo_name/diff/stats",
274 get(diff_stats),
275 )
276 .route(
277 "/:space_name/:repo_name/diff/files-with-context",
278 get(diff_files),
279 )
280 .route(
281 "/:space_name/:repo_name/diff/for-commit/:commit",
282 get(diff_for_commit),
283 )
284 .route(
285 "/:space_name/:repo_name/diff/tree",
286 get(diff_tree),
287 )
288 .route(
289 "/:space_name/:repo_name/diff/range",
290 post(range_diff),
291 )
292 .route(
293 "/:space_name/:repo_name/patch/generate",
294 get(patch_generate),
295 )
296 .route(
297 "/:space_name/:repo_name/patch/apply",
298 post(patch_apply),
299 )
300 .route("/_/patch/parse", post(patch_parse))
301 .route(
302 "/:space_name/:repo_name/conflicts/check",
303 get(conflict_check),
304 )
305 .route(
306 "/:space_name/:repo_name/conflicts/files",
307 get(conflicted_files),
308 )
309 .route(
310 "/:space_name/:repo_name/conflicts/detail",
311 get(conflict_detail),
312 )
313 .route(
314 "/:space_name/:repo_name/conflicts/check-threeway",
315 post(conflict_check_threeway),
316 )
317 .route(
318 "/:space_name/:repo_name/remotes/import",
319 post(remote_clone_import),
320 )
321 .route(
322 "/:space_name/:repo_name/remotes/fetch",
323 post(remote_fetch),
324 )
325 .route(
326 "/:space_name/:repo_name/remotes/push",
327 post(remote_push),
328 )
329 .route(
330 "/:space_name/:repo_name/remotes/:name",
331 post(remote_add).delete(remote_remove),
332 )
333 .route(
334 "/:space_name/:repo_name/lfs/locks",
335 get(list_locks).post(lock).delete(unlock),
336 )
337 .route(
338 "/:space_name/:repo_name/lfs/locks/verify",
339 post(verify_locks),
340 )
341 .route(
342 "/:space_name/:repo_name/lfs/locks/:lock_id",
343 delete(unlock_by_id),
344 )
345 .route(
346 "/:space_name/:repo_name/lfs/cleanup",
347 post(cleanup_unreferenced),
348 )
349 .route(
350 "/_/hooks/pre-receive",
351 post(hook_pre_receive),
352 )
353 .route(
354 "/_/hooks/post-receive",
355 post(hook_post_receive),
356 )
357 .route(
358 "/:space_name/:repo_name/hooks/:script",
359 post(execute_script),
360 )
361 .route(
362 "/:space_name/:repo_name/pipelines/trigger",
363 post(trigger),
364 )
365 .route(
366 "/:space_name/:repo_name/pipelines/schedule",
367 post(schedule),
368 )
369 .route(
370 "/_/pipelines/cancel",
371 post(cancel),
372 )
373 .route(
374 "/:space_name/:repo_name/packs/stats",
375 get(pack_stats),
376 )
377 .route(
378 "/:space_name/:repo_name/packs/ingest",
379 post(pack_ingest),
380 )
381 .route(
382 "/:space_name/:repo_name/packs/repack",
383 post(pack_repack),
384 )
385 .route(
386 "/:space_name/:repo_name/maintenance/prune",
387 post(prune),
388 )
389 .route(
390 "/:space_name/:repo_name/maintenance/fsck",
391 post(fsck),
392 )
393 .route(
394 "/_/contents/signature",
395 post(caller_signature),
396 )
397 .route(
398 "/:space_name/:repo_name/contents/blobs",
399 post(write_blob),
400 )
401 .route(
402 "/:space_name/:repo_name/contents/trees",
403 post(write_tree_from_files),
404 )
405 .route(
406 "/:space_name/:repo_name/contents/commits",
407 post(commit_object),
408 )
409 .route(
410 "/:space_name/:repo_name/analysis/languages",
411 get(languages_read).post(languages),
412 )
413 .route(
414 "/:space_name/:repo_name/analysis/contributors",
415 get(contributors),
416 )
417 .route(
418 "/:space_name/:repo_name/analysis/code-activity",
419 get(code_activity),
420 )
421 .route(
422 "/:space_name/:repo_name/archives/create/:revision",
423 post(archive_create),
424 )
425 .route(
426 "/:space_name/:repo_name/archives/download/:revision",
427 get(archive_download),
428 )
429 .route(
430 "/:space_name/:repo_name/archives/bundle",
431 post(create_bundle),
432 )
433}
No newline at end of file