Skip to content
Clone

refactor(git): unified GET /diff?view=, GET /conflicts, GET /tree/{rev} with path/recurse/resolve/view

ZhenYi committed
parent 6956087 commit 154267f Browse files

21 files changed

+254 −698

File tree 21
Modified lib/git/src/handler/commits/mod.rs View lib/git/src/handler/commits/mod.rs
@@ -6,4 +6,3 @@
66pub mod set_commit_status;
77pub mod stats;
88pub mod sync_commit;
9pub mod tree_entries;
Deleted lib/git/src/handler/commits/tree_entries.rs
@@ -1,57 +0,0 @@
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, utoipa::IntoParams)]
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, utoipa::IntoParams)]
20pub struct TreeQuery {
21 #[serde(default)]
22 pub path: Option<String>,
23}
24
25#[utoipa::path(
26 get,
27 path = "/repos/{space_name}/{repo_name}/commits/{revision}/tree",
28 tag = "commits",
29 params(TreePath, TreeQuery),
30 responses(
31 (status = 200, description = "commit tree entries")
32 )
33)]
34pub async fn get_tree_entries(
35 State(service): State<GitService>,
36 session: Session,
37 Path(path): Path<TreePath>,
38 Query(query): Query<TreeQuery>,
39) -> Result<AppResponseData<Vec<TreeEntry>>, ApiError> {
40 let _ = resolve_reader(
41 &service,
42 &session,
43 path.space_name.clone(),
44 path.repo_name.clone(),
45 )
46 .await?;
47 let out = service
48 .get_tree_entries(
49 path.space_name,
50 path.repo_name,
51 path.revision,
52 query.path.map(PathBuf::from).unwrap_or_default(),
53 )
54 .await
55 .map_err(GitApiError::from)?;
56 Ok(AppResponseData::ok(out))
57}
Deleted lib/git/src/handler/conflicts/check.rs
@@ -1,43 +0,0 @@
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, utoipa::IntoParams)]
11pub struct ConflictBaseHeadQuery {
12 pub base: String,
13 pub head: String,
14}
15
16#[utoipa::path(
17 get,
18 path = "/repos/{space_name}/{repo_name}/conflicts/check",
19 tag = "conflicts",
20 params(crate::handler::RepoPath, ConflictBaseHeadQuery),
21 responses(
22 (status = 200, description = "check merge conflicts", body = AppResponseData<MergeStatusDto>)
23 )
24)]
25pub async fn conflict_check(
26 State(service): State<GitService>,
27 session: Session,
28 Path(path): Path<crate::handler::RepoPath>,
29 Query(q): Query<ConflictBaseHeadQuery>,
30) -> Result<AppResponseData<MergeStatusDto>, ApiError> {
31 let _ = resolve_reader(
32 &service,
33 &session,
34 path.space_name.clone(),
35 path.repo_name.clone(),
36 )
37 .await?;
38 let out = service
39 .conflict_check(path.space_name, path.repo_name, q.base, q.head)
40 .await
41 .map_err(GitApiError::from)?;
42 Ok(AppResponseData::ok(out))
43}
Deleted lib/git/src/handler/conflicts/check_threeway.rs
@@ -1,52 +0,0 @@
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, utoipa::ToSchema)]
12pub struct ConflictCheckThreewayBody {
13 pub ours: String,
14 pub theirs: String,
15 pub ancestor: String,
16}
17
18#[utoipa::path(
19 post,
20 path = "/repos/{space_name}/{repo_name}/conflicts/check-threeway",
21 tag = "conflicts",
22 params(crate::handler::RepoPath),
23 request_body = ConflictCheckThreewayBody,
24 responses(
25 (status = 200, description = "three-way merge conflict check", body = AppResponseData<MergeStatusDto>)
26 )
27)]
28pub async fn conflict_check_threeway(
29 State(service): State<GitService>,
30 session: Session,
31 Path(path): Path<crate::handler::RepoPath>,
32 Json(body): Json<ConflictCheckThreewayBody>,
33) -> Result<AppResponseData<MergeStatusDto>, ApiError> {
34 let _ = resolve_reader(
35 &service,
36 &session,
37 path.space_name.clone(),
38 path.repo_name.clone(),
39 )
40 .await?;
41 let out = service
42 .conflict_check_threeway(
43 path.space_name,
44 path.repo_name,
45 body.ours,
46 body.theirs,
47 body.ancestor,
48 )
49 .await
50 .map_err(GitApiError::from)?;
51 Ok(AppResponseData::ok(out))
52}
Deleted lib/git/src/handler/conflicts/conflicted_files.rs
@@ -1,42 +0,0 @@
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, utoipa::IntoParams)]
10pub struct ConflictBaseHeadQuery {
11 pub base: String,
12 pub head: String,
13}
14
15#[utoipa::path(
16 get,
17 path = "/repos/{space_name}/{repo_name}/conflicts/files",
18 tag = "conflicts",
19 params(crate::handler::RepoPath, ConflictBaseHeadQuery),
20 responses(
21 (status = 200, description = "conflicted files", body = AppResponseData<Vec<String>>)
22 )
23)]
24pub async fn conflicted_files(
25 State(service): State<GitService>,
26 session: Session,
27 Path(path): Path<crate::handler::RepoPath>,
28 Query(q): Query<ConflictBaseHeadQuery>,
29) -> Result<AppResponseData<Vec<String>>, ApiError> {
30 let _ = resolve_reader(
31 &service,
32 &session,
33 path.space_name.clone(),
34 path.repo_name.clone(),
35 )
36 .await?;
37 let out = service
38 .conflict_conflicted_files(path.space_name, path.repo_name, q.base, q.head)
39 .await
40 .map_err(GitApiError::from)?;
41 Ok(AppResponseData::ok(out))
42}
Added lib/git/src/handler/conflicts/get_conflicts.rs View lib/git/src/handler/conflicts/get_conflicts.rs
@@ -0,0 +1,60 @@
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, utoipa::IntoParams)]
11pub struct GetConflictsQuery {
12 pub base: String,
13 pub head: String,
14 #[serde(default)]
15 pub ancestor: Option<String>,
16}
17
18#[utoipa::path(
19 get,
20 path = "/repos/{space_name}/{repo_name}/conflicts",
21 tag = "conflicts",
22 params(crate::handler::RepoPath, GetConflictsQuery),
23 responses(
24 (status = 200, description = "merge conflict status", body = AppResponseData<MergeStatusDto>)
25 )
26)]
27pub async fn get_conflicts(
28 State(service): State<GitService>,
29 session: Session,
30 Path(path): Path<crate::handler::RepoPath>,
31 Query(q): Query<GetConflictsQuery>,
32) -> Result<AppResponseData<MergeStatusDto>, ApiError> {
33 let _ = resolve_reader(
34 &service,
35 &session,
36 path.space_name.clone(),
37 path.repo_name.clone(),
38 )
39 .await?;
40 let out = match q.ancestor {
41 Some(ancestor) => {
42 service
43 .conflict_check_threeway(
44 path.space_name,
45 path.repo_name,
46 q.base,
47 q.head,
48 ancestor,
49 )
50 .await
51 }
52 None => {
53 service
54 .conflict_check(path.space_name, path.repo_name, q.base, q.head)
55 .await
56 }
57 }
58 .map_err(GitApiError::from)?;
59 Ok(AppResponseData::ok(out))
60}
Modified lib/git/src/handler/conflicts/mod.rs View lib/git/src/handler/conflicts/mod.rs
@@ -1,4 +1,2 @@
1pub mod check;
2pub mod check_threeway;
3pub mod conflicted_files;
41pub mod detail;
2pub mod get_conflicts;
Deleted lib/git/src/handler/diffs/files_changed_between.rs
@@ -1,45 +0,0 @@
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, utoipa::IntoParams)]
10pub struct DiffBaseHeadQuery {
11 pub base: String,
12 pub head: String,
13}
14
15#[utoipa::path(
16 get,
17 path = "/repos/{space_name}/{repo_name}/diff/files",
18 tag = "diffs",
19 params(
20 crate::handler::RepoPath,
21 DiffBaseHeadQuery,
22 ),
23 responses(
24 (status = 200, description = "files changed between revisions", body = AppResponseData<Vec<String>>)
25 )
26)]
27pub async fn files_changed_between(
28 State(service): State<GitService>,
29 session: Session,
30 Path(path): Path<crate::handler::RepoPath>,
31 Query(q): Query<DiffBaseHeadQuery>,
32) -> Result<AppResponseData<Vec<String>>, ApiError> {
33 let _ = resolve_reader(
34 &service,
35 &session,
36 path.space_name.clone(),
37 path.repo_name.clone(),
38 )
39 .await?;
40 let out = service
41 .diff_files_changed_between(path.space_name, path.repo_name, q.base, q.head)
42 .await
43 .map_err(GitApiError::from)?;
44 Ok(AppResponseData::ok(out))
45}
Added lib/git/src/handler/diffs/get_diff.rs View lib/git/src/handler/diffs/get_diff.rs
@@ -0,0 +1,107 @@
1use axum::extract::{Path, Query, State};
2use export::rest::AppResponseData;
3use serde::Deserialize;
4use session::Session;
5
6use crate::errors::{ApiError, GitApiError};
7use crate::handler::resolve_reader;
8use crate::service::GitService;
9use crate::service::diffs::DiffOptionsDto;
10use crate::share::errors::GitError;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, utoipa::ToSchema)]
13#[serde(rename_all = "lowercase")]
14pub enum DiffView {
15 Shortstat,
16 Numstat,
17 Files,
18 Tree,
19}
20
21#[derive(Debug, Clone, Deserialize, utoipa::IntoParams)]
22pub struct GetDiffQuery {
23 pub base: String,
24 pub head: String,
25 #[serde(default = "default_view")]
26 pub view: DiffView,
27 #[serde(default)]
28 pub use_merge_base: bool,
29}
30
31fn default_view() -> DiffView {
32 DiffView::Numstat
33}
34
35fn json_err(e: serde_json::Error) -> ApiError {
36 GitApiError::from(GitError::Internal(e.to_string())).into()
37}
38
39#[utoipa::path(
40 get,
41 path = "/repos/{space_name}/{repo_name}/diff",
42 tag = "diffs",
43 params(
44 crate::handler::RepoPath,
45 GetDiffQuery,
46 ),
47 responses(
48 (status = 200, description = "diff payload shaped by view (shortstat | numstat | files | tree)", body = AppResponseData<serde_json::Value>)
49 )
50)]
51pub async fn get_diff(
52 State(service): State<GitService>,
53 session: Session,
54 Path(path): Path<crate::handler::RepoPath>,
55 Query(q): Query<GetDiffQuery>,
56) -> Result<AppResponseData<serde_json::Value>, ApiError> {
57 let _ = resolve_reader(
58 &service,
59 &session,
60 path.space_name.clone(),
61 path.repo_name.clone(),
62 )
63 .await?;
64 let out = match q.view {
65 DiffView::Shortstat => {
66 let s = service
67 .diff_short_stat(path.space_name, path.repo_name, q.base, q.head)
68 .await
69 .map_err(GitApiError::from)?;
70 serde_json::to_value(s).map_err(json_err)?
71 }
72 DiffView::Numstat => {
73 let s = service
74 .diff_stats(
75 path.space_name,
76 path.repo_name,
77 q.base,
78 q.head,
79 DiffOptionsDto::default(),
80 )
81 .await
82 .map_err(GitApiError::from)?;
83 serde_json::to_value(s).map_err(json_err)?
84 }
85 DiffView::Files => {
86 let f = service
87 .diff_files_changed_between(path.space_name, path.repo_name, q.base, q.head)
88 .await
89 .map_err(GitApiError::from)?;
90 serde_json::to_value(f).map_err(json_err)?
91 }
92 DiffView::Tree => {
93 let t = service
94 .diff_tree(
95 path.space_name,
96 path.repo_name,
97 q.base,
98 q.head,
99 q.use_merge_base,
100 )
101 .await
102 .map_err(GitApiError::from)?;
103 serde_json::to_value(t).map_err(json_err)?
104 }
105 };
106 Ok(AppResponseData::ok(out))
107}
Modified lib/git/src/handler/diffs/mod.rs View lib/git/src/handler/diffs/mod.rs
@@ -1,7 +1,4 @@
1pub mod files_changed_between;
21pub mod for_commit;
2pub mod get_diff;
33pub mod range_diff;
44pub mod raw;
5pub mod short_stat;
6pub mod stats;
7pub mod tree;
Deleted lib/git/src/handler/diffs/short_stat.rs
@@ -1,46 +0,0 @@
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, utoipa::IntoParams)]
11pub struct DiffBaseHeadQuery {
12 pub base: String,
13 pub head: String,
14}
15
16#[utoipa::path(
17 get,
18 path = "/repos/{space_name}/{repo_name}/diff/shortstat",
19 tag = "diffs",
20 params(
21 crate::handler::RepoPath,
22 DiffBaseHeadQuery,
23 ),
24 responses(
25 (status = 200, description = "diff short stat")
26 )
27)]
28pub async fn diff_short_stat(
29 State(service): State<GitService>,
30 session: Session,
31 Path(path): Path<crate::handler::RepoPath>,
32 Query(q): Query<DiffBaseHeadQuery>,
33) -> Result<AppResponseData<ShortStat>, ApiError> {
34 let _ = resolve_reader(
35 &service,
36 &session,
37 path.space_name.clone(),
38 path.repo_name.clone(),
39 )
40 .await?;
41 let out = service
42 .diff_short_stat(path.space_name, path.repo_name, q.base, q.head)
43 .await
44 .map_err(GitApiError::from)?;
45 Ok(AppResponseData::ok(out))
46}
Deleted lib/git/src/handler/diffs/stats.rs
@@ -1,53 +0,0 @@
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, utoipa::IntoParams)]
12pub struct DiffBaseHeadQuery {
13 pub base: String,
14 pub head: String,
15}
16
17#[utoipa::path(
18 get,
19 path = "/repos/{space_name}/{repo_name}/diff/stats",
20 tag = "diffs",
21 params(
22 crate::handler::RepoPath,
23 DiffBaseHeadQuery,
24 ),
25 responses(
26 (status = 200, description = "diff stats")
27 )
28)]
29pub async fn diff_stats(
30 State(service): State<GitService>,
31 session: Session,
32 Path(path): Path<crate::handler::RepoPath>,
33 Query(q): Query<DiffBaseHeadQuery>,
34) -> Result<AppResponseData<Vec<NumStat>>, ApiError> {
35 let _ = resolve_reader(
36 &service,
37 &session,
38 path.space_name.clone(),
39 path.repo_name.clone(),
40 )
41 .await?;
42 let out = service
43 .diff_stats(
44 path.space_name,
45 path.repo_name,
46 q.base,
47 q.head,
48 DiffOptionsDto::default(),
49 )
50 .await
51 .map_err(GitApiError::from)?;
52 Ok(AppResponseData::ok(out))
53}
Deleted lib/git/src/handler/diffs/tree.rs
@@ -1,54 +0,0 @@
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, utoipa::IntoParams)]
11pub struct DiffTreeQuery {
12 pub base: String,
13 pub head: String,
14 #[serde(default)]
15 pub use_merge_base: Option<bool>,
16}
17
18#[utoipa::path(
19 get,
20 path = "/repos/{space_name}/{repo_name}/diff/tree",
21 tag = "diffs",
22 params(
23 crate::handler::RepoPath,
24 DiffTreeQuery,
25 ),
26 responses(
27 (status = 200, description = "diff trees", body = AppResponseData<Vec<DiffTreeRecordDto>>)
28 )
29)]
30pub async fn diff_tree(
31 State(service): State<GitService>,
32 session: Session,
33 Path(path): Path<crate::handler::RepoPath>,
34 Query(q): Query<DiffTreeQuery>,
35) -> Result<AppResponseData<Vec<DiffTreeRecordDto>>, ApiError> {
36 let _ = resolve_reader(
37 &service,
38 &session,
39 path.space_name.clone(),
40 path.repo_name.clone(),
41 )
42 .await?;
43 let out = service
44 .diff_tree(
45 path.space_name,
46 path.repo_name,
47 q.base,
48 q.head,
49 q.use_merge_base.unwrap_or(false),
50 )
51 .await
52 .map_err(GitApiError::from)?;
53 Ok(AppResponseData::ok(out))
54}
Deleted lib/git/src/handler/trees/follow.rs
@@ -1,57 +0,0 @@
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, utoipa::IntoParams)]
18pub struct TreeFollowQuery {
19 pub revision: String,
20 pub path: String,
21}
22
23#[utoipa::path(
24 get,
25 path = "/repos/{space_name}/{repo_name}/tree/follow",
26 tag = "trees",
27 params(
28 crate::handler::RepoPath,
29 TreeFollowQuery,
30 ),
31 responses(
32 (status = 200, description = "follow tree entry through symlink")
33 )
34)]
35pub async fn tree_follow(
36 State(service): State<GitService>,
37 session: Session,
38 Path(path): Path<crate::handler::RepoPath>,
39 Query(q): Query<TreeFollowQuery>,
40) -> Result<AppResponseData<TreeFollowResponse>, ApiError> {
41 let _ = resolve_reader(
42 &service,
43 &session,
44 path.space_name.clone(),
45 path.repo_name.clone(),
46 )
47 .await?;
48 let (entry, symlink_target, target_entry) = service
49 .tree_follow(path.space_name, path.repo_name, q.revision, q.path)
50 .await
51 .map_err(GitApiError::from)?;
52 Ok(AppResponseData::ok(TreeFollowResponse {
53 entry,
54 symlink_target,
55 target_entry,
56 }))
57}
Deleted lib/git/src/handler/trees/last_updated.rs
@@ -1,47 +0,0 @@
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, utoipa::IntoParams)]
11pub struct TreeLastUpdatedQuery {
12 pub revision: String,
13 #[serde(default)]
14 pub path: Option<String>,
15}
16
17#[utoipa::path(
18 get,
19 path = "/repos/{space_name}/{repo_name}/tree/last-updated",
20 tag = "trees",
21 params(
22 crate::handler::RepoPath,
23 TreeLastUpdatedQuery,
24 ),
25 responses(
26 (status = 200, description = "last updated tree entries", body = AppResponseData<Vec<PathLastUpdated>>)
27 )
28)]
29pub async fn tree_last_updated(
30 State(service): State<GitService>,
31 session: Session,
32 Path(path): Path<crate::handler::RepoPath>,
33 Query(q): Query<TreeLastUpdatedQuery>,
34) -> Result<AppResponseData<Vec<PathLastUpdated>>, ApiError> {
35 let _ = resolve_reader(
36 &service,
37 &session,
38 path.space_name.clone(),
39 path.repo_name.clone(),
40 )
41 .await?;
42 let out = service
43 .tree_last_updated(path.space_name, path.repo_name, q.revision, q.path)
44 .await
45 .map_err(GitApiError::from)?;
46 Ok(AppResponseData::ok(out))
47}
Modified lib/git/src/handler/trees/mod.rs View lib/git/src/handler/trees/mod.rs
@@ -1,5 +1 @@
1pub mod follow;
2pub mod last_updated;
31pub mod read;
4pub mod resolve_path;
5pub mod walk;
Modified lib/git/src/handler/trees/read.rs View lib/git/src/handler/trees/read.rs
@@ -2,24 +2,33 @@
22
33use axum::extract::{Path, Query, State};
44use export::rest::AppResponseData;
5use gitbaby::commit::types::TreeEntry;
5use serde::Deserialize;
66use session::Session;
77
88use crate::errors::{ApiError, GitApiError};
99use crate::handler::resolve_reader;
1010use crate::service::GitService;
11use crate::share::errors::GitError;
1112
12#[derive(Debug, Clone, serde::Deserialize, utoipa::IntoParams)]
13pub struct TreePath {
14 pub space_name: String,
15 pub repo_name: String,
16 pub revision: String,
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, utoipa::ToSchema)]
14#[serde(rename_all = "snake_case")]
15pub enum TreeView {
16 Entries,
17 LastUpdated,
1718}
1819
19#[derive(Debug, Clone, serde::Deserialize, utoipa::IntoParams)]
20pub struct TreeReadQuery {
20#[derive(Debug, Clone, Deserialize, utoipa::IntoParams)]
21pub struct GetTreeQuery {
22 #[serde(default)]
23 pub path: String,
24 #[serde(default)]
25 pub recurse: bool,
26 #[serde(default)]
27 pub resolve: bool,
28 #[serde(default)]
29 pub show_trees: bool,
2130 #[serde(default)]
22 pub path: Option<String>,
31 pub view: Option<TreeView>,
2332}
2433
2534#[utoipa::path(
@@ -27,19 +36,19 @@
2736 path = "/repos/{space_name}/{repo_name}/tree/{revision}",
2837 tag = "trees",
2938 params(
30 TreePath,
31 TreeReadQuery,
39 crate::handler::RepoPathRev,
40 GetTreeQuery,
3241 ),
3342 responses(
34 (status = 200, description = "read tree entries")
43 (status = 200, description = "tree payload: entries list, single entry (resolve), or last-updated list (view=last_updated)", body = AppResponseData<serde_json::Value>)
3544 )
3645)]
37pub async fn tree_read(
46pub async fn get_tree(
3847 State(service): State<GitService>,
3948 session: Session,
40 Path(path): Path<TreePath>,
41 Query(q): Query<TreeReadQuery>,
42) -> Result<AppResponseData<Vec<TreeEntry>>, ApiError> {
49 Path(path): Path<crate::handler::RepoPathRev>,
50 Query(q): Query<GetTreeQuery>,
51) -> Result<AppResponseData<serde_json::Value>, ApiError> {
4352 let _ = resolve_reader(
4453 &service,
4554 &session,
@@ -47,14 +56,55 @@
4756 path.repo_name.clone(),
4857 )
4958 .await?;
50 let out = service
51 .tree_read(
52 path.space_name,
53 path.repo_name,
54 path.revision,
55 PathBuf::from(q.path.unwrap_or_default()),
56 )
57 .await
58 .map_err(GitApiError::from)?;
59 let out = match q.view {
60 Some(TreeView::LastUpdated) => {
61 let p = (!q.path.is_empty()).then(|| q.path.clone());
62 let rows = service
63 .tree_last_updated(path.space_name, path.repo_name, path.revision, p)
64 .await
65 .map_err(GitApiError::from)?;
66 serde_json::to_value(rows).map_err(json_err)?
67 }
68 _ => {
69 if q.resolve && !q.path.is_empty() {
70 let (entry, target, resolved) = service
71 .tree_follow(path.space_name, path.repo_name, path.revision, q.path)
72 .await
73 .map_err(GitApiError::from)?;
74 serde_json::json!({
75 "entry": entry,
76 "symlink_target": target,
77 "resolved": resolved,
78 })
79 } else if q.recurse {
80 let entries = service
81 .tree_walk(
82 path.space_name,
83 path.repo_name,
84 path.revision,
85 true,
86 q.show_trees,
87 )
88 .await
89 .map_err(GitApiError::from)?;
90 serde_json::to_value(entries).map_err(json_err)?
91 } else {
92 let entries = service
93 .tree_read(
94 path.space_name,
95 path.repo_name,
96 path.revision,
97 PathBuf::from(&q.path),
98 )
99 .await
100 .map_err(GitApiError::from)?;
101 serde_json::to_value(entries).map_err(json_err)?
102 }
103 }
104 };
59105 Ok(AppResponseData::ok(out))
60106}
107
108fn json_err(e: serde_json::Error) -> ApiError {
109 GitApiError::from(GitError::Internal(e.to_string())).into()
110}
Deleted lib/git/src/handler/trees/resolve_path.rs
@@ -1,46 +0,0 @@
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, utoipa::IntoParams)]
11pub struct TreeResolveQuery {
12 pub revision: String,
13 pub path: String,
14}
15
16#[utoipa::path(
17 get,
18 path = "/repos/{space_name}/{repo_name}/tree/resolve",
19 tag = "trees",
20 params(
21 crate::handler::RepoPath,
22 TreeResolveQuery,
23 ),
24 responses(
25 (status = 200, description = "resolve path to tree entry")
26 )
27)]
28pub async fn tree_resolve_path(
29 State(service): State<GitService>,
30 session: Session,
31 Path(path): Path<crate::handler::RepoPath>,
32 Query(q): Query<TreeResolveQuery>,
33) -> Result<AppResponseData<TreeEntry>, ApiError> {
34 let _ = resolve_reader(
35 &service,
36 &session,
37 path.space_name.clone(),
38 path.repo_name.clone(),
39 )
40 .await?;
41 let out = service
42 .tree_resolve_path(path.space_name, path.repo_name, q.revision, q.path)
43 .await
44 .map_err(GitApiError::from)?;
45 Ok(AppResponseData::ok(out))
46}
Deleted lib/git/src/handler/trees/walk.rs
@@ -1,55 +0,0 @@
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, utoipa::IntoParams)]
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
19#[utoipa::path(
20 get,
21 path = "/repos/{space_name}/{repo_name}/tree/walk",
22 tag = "trees",
23 params(
24 crate::handler::RepoPath,
25 TreeWalkQuery,
26 ),
27 responses(
28 (status = 200, description = "walk tree")
29 )
30)]
31pub async fn tree_walk(
32 State(service): State<GitService>,
33 session: Session,
34 Path(path): Path<crate::handler::RepoPath>,
35 Query(q): Query<TreeWalkQuery>,
36) -> Result<AppResponseData<Vec<TreeEntry>>, ApiError> {
37 let _ = resolve_reader(
38 &service,
39 &session,
40 path.space_name.clone(),
41 path.repo_name.clone(),
42 )
43 .await?;
44 let out = service
45 .tree_walk(
46 path.space_name,
47 path.repo_name,
48 q.revision,
49 q.recurse.unwrap_or(false),
50 q.show_trees.unwrap_or(false),
51 )
52 .await
53 .map_err(GitApiError::from)?;
54 Ok(AppResponseData::ok(out))
55}
Modified lib/git/src/openapi.rs View lib/git/src/openapi.rs
@@ -32,19 +32,13 @@
3232 handler::commits::rev_parse::rev_parse,
3333 handler::commits::set_commit_status::set_commit_status,
3434 handler::commits::stats::commit_stats,
35 handler::commits::tree_entries::get_tree_entries,
36 handler::conflicts::check::conflict_check,
37 handler::conflicts::check_threeway::conflict_check_threeway,
38 handler::conflicts::conflicted_files::conflicted_files,
3935 handler::conflicts::detail::conflict_detail,
36 handler::conflicts::get_conflicts::get_conflicts,
4037 handler::content::caller_signature::caller_signature,
41 handler::diffs::files_changed_between::files_changed_between,
4238 handler::diffs::for_commit::diff_for_commit,
4339 handler::diffs::range_diff::range_diff,
40 handler::diffs::get_diff::get_diff,
4441 handler::diffs::raw::diff_raw,
45 handler::diffs::short_stat::diff_short_stat,
46 handler::diffs::stats::diff_stats,
47 handler::diffs::tree::diff_tree,
4842 handler::hooks::execute_script::execute_script,
4943 handler::licenses::get_license,
5044 handler::licenses::list_licenses,
@@ -90,11 +84,7 @@
9084 handler::topics::list_repos_by_topic,
9185 handler::topics::list_topics,
9286 handler::topics::remove_topic_from_repo,
93 handler::trees::follow::tree_follow,
94 handler::trees::last_updated::tree_last_updated,
95 handler::trees::read::tree_read,
96 handler::trees::resolve_path::tree_resolve_path,
97 handler::trees::walk::tree_walk,
87 handler::trees::read::get_tree,
9888 handler::watches::get_watch_mode,
9989 handler::watches::list_watchers,
10090 handler::watches::unwatch,
@@ -190,7 +180,6 @@
190180 crate::service::whitelists::TagWhitelistDto,
191181 crate::handler::commits::is_ancestor::IsAncestorResponse,
192182 crate::handler::commits::sync_commit::CommitSyncResponse,
193 crate::handler::conflicts::check_threeway::ConflictCheckThreewayBody,
194183 crate::handler::content::caller_signature::CallerSignatureBody,
195184 crate::handler::content::commit_object::CommitObjectBody,
196185 crate::handler::content::write_blob::WriteBlobBody,
Modified lib/git/src/routes.rs View lib/git/src/routes.rs
@@ -23,22 +23,16 @@
2323use crate::handler::commits::set_commit_status::set_commit_status;
2424use crate::handler::commits::stats::commit_stats;
2525use crate::handler::commits::sync_commit::sync_commit;
26use crate::handler::commits::tree_entries::get_tree_entries as commit_tree_entries;
27use crate::handler::conflicts::check::conflict_check;
28use crate::handler::conflicts::check_threeway::conflict_check_threeway;
29use crate::handler::conflicts::conflicted_files::conflicted_files;
3026use crate::handler::conflicts::detail::conflict_detail;
27use crate::handler::conflicts::get_conflicts::get_conflicts;
3128use crate::handler::content::caller_signature::caller_signature;
3229use crate::handler::content::commit_object::commit_object;
3330use crate::handler::content::write_blob::write_blob;
3431use crate::handler::content::write_tree_from_files::write_tree_from_files;
35use crate::handler::diffs::files_changed_between::files_changed_between;
3632use crate::handler::diffs::for_commit::diff_for_commit;
33use crate::handler::diffs::get_diff::get_diff;
3734use crate::handler::diffs::range_diff::range_diff;
3835use crate::handler::diffs::raw::diff_raw;
39use crate::handler::diffs::short_stat::diff_short_stat;
40use crate::handler::diffs::stats::diff_stats;
41use crate::handler::diffs::tree::diff_tree;
4236use crate::handler::graphql::graphql_get;
4337use crate::handler::graphql::graphql_post;
4438use crate::handler::hooks::execute_script::execute_script;
@@ -96,11 +90,7 @@
9690 add_topic_to_repo, create_topic, get_topic, list_repo_topics, list_repos_by_topic, list_topics,
9791 remove_topic_from_repo,
9892};
99use crate::handler::trees::follow::tree_follow;
100use crate::handler::trees::last_updated::tree_last_updated;
101use crate::handler::trees::read::tree_read;
102use crate::handler::trees::resolve_path::tree_resolve_path;
103use crate::handler::trees::walk::tree_walk;
93use crate::handler::trees::read::get_tree;
10494use crate::handler::watches::{get_watch_mode, list_watchers, unwatch, upsert_watch};
10595use crate::handler::whitelists::{
10696 add_branch_whitelist, add_tag_whitelist, list_branch_whitelists, list_tag_whitelists,
@@ -164,10 +154,6 @@
164154 )
165155 .route("/{space_name}/{repo_name}/commits/stats", get(commit_stats))
166156 .route(
167 "/{space_name}/{repo_name}/commits/{revision}/tree",
168 get(commit_tree_entries),
169 )
170 .route(
171157 "/{space_name}/{repo_name}/commits/ancestor",
172158 get(is_ancestor),
173159 )
@@ -180,6 +166,7 @@
180166 "/{space_name}/{repo_name}/commit-statuses/{sha}",
181167 get(list_commit_statuses),
182168 )
169 .route("/{space_name}/{repo_name}/tree/{revision}", get(get_tree))
183170 .route("/{space_name}/{repo_name}/path-log", get(path_log))
184171 .route(
185172 "/{space_name}/{repo_name}/blobs/{oid}/metadata",
@@ -193,17 +180,7 @@
193180 "/{space_name}/{repo_name}/lfs-pointers",
194181 get(list_lfs_pointers),
195182 )
196 .route("/{space_name}/{repo_name}/tree/{revision}", get(tree_read))
197 .route(
198 "/{space_name}/{repo_name}/tree/resolve",
199 get(tree_resolve_path),
200 )
201 .route("/{space_name}/{repo_name}/tree/walk", get(tree_walk))
202 .route("/{space_name}/{repo_name}/tree/follow", get(tree_follow))
203 .route(
204 "/{space_name}/{repo_name}/tree/last-updated",
205 get(tree_last_updated),
206 )
183
207184 .route("/{space_name}/{repo_name}/blame", get(blame_handler))
208185 .route("/{space_name}/{repo_name}/submodules", get(submodules_list))
209186 .route(
@@ -218,42 +195,22 @@
218195 "/{space_name}/{repo_name}/signatures/tag/{name}",
219196 get(verify_tag),
220197 )
198 .route("/{space_name}/{repo_name}/diff", get(get_diff))
221199 .route("/{space_name}/{repo_name}/diff/raw", get(diff_raw))
222200 .route(
223 "/{space_name}/{repo_name}/diff/files",
224 get(files_changed_between),
225 )
226 .route(
227 "/{space_name}/{repo_name}/diff/shortstat",
228 get(diff_short_stat),
229 )
230 .route("/{space_name}/{repo_name}/diff/stats", get(diff_stats))
231 .route(
232201 "/{space_name}/{repo_name}/diff/for-commit/{commit}",
233202 get(diff_for_commit),
234203 )
235 .route("/{space_name}/{repo_name}/diff/tree", get(diff_tree))
236204 .route("/{space_name}/{repo_name}/diff/range", post(range_diff))
237205 .route(
238206 "/{space_name}/{repo_name}/patch/generate",
239207 get(patch_generate),
240208 )
241209 .route("/_/patch/parse", post(patch_parse))
210 .route("/{space_name}/{repo_name}/conflicts", get(get_conflicts))
242211 .route(
243 "/{space_name}/{repo_name}/conflicts/check",
244 get(conflict_check),
245 )
246 .route(
247 "/{space_name}/{repo_name}/conflicts/files",
248 get(conflicted_files),
249 )
250 .route(
251212 "/{space_name}/{repo_name}/conflicts/detail",
252213 get(conflict_detail),
253 )
254 .route(
255 "/{space_name}/{repo_name}/conflicts/check-threeway",
256 post(conflict_check_threeway),
257214 )
258215 .route(
259216 "/{space_name}/{repo_name}/remotes/import",