use gunnar_proto::repos_server::Repos;
use gunnar_proto::{CreateRepoRequest, GetRepoRequest, HashKind, Repo, RepoPath, SetDefaultBranchRequest, SetVisibilityRequest, Visibility};
use tonic::{Request, Status};
use crate::auth::Caller;
use crate::service::{ReposService, ServiceContext};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RepoSetting {
Show,
Visibility(bool),
DefaultBranch(String),
Create(bool),
}
pub async fn ask(
ctx: &ServiceContext,
principal: &str,
fingerprint: &str,
namespace: &str,
repo: &str,
setting: RepoSetting,
) -> Result<Repo, Status> {
let caller = Caller {
principal_id: principal.to_owned(),
fingerprint: fingerprint.to_owned(),
machine: false,
authenticated: true,
};
fn as_caller<T>(caller: &Caller, message: T) -> Request<T> {
let mut request = Request::new(message);
request.extensions_mut().insert(caller.clone());
request
}
let path = Some(RepoPath { namespace: namespace.to_owned(), repo: repo.to_owned() });
let service = ReposService::new(ctx.clone());
let repo = match setting {
RepoSetting::Show => service.get(as_caller(&caller, GetRepoRequest { path })).await?.into_inner().repo,
RepoSetting::Visibility(public) => {
let visibility = if public { Visibility::Public } else { Visibility::Private } as i32;
service
.set_visibility(as_caller(&caller, SetVisibilityRequest { path, visibility }))
.await?
.into_inner()
.repo
}
RepoSetting::Create(sha256) => {
let hash_kind = if sha256 { HashKind::Sha256 } else { HashKind::Sha1 } as i32;
service
.create(as_caller(&caller, CreateRepoRequest { path, hash_kind, ..Default::default() }))
.await?
.into_inner()
.repo
}
RepoSetting::DefaultBranch(default_branch) => {
service
.set_default_branch(as_caller(&caller, SetDefaultBranchRequest { path, default_branch }))
.await?
.into_inner()
.repo
}
};
repo.ok_or_else(|| Status::internal("the repository service answered with no repository"))
}
pub fn render(repo: &Repo) -> String {
let path = repo.path.as_ref().map(|p| format!("{}/{}", p.namespace, p.repo)).unwrap_or_default();
let visibility = if repo.visibility == Visibility::Public as i32 { "public" } else { "private" };
let format = if repo.hash_kind == HashKind::Sha256 as i32 { "sha256" } else { "sha1" };
format!(
"repository {path}\nvisibility {visibility}\ndefault-branch {}\nencrypted {}\nobject-format {format}\n",
repo.default_branch,
if repo.encrypted { "yes" } else { "no" }
)
}