143 lines
4.1 KiB
Rust
143 lines
4.1 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use session::Session;
|
|
use utoipa::ToSchema;
|
|
|
|
use crate::{AppService, error::AppError};
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
|
pub struct ReadmeDto {
|
|
pub content: String,
|
|
pub html: String,
|
|
}
|
|
|
|
impl AppService {
|
|
pub async fn git_repo_readme(
|
|
&self,
|
|
ctx: &Session,
|
|
wk_name: &str,
|
|
repo_name: &str,
|
|
) -> Result<Option<ReadmeDto>, AppError> {
|
|
let repo = self.git_require_member(ctx, wk_name, repo_name).await?;
|
|
|
|
let readme_names = [
|
|
"README.md",
|
|
"README.markdown",
|
|
"README.txt",
|
|
"README",
|
|
"Readme.md",
|
|
"readme.md",
|
|
];
|
|
|
|
for name in &readme_names {
|
|
match self
|
|
.git_tree_entry_by_path_from_commit_for_readme(&repo.id, name)
|
|
.await?
|
|
{
|
|
Some((content, oid)) => {
|
|
return self
|
|
.git_blob_load_for_readme(&repo, &content, &oid)
|
|
.await;
|
|
}
|
|
None => continue,
|
|
}
|
|
}
|
|
|
|
Ok(None)
|
|
}
|
|
}
|
|
impl AppService {
|
|
async fn git_tree_entry_by_path_from_commit_for_readme(
|
|
&self,
|
|
repo_id: &uuid::Uuid,
|
|
readme_name: &str,
|
|
) -> Result<Option<(String, String)>, AppError> {
|
|
use crate::git::rpc_err;
|
|
use git::rpc::proto as p;
|
|
use git::rpc::proto::tree_service_client::TreeServiceClient;
|
|
|
|
let mut client = TreeServiceClient::new(self.git.clone());
|
|
let mut commit_client =
|
|
git::rpc::proto::commit_service_client::CommitServiceClient::new(
|
|
self.git.clone(),
|
|
);
|
|
let summary_resp = commit_client
|
|
.commit_summary(tonic::Request::new(p::CommitSummaryRequest {
|
|
repo_id: repo_id.to_string(),
|
|
}))
|
|
.await
|
|
.map_err(rpc_err)?
|
|
.into_inner();
|
|
|
|
let head_commit = match summary_resp.summary.and_then(|s| s.head) {
|
|
Some(c) => c,
|
|
None => return Ok(None),
|
|
};
|
|
|
|
let tree_id = match head_commit.tree_id {
|
|
Some(id) => id.value,
|
|
None => return Ok(None),
|
|
};
|
|
|
|
let resp = client
|
|
.tree_entry_by_path(tonic::Request::new(
|
|
p::TreeEntryByPathRequest {
|
|
repo_id: repo_id.to_string(),
|
|
tree_oid: Some(p::ObjectId {
|
|
value: tree_id.clone(),
|
|
}),
|
|
path: readme_name.to_string(),
|
|
},
|
|
))
|
|
.await
|
|
.map_err(rpc_err)?
|
|
.into_inner();
|
|
|
|
match resp.entry {
|
|
Some(entry) => {
|
|
let oid = entry.oid.map(|o| o.value).unwrap_or_default();
|
|
if oid.is_empty() {
|
|
Ok(None)
|
|
} else {
|
|
Ok(Some((readme_name.to_string(), oid)))
|
|
}
|
|
}
|
|
None => Ok(None),
|
|
}
|
|
}
|
|
async fn git_blob_load_for_readme(
|
|
&self,
|
|
repo: &model::repos::RepoModel,
|
|
_path: &str,
|
|
oid: &str,
|
|
) -> Result<Option<super::readme::ReadmeDto>, AppError> {
|
|
use crate::git::rpc_err;
|
|
use git::rpc::proto as p;
|
|
use git::rpc::proto::blob_service_client::BlobServiceClient;
|
|
|
|
let mut client = BlobServiceClient::new(self.git.clone());
|
|
let resp = client
|
|
.blob_load(tonic::Request::new(p::BlobLoadRequest {
|
|
repo_id: repo.id.to_string(),
|
|
id: Some(p::ObjectId {
|
|
value: oid.to_string(),
|
|
}),
|
|
path: String::new(),
|
|
}))
|
|
.await
|
|
.map_err(rpc_err)?
|
|
.into_inner();
|
|
|
|
let content = String::from_utf8_lossy(&resp.blob).to_string();
|
|
if content.is_empty() {
|
|
return Ok(None);
|
|
}
|
|
|
|
let html = comrak::markdown_to_html(
|
|
&content,
|
|
&comrak::ComrakOptions::default(),
|
|
);
|
|
|
|
Ok(Some(super::readme::ReadmeDto { content, html }))
|
|
}
|
|
}
|