use std::{net::SocketAddr, path::PathBuf, sync::Arc}; use cache::AppCache; use db::database::AppDatabase; use tonic::transport::Server; use uuid::Uuid; use crate::rpc::{ archive::ArchiveServiceImpl, blame::BlameServiceImpl, blob::BlobServiceImpl, branch::BranchServiceImpl, commit::CommitServiceImpl, diff::DiffServiceImpl, fork::ForkServiceImpl, init::InitServiceImpl, merge::MergeServiceImpl, proto::{ archive_service_server::ArchiveServiceServer, blame_service_server::BlameServiceServer, blob_service_server::BlobServiceServer, branch_service_server::BranchServiceServer, commit_service_server::CommitServiceServer, diff_service_server::DiffServiceServer, fork_service_server::ForkServiceServer, init_service_server::InitServiceServer, merge_service_server::MergeServiceServer, tag_service_server::TagServiceServer, tree_service_server::TreeServiceServer, }, registry::{RepoRegistry, shared_registry}, tag::TagServiceImpl, tree::TreeServiceImpl, }; use crate::sync::ReceiveSyncService; type RepoId = Uuid; pub struct GitServer { addr: SocketAddr, pub registry: Arc, pub cache: AppCache, pub sync: ReceiveSyncService, } impl GitServer { pub fn new( addr: SocketAddr, db: AppDatabase, cache: AppCache, sync: ReceiveSyncService, ) -> Self { Self { addr, cache: cache.clone(), registry: shared_registry(db, cache), sync, } } pub fn register_repo(&self, repo_id: Uuid, bare_dir: PathBuf) { self.registry.register(repo_id, bare_dir); } pub async fn serve(self) -> Result<(), Box> { let archive = ArchiveServiceServer::new(ArchiveServiceImpl { registry: self.registry.clone(), }); let blame = BlameServiceServer::new(BlameServiceImpl { registry: self.registry.clone(), cache: self.cache.clone(), }); let blob = BlobServiceServer::new(BlobServiceImpl { registry: self.registry.clone(), cache: self.cache.clone(), }); let branch = BranchServiceServer::new(BranchServiceImpl { registry: self.registry.clone(), }); let commit = CommitServiceServer::new(CommitServiceImpl { registry: self.registry.clone(), cache: self.cache.clone(), sync: self.sync.clone(), }); let diff = DiffServiceServer::new(DiffServiceImpl { registry: self.registry.clone(), cache: self.cache.clone(), }); let fork = ForkServiceServer::new(ForkServiceImpl { registry: self.registry.clone(), }); let init = InitServiceServer::new(InitServiceImpl { registry: self.registry.clone(), sync: self.sync.clone(), }); let merge = MergeServiceServer::new(MergeServiceImpl { registry: self.registry.clone(), }); let tag = TagServiceServer::new(TagServiceImpl { registry: self.registry.clone(), }); let tree = TreeServiceServer::new(TreeServiceImpl { registry: self.registry.clone(), cache: self.cache.clone(), }); Server::builder() .max_frame_size(Some(16 * 1024 * 1024 - 1)) .add_service(archive) .add_service(blame) .add_service(blob) .add_service(branch) .add_service(commit) .add_service(diff) .add_service(fork) .add_service(init) .add_service(merge) .add_service(tag) .add_service(tree) .serve(self.addr) .await?; Ok(()) } } pub struct GitServerBuilder { addr: SocketAddr, db: AppDatabase, cache: AppCache, sync: ReceiveSyncService, repos: Vec<(RepoId, PathBuf)>, } impl GitServerBuilder { pub fn new( addr: SocketAddr, db: AppDatabase, cache: AppCache, sync: ReceiveSyncService, ) -> Self { Self { addr, db, cache, sync, repos: Vec::new(), } } pub fn repo( mut self, repo_id: RepoId, bare_dir: impl Into, ) -> Self { self.repos.push((repo_id, bare_dir.into())); self } pub fn build(self) -> GitServer { let server = GitServer::new(self.addr, self.db, self.cache, self.sync); for (repo_id, bare_dir) in self.repos { server.register_repo(repo_id, bare_dir); } server } }