89109d2
use serde::{Deserialize, Serialize};
use crate::service::GitService;
use crate::service::cache::{self, IMMUTABLE_TTL};
use crate::share::errors::{GitError, map_baby};
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct PatchDto {
pub content: String,
pub size: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct ParsedPatchDto {
pub files: Vec<String>,
pub additions: i64,
pub deletions: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct AppliedPatchDto {
pub applied: bool,
pub conflicts: Vec<String>,
}
impl GitService {
pub async fn patch_generate(
&self,
space_name: String,
repo_name: String,
base: String,
head: String,
) -> Result<PatchDto, GitError> {
let ctx = self.context(space_name, repo_name).await?;
let baby = self.baby(&ctx);
let left = baby.rev_parse(&base).await.map_err(map_baby)?;
let right = baby.rev_parse(&head).await.map_err(map_baby)?;
let key = format!("repo.{}.patch_generate.{}.{}", ctx.model.id, left, right);
cache::cached_fetch(&ctx.cache, &key, IMMUTABLE_TTL, || async {
let body = baby
.raw_diff(
&crate::rpcgit::diff::types::DiffRequest { left, right },
None,
)
.await
.map_err(map_baby)?;
let size = body.len() as i64;
Ok(PatchDto {
content: body,
size,
})
})
.await
}
pub async fn patch_parse(&self, content: String) -> Result<ParsedPatchDto, GitError> {
let mut files: Vec<String> = Vec::new();
let mut additions = 0i64;
let mut deletions = 0i64;
for line in content.lines() {
if let Some(rest) = line.strip_prefix("+++ b/") {
if rest != "/dev/null" {
files.push(rest.to_string());
}
} else if let Some(rest) = line.strip_prefix("--- a/") {
if rest == "/dev/null" && !files.iter().any(|f| f == "unknown") {
files.push("unknown".to_string());
}
} else if line.starts_with("+") && !line.starts_with("+++") {
additions += 1;
} else if line.starts_with("-") && !line.starts_with("---") {
deletions += 1;
}
}
files.sort();
files.dedup();
Ok(ParsedPatchDto {
files,
additions,
deletions,
})
}
pub async fn patch_apply(
&self,
_space_name: String,
_repo_name: String,
_patch: String,
_base: String,
) -> Result<AppliedPatchDto, GitError> {
Err(GitError::Unimplemented(
"applying patches requires a KenShell PatchService",
))
}
}