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" }
)
}