Skip to content
Clone
02d8172
140 lines 3.9 KB Rust
use crate::rpcgit::commit::types::CommitInfo;
use models::pull_request::pull_requests::MergeMethod;
use serde::{Deserialize, Serialize};
use time::OffsetDateTime;
use crate::context::facade::GitContext;
use crate::service::GitService;
use crate::share::errors::{GitError, map_baby};
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct MergePlanDto {
pub base_sha: String,
pub head_sha: String,
pub merge_base: Option<String>,
pub fast_forwardable: bool,
/// base 上 head 没有的提交数。
pub base_only: i64,
/// head 上 base 没有的提交数。
pub head_only: i64,
pub clean: bool,
pub conflicts: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct MergeResultDto {
/// `fast_forward` | `merge_commit` | `squash` | `rebase`
pub method: String,
pub base_ref: String,
pub old_sha: String,
pub new_sha: String,
pub head_sha: String,
/// rebase 时重写出来的提交(按时间正序)。
pub rewritten: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct ExecuteMergeCmd {
pub base_branch: String,
pub head_revision: String,
pub method: MergeMethod,
pub message: Option<String>,
pub caller: i64,
pub allow_ff_only: bool,
pub summary: String,
}
fn hex(oid: &crate::rpcgit::oid::ObjectId) -> String {
oid.to_string()
}
impl GitService {
/// 合并在 KenShell 补齐 MergeService 之前不可用。
pub async fn merge_plan(
&self,
_ctx: &GitContext,
_base: &str,
_head: &str,
) -> Result<MergePlanDto, GitError> {
Err(GitError::Unimplemented(
"merge planning requires KenShell MergeService",
))
}
pub async fn merge_execute(
&self,
_space_name: String,
_repo_name: String,
_cmd: ExecuteMergeCmd,
) -> Result<MergeResultDto, GitError> {
Err(GitError::Unimplemented(
"merge execution requires KenShell MergeService",
))
}
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct MergeCommitDto {
pub sha: String,
pub subject: String,
pub message: String,
pub author_name: String,
pub author_email: String,
pub author_at: OffsetDateTime,
pub parents: Vec<String>,
}
const MAX_LISTED_COMMITS: u32 = 200;
fn commit_dto(info: CommitInfo) -> MergeCommitDto {
MergeCommitDto {
sha: hex(&info.id),
subject: info.message.lines().next().unwrap_or_default().to_string(),
message: info.message.clone(),
author_name: info.author.name.clone(),
author_email: info.author.email.clone(),
author_at: info.author.time,
parents: info.parents.iter().map(hex).collect(),
}
}
impl GitService {
/// `base..head` 的提交列表(正序,最多 200 条)。
pub async fn merge_commits(
&self,
ctx: &GitContext,
base: &str,
head: &str,
) -> Result<Vec<MergeCommitDto>, GitError> {
self.commits_between(ctx, base, head, MAX_LISTED_COMMITS)
.await
}
pub async fn commits_between(
&self,
ctx: &GitContext,
base: &str,
head: &str,
limit: u32,
) -> Result<Vec<MergeCommitDto>, GitError> {
let baby = self.baby(&ctx);
let base_oid = baby.rev_parse(base).await.map_err(map_baby)?;
let head_oid = baby.rev_parse(head).await.map_err(map_baby)?;
let ids = baby
.commit_ids_between_reverse(
&hex(&base_oid),
&hex(&head_oid),
None,
Some(limit.min(MAX_LISTED_COMMITS)),
)
.await
.map_err(map_baby)?;
let mut out = Vec::with_capacity(ids.len());
for id in ids {
out.push(commit_dto(
baby.get_commit(&hex(&id)).await.map_err(map_baby)?,
));
}
Ok(out)
}
}