Skip to content
Clone
d6dc02f
147 lines 4.9 KB Rust
pub use crate::context::facade::GitContext;
pub use crate::handler::RepoPath;
pub use crate::service::GitService;
pub use crate::service::commits::{CommitStatusDto, CommitStatusDtoState};
pub use crate::service::diffs::{ChangedPathDiffDto, DiffOptionsDto};
pub use crate::service::merge::{ExecuteMergeCmd, MergeCommitDto, MergePlanDto, MergeResultDto};
pub use crate::share::access::authorize_repo_access;
pub use crate::share::errors::GitError;
use models::repo::repos;
use sea_orm::{ActiveModelTrait, ConnectionTrait, EntityTrait, QuerySelect, Set};
use uuid::Uuid;
pub struct RepositoryInfo {
pub lower_name: String,
pub is_private: bool,
}
impl GitService {
pub async fn repository(&self, id: Uuid) -> Result<Option<RepositoryInfo>, GitError> {
let Some(repo) = repos::Entity::find_by_id(id)
.one(self.database.read())
.await?
else {
return Ok(None);
};
Ok(Some(RepositoryInfo {
lower_name: repo.lower_name,
is_private: repo.is_private,
}))
}
pub async fn repository_visible_from_space(
&self,
id: Uuid,
space_id: Uuid,
) -> Result<bool, GitError> {
let Some(repo) = repos::Entity::find_by_id(id)
.one(self.database.read())
.await?
else {
return Ok(false);
};
if !repo.is_private {
return Ok(true);
}
Ok(self
.access
.for_dir(repo.dir_id)
.await?
.is_some_and(|space| space.id() == space_id))
}
pub async fn merge_requirements(
&self,
repository: Uuid,
branch: &str,
caller: i64,
) -> Result<Option<MergeRequirements>, GitError> {
let policies =
crate::share::policy::match_branch_policies(self.database.read(), repository, branch)
.await?;
if policies.is_empty() {
return Ok(None);
}
let whitelists =
crate::share::policy::branch_policy_whitelists(self.database.read(), &policies).await?;
Ok(Some(MergeRequirements {
required_approvals: policies
.iter()
.map(|policy| policy.required_approvals)
.max()
.unwrap_or(0),
dismiss_stale_approvals: policies.iter().any(|policy| policy.dismiss_stale_approvals),
whitelist_bypass: policies.iter().any(|policy| policy.enable_merge_whitelist)
&& whitelists.merge_allowed.contains(&caller),
block_on_rejected_reviews: policies
.iter()
.any(|policy| policy.block_on_rejected_reviews),
block_on_change_requested_reviews: policies
.iter()
.any(|policy| policy.block_on_change_requested_reviews),
block_on_outdated_branch: policies
.iter()
.any(|policy| policy.block_on_outdated_branch),
require_signed_commits: policies.iter().any(|policy| policy.require_signed_commits),
required_status_contexts: policies
.iter()
.flat_map(|policy| {
policy
.required_status_contexts
.split(['\n', ','])
.map(str::trim)
.filter(|value| !value.is_empty())
.map(str::to_owned)
})
.collect(),
protected_file_patterns: policies
.iter()
.map(|policy| policy.protected_file_patterns.as_str())
.collect::<Vec<_>>()
.join(","),
unprotected_file_patterns: policies
.iter()
.map(|policy| policy.unprotected_file_patterns.as_str())
.collect::<Vec<_>>()
.join(","),
}))
}
pub async fn lock_repository(
&self,
tx: &impl ConnectionTrait,
id: Uuid,
) -> Result<(), GitError> {
repos::Entity::find_by_id(id)
.lock_exclusive()
.one(tx)
.await?
.ok_or(GitError::NotFound)?;
Ok(())
}
pub async fn set_pull_count(&self, id: Uuid, count: i32) -> Result<(), GitError> {
repos::ActiveModel {
id: Set(id),
nums_pr: Set(count),
..Default::default()
}
.update(self.database.write())
.await?;
Ok(())
}
}
pub struct MergeRequirements {
pub required_approvals: i32,
pub dismiss_stale_approvals: bool,
pub whitelist_bypass: bool,
pub block_on_rejected_reviews: bool,
pub block_on_change_requested_reviews: bool,
pub block_on_outdated_branch: bool,
pub require_signed_commits: bool,
pub required_status_contexts: Vec<String>,
pub protected_file_patterns: String,
pub unprotected_file_patterns: String,
}