181 lines
6.6 KiB
Rust
181 lines
6.6 KiB
Rust
use std::sync::Arc;
|
|
|
|
use cache::AppCache;
|
|
use tokio_stream::wrappers::ReceiverStream;
|
|
use tonic::{Request, Response, Status};
|
|
|
|
use crate::rpc::{
|
|
error::{spawn_blocking_error, to_status},
|
|
proto as p,
|
|
registry::RepoRegistry,
|
|
};
|
|
|
|
pub struct DiffServiceImpl {
|
|
pub registry: Arc<RepoRegistry>,
|
|
pub cache: AppCache,
|
|
}
|
|
|
|
type DiffStream = ReceiverStream<Result<p::DiffDelta, Status>>;
|
|
|
|
#[tonic::async_trait]
|
|
impl p::diff_service_server::DiffService for DiffServiceImpl {
|
|
async fn diff_stats(
|
|
&self,
|
|
req: Request<p::DiffStatsRequest>,
|
|
) -> Result<Response<p::DiffStatsResponse>, Status> {
|
|
let inner = req.into_inner();
|
|
let repo_id = inner.repo_id.clone();
|
|
let old_str = inner.old_oid.clone().map(|o| o.value).unwrap_or_default();
|
|
let new_str = inner.new_oid.clone().map(|o| o.value).unwrap_or_default();
|
|
let cache_key = format!("git:rpc:cache:diff:stats:{}:{}:{}", repo_id, old_str, new_str);
|
|
|
|
if let Ok(Some(cached)) = self.cache.get::<p::DiffStatsResponse>(&cache_key).await {
|
|
return Ok(Response::new(cached));
|
|
}
|
|
|
|
let bare = self.registry.get(&repo_id).await?;
|
|
let old: crate::cmd::oid::ObjectId =
|
|
inner.old_oid.unwrap_or_default().into();
|
|
let new: crate::cmd::oid::ObjectId =
|
|
inner.new_oid.unwrap_or_default().into();
|
|
let opts = inner.options.map(Into::into);
|
|
let stats = tokio::task::spawn_blocking(move || {
|
|
bare.diff_stats(old, new, opts)
|
|
})
|
|
.await
|
|
.map_err(spawn_blocking_error)?
|
|
.map_err(to_status)?;
|
|
let result = crate::cmd::diff::DiffResult { stats, deltas: vec![] };
|
|
let resp = p::DiffStatsResponse { result: Some(result.into()) };
|
|
let _ = self.cache.set(&cache_key, &resp).await;
|
|
Ok(Response::new(resp))
|
|
}
|
|
|
|
async fn diff_patch(
|
|
&self,
|
|
req: Request<p::DiffPatchRequest>,
|
|
) -> Result<Response<p::DiffPatchResponse>, Status> {
|
|
let inner = req.into_inner();
|
|
let repo_id = inner.repo_id.clone();
|
|
let old_str = inner.old_oid.clone().map(|o| o.value).unwrap_or_default();
|
|
let new_str = inner.new_oid.clone().map(|o| o.value).unwrap_or_default();
|
|
let cache_key = format!("git:rpc:cache:diff:patch:{}:{}:{}", repo_id, old_str, new_str);
|
|
|
|
if let Ok(Some(cached)) = self.cache.get::<p::DiffPatchResponse>(&cache_key).await {
|
|
return Ok(Response::new(cached));
|
|
}
|
|
|
|
let bare = self.registry.get(&repo_id).await?;
|
|
let old: crate::cmd::oid::ObjectId =
|
|
inner.old_oid.unwrap_or_default().into();
|
|
let new: crate::cmd::oid::ObjectId =
|
|
inner.new_oid.unwrap_or_default().into();
|
|
let opts = inner.options.map(Into::into);
|
|
let result = tokio::task::spawn_blocking(move || {
|
|
bare.diff_patch(old, new, opts)
|
|
})
|
|
.await
|
|
.map_err(spawn_blocking_error)?
|
|
.map_err(to_status)?;
|
|
let resp = p::DiffPatchResponse { result: Some(result.into()) };
|
|
let _ = self.cache.set(&cache_key, &resp).await;
|
|
Ok(Response::new(resp))
|
|
}
|
|
|
|
type DiffStreamStream = DiffStream;
|
|
|
|
async fn diff_stream(
|
|
&self,
|
|
req: Request<p::DiffPatchRequest>,
|
|
) -> Result<Response<DiffStream>, Status> {
|
|
let inner = req.into_inner();
|
|
let bare = self.registry.get(&inner.repo_id).await?;
|
|
let old: crate::cmd::oid::ObjectId =
|
|
inner.old_oid.unwrap_or_default().into();
|
|
let new: crate::cmd::oid::ObjectId =
|
|
inner.new_oid.unwrap_or_default().into();
|
|
let opts = inner.options.map(Into::into);
|
|
let (tx, rx) = tokio::sync::mpsc::channel(128);
|
|
tokio::task::spawn_blocking(move || {
|
|
let result = bare.diff_patch(old, new, opts);
|
|
match result {
|
|
Ok(diff_result) => {
|
|
for delta in diff_result.deltas {
|
|
if tx.blocking_send(Ok(delta.into())).is_err() {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
let _ = tx.blocking_send(Err(to_status(e)));
|
|
}
|
|
}
|
|
});
|
|
Ok(Response::new(ReceiverStream::new(rx)))
|
|
}
|
|
|
|
async fn diff_patch_side_by_side(
|
|
&self,
|
|
req: Request<p::DiffPatchSideBySideRequest>,
|
|
) -> Result<Response<p::DiffPatchSideBySideResponse>, Status> {
|
|
let inner = req.into_inner();
|
|
let bare = self.registry.get(&inner.repo_id).await?;
|
|
let old: crate::cmd::oid::ObjectId =
|
|
inner.old_oid.unwrap_or_default().into();
|
|
let new: crate::cmd::oid::ObjectId =
|
|
inner.new_oid.unwrap_or_default().into();
|
|
let opts = inner.options.map(Into::into);
|
|
let result = tokio::task::spawn_blocking(move || {
|
|
bare.diff_patch_side_by_side(old, new, opts)
|
|
})
|
|
.await
|
|
.map_err(spawn_blocking_error)?
|
|
.map_err(to_status)?;
|
|
Ok(Response::new(p::DiffPatchSideBySideResponse {
|
|
result: Some(result.into()),
|
|
}))
|
|
}
|
|
|
|
async fn diff_tree_to_tree(
|
|
&self,
|
|
req: Request<p::DiffTreeToTreeRequest>,
|
|
) -> Result<Response<p::DiffTreeToTreeResponse>, Status> {
|
|
let inner = req.into_inner();
|
|
let bare = self.registry.get(&inner.repo_id).await?;
|
|
let old_tree: crate::cmd::oid::ObjectId =
|
|
inner.old_tree.unwrap_or_default().into();
|
|
let new_tree: crate::cmd::oid::ObjectId =
|
|
inner.new_tree.unwrap_or_default().into();
|
|
let options = inner.options.map(Into::into);
|
|
let result = tokio::task::spawn_blocking(move || {
|
|
bare.diff_tree_to_tree(old_tree, new_tree, options)
|
|
})
|
|
.await
|
|
.map_err(spawn_blocking_error)?
|
|
.map_err(to_status)?;
|
|
Ok(Response::new(p::DiffTreeToTreeResponse {
|
|
result: Some(result.into()),
|
|
}))
|
|
}
|
|
|
|
async fn diff_index_to_tree(
|
|
&self,
|
|
req: Request<p::DiffIndexToTreeRequest>,
|
|
) -> Result<Response<p::DiffIndexToTreeResponse>, Status> {
|
|
let inner = req.into_inner();
|
|
let bare = self.registry.get(&inner.repo_id).await?;
|
|
let tree_oid: crate::cmd::oid::ObjectId =
|
|
inner.tree_oid.unwrap_or_default().into();
|
|
let options = inner.options.map(Into::into);
|
|
let result = tokio::task::spawn_blocking(move || {
|
|
bare.diff_index_to_tree(tree_oid, options)
|
|
})
|
|
.await
|
|
.map_err(spawn_blocking_error)?
|
|
.map_err(to_status)?;
|
|
Ok(Response::new(p::DiffIndexToTreeResponse {
|
|
result: Some(result.into()),
|
|
}))
|
|
}
|
|
}
|