89109d2
use std::path::PathBuf;
use axum::extract::{Path, Query, State};
use export::rest::AppResponseData;
use jwt::Session;
use serde::Deserialize;
use crate::errors::{ApiError, GitApiError};
use crate::handler::resolve_reader;
use crate::service::GitService;
use crate::share::errors::GitError;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, utoipa::ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum TreeView {
Entries,
LastUpdated,
}
#[derive(Debug, Clone, Deserialize, utoipa::IntoParams)]
pub struct GetTreeQuery {
#[serde(default)]
pub path: String,
#[serde(default)]
pub recurse: bool,
#[serde(default)]
pub resolve: bool,
#[serde(default)]
pub show_trees: bool,
#[serde(default)]
pub view: Option<TreeView>,
}
#[utoipa::path(
get,
path = "/repos/{space_name}/{repo_name}/tree/{revision}",
tag = "trees",
description = "读取修订下的目录树,并支持递归、符号链接解析和更新时间视图。",
params(
crate::handler::RepoPathRev,
GetTreeQuery,
),
responses(
(status = 200, description = "tree payload: entries list, single entry (resolve), or last-updated list (view=last_updated)", body = AppResponseData<serde_json::Value>)
)
)]
pub async fn get_tree(
State(service): State<GitService>,
session: Session,
Path(path): Path<crate::handler::RepoPathRev>,
Query(q): Query<GetTreeQuery>,
) -> Result<AppResponseData<serde_json::Value>, ApiError> {
let _ = resolve_reader(
&service,
&session,
path.space_name.clone(),
path.repo_name.clone(),
)
.await?;
let out = match q.view {
Some(TreeView::LastUpdated) => {
let p = (!q.path.is_empty()).then(|| q.path.clone());
let rows = service
.tree_last_updated(path.space_name, path.repo_name, path.revision, p)
.await
.map_err(GitApiError::from)?;
serde_json::to_value(rows).map_err(json_err)?
}
_ => {
if q.resolve && !q.path.is_empty() {
let (entry, target, resolved) = service
.tree_follow(path.space_name, path.repo_name, path.revision, q.path)
.await
.map_err(GitApiError::from)?;
serde_json::json!({
"entry": entry,
"symlink_target": target,
"resolved": resolved,
})
} else if q.recurse {
let entries = service
.tree_walk(
path.space_name,
path.repo_name,
path.revision,
true,
q.show_trees,
)
.await
.map_err(GitApiError::from)?;
serde_json::to_value(entries).map_err(json_err)?
} else {
let entries = service
.tree_read(
path.space_name,
path.repo_name,
path.revision,
PathBuf::from(&q.path),
)
.await
.map_err(GitApiError::from)?;
serde_json::to_value(entries).map_err(json_err)?
}
}
};
Ok(AppResponseData::ok(out))
}
fn json_err(e: serde_json::Error) -> ApiError {
GitApiError::from(GitError::Internal(e.to_string())).into()
}