use gunnar_proto::pull_requests_server::PullRequests;
use gunnar_proto::{
event, ClosePullRequestRequest, ClosePullRequestResponse, CreatePullRequestRequest,
CreatePullRequestResponse, GetPullRequestRequest, GetPullRequestResponse,
ListPullRequestsRequest, ListPullRequestsResponse, MergePullRequestRequest,
MergePullRequestResponse, PullRequestClosed, PullRequestMerged, PullRequestOpened, RefUpdated,
};
use tonic::{Request, Response, Status};
use crate::auth::Access;
use crate::service::PullsService;
use crate::status::repo_path;
use gunnar_proto::GrantLevel;
#[tonic::async_trait]
impl PullRequests for PullsService {
async fn create(
&self,
request: Request<CreatePullRequestRequest>,
) -> Result<Response<CreatePullRequestResponse>, Status> {
let caller = self.ctx.caller(&request)?;
let request = request.into_inner();
let path = repo_path(request.repo, "repo")?;
self.ctx.require(
&caller,
Access::repo(&path),
GrantLevel::Write,
"PullRequests.Create",
)?;
let pull = self.ctx.control.create_pull(
&path,
&caller.principal_id,
&request.title,
&request.description,
&request.source_ref,
&request.target_ref,
)?;
self.ctx
.bus
.publish(event::Payload::PullRequestOpened(PullRequestOpened {
repo: Some(path),
number: pull.number,
title: pull.title.clone(),
source_ref: pull.source_ref.clone(),
target_ref: pull.target_ref.clone(),
principal_id: caller.principal_id.clone(),
}));
Ok(Response::new(CreatePullRequestResponse {
pull: Some(pull),
}))
}
async fn list(
&self,
request: Request<ListPullRequestsRequest>,
) -> Result<Response<ListPullRequestsResponse>, Status> {
let caller = self.ctx.caller(&request)?;
let request = request.into_inner();
let path = repo_path(request.repo, "repo")?;
self.ctx.require(
&caller,
Access::repo(&path),
GrantLevel::Read,
"PullRequests.List",
)?;
let pulls = self.ctx.control.list_pulls(&path, request.state)?;
Ok(Response::new(ListPullRequestsResponse { pulls }))
}
async fn get(
&self,
request: Request<GetPullRequestRequest>,
) -> Result<Response<GetPullRequestResponse>, Status> {
let caller = self.ctx.caller(&request)?;
let request = request.into_inner();
let path = repo_path(request.repo, "repo")?;
self.ctx.require(
&caller,
Access::repo(&path),
GrantLevel::Read,
"PullRequests.Get",
)?;
let pull = self.ctx.control.get_pull(&path, request.number)?;
Ok(Response::new(GetPullRequestResponse { pull: Some(pull) }))
}
async fn close(
&self,
request: Request<ClosePullRequestRequest>,
) -> Result<Response<ClosePullRequestResponse>, Status> {
let caller = self.ctx.caller(&request)?;
let request = request.into_inner();
let path = repo_path(request.repo, "repo")?;
self.ctx.require(
&caller,
Access::repo(&path),
GrantLevel::Write,
"PullRequests.Close",
)?;
let pull = self.ctx.control.close_pull(&path, request.number)?;
self.ctx
.bus
.publish(event::Payload::PullRequestClosed(PullRequestClosed {
repo: Some(path),
number: pull.number,
title: pull.title.clone(),
principal_id: caller.principal_id.clone(),
}));
Ok(Response::new(ClosePullRequestResponse { pull: Some(pull) }))
}
async fn merge(
&self,
request: Request<MergePullRequestRequest>,
) -> Result<Response<MergePullRequestResponse>, Status> {
let caller = self.ctx.caller(&request)?;
let request = request.into_inner();
let path = repo_path(request.repo, "repo")?;
self.ctx.require(
&caller,
Access::repo(&path),
GrantLevel::Write,
"PullRequests.Merge",
)?;
let (pull, moved) =
self.ctx
.control
.merge_pull(&path, request.number, &caller.principal_id)?;
self.ctx.bus.publish(event::Payload::RefUpdated(RefUpdated {
repo: Some(path.clone()),
ref_name: moved.ref_name,
old_oid: moved.old_oid,
new_oid: moved.new_oid.clone(),
principal_id: caller.principal_id.clone(),
key_fingerprint: caller.fingerprint.clone(),
credential: format!("key:{}", caller.fingerprint),
forced: false,
}));
self.ctx
.bus
.publish(event::Payload::PullRequestMerged(PullRequestMerged {
repo: Some(path),
number: pull.number,
title: pull.title.clone(),
target_ref: pull.target_ref.clone(),
merge_oid: moved.new_oid,
principal_id: caller.principal_id.clone(),
}));
Ok(Response::new(MergePullRequestResponse { pull: Some(pull) }))
}
}