use chrono::{DateTime, Utc};
use super::entity::*;
pub trait AptRepositoryWriter: Send + Sync + 'static {
fn synchronize(&self) -> impl Future<Output = anyhow::Result<()>> + Send;
}
pub trait AptRepositoryReader: Send + Sync + 'static {
fn list_packages(
&self,
arch: &str,
) -> impl Future<Output = anyhow::Result<Vec<Package>>> + Send;
fn release_metadata(
&self,
) -> impl Future<Output = anyhow::Result<Option<ReleaseMetadata>>> + Send;
fn signed_release_metadata(
&self,
) -> impl Future<Output = anyhow::Result<Option<String>>> + Send;
fn release_gpg_signature(&self) -> impl Future<Output = anyhow::Result<Option<String>>> + Send;
fn packages_file(&self, arch: &str) -> impl Future<Output = anyhow::Result<String>> + Send {
async {
let list = self.list_packages(arch).await?;
Ok(list
.into_iter()
.map(|package| package.serialize().to_string())
.collect::<Vec<_>>()
.join("\n"))
}
}
fn translation_file(&self) -> impl Future<Output = anyhow::Result<String>> + Send;
fn package(
&self,
name: &str,
filename: &str,
) -> impl Future<Output = anyhow::Result<Option<Package>>> + Send;
fn find_architecture_by_hash(
&self,
hash: &str,
) -> impl Future<Output = anyhow::Result<Option<ArchitectureHashMatch>>> + Send;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ArchitectureHashMatch {
pub architecture: String,
pub compressed: bool,
}
#[cfg(test)]
mockall::mock! {
pub AptRepositoryService {}
impl Clone for AptRepositoryService {
fn clone(&self) -> Self;
}
impl AptRepositoryReader for AptRepositoryService {
fn list_packages(
&self,
arch: &str,
) -> impl Future<Output = anyhow::Result<Vec<Package>>> + Send;
fn release_metadata(&self) -> impl Future<Output = anyhow::Result<Option<ReleaseMetadata>>> + Send;
fn signed_release_metadata(&self) -> impl Future<Output = anyhow::Result<Option<String>>> + Send;
fn release_gpg_signature(&self) -> impl Future<Output = anyhow::Result<Option<String>>> + Send;
fn packages_file(&self, arch: &str) -> impl Future<Output = anyhow::Result<String>> + Send;
fn translation_file(&self) -> impl Future<Output = anyhow::Result<String>> + Send;
fn package(
&self,
name: &str,
filename: &str,
) -> impl Future<Output = anyhow::Result<Option<Package>>> + Send;
fn find_architecture_by_hash(
&self,
hash: &str,
) -> impl Future<Output = anyhow::Result<Option<ArchitectureHashMatch>>> + Send;
}
}
pub trait DebMetadataExtractor: Send + Sync + 'static {
fn extract_metadata(
&self,
path: &std::path::Path,
) -> impl Future<Output = anyhow::Result<PackageMetadata>> + Send;
}
#[cfg(test)]
mockall::mock! {
pub DebMetadataExtractor {}
impl Clone for DebMetadataExtractor {
fn clone(&self) -> Self;
}
impl DebMetadataExtractor for DebMetadataExtractor {
fn extract_metadata(
&self,
path: &std::path::Path,
) -> impl Future<Output = anyhow::Result<PackageMetadata>> + Send;
}
}
pub trait PackageSource: Send + Sync + 'static {
fn fetch_deb(
&self,
asset: &DebAsset,
) -> impl Future<Output = anyhow::Result<temp_file::TempFile>> + Send;
fn stream_releases_with_assets(
&self,
repo: &str,
) -> impl Future<Output = anyhow::Result<Vec<ReleaseWithAssets>>> + Send;
}
#[cfg(test)]
mockall::mock! {
pub PackageSource {}
impl Clone for PackageSource {
fn clone(&self) -> Self;
}
impl PackageSource for PackageSource {
fn fetch_deb(
&self,
asset: &DebAsset,
) -> impl Future<Output = anyhow::Result<temp_file::TempFile>> + Send;
fn stream_releases_with_assets(
&self,
repo: &str,
) -> impl Future<Output = anyhow::Result<Vec<ReleaseWithAssets>>> + Send;
}
}
pub trait ReleaseStore: Send + Sync + 'static {
fn insert_release(&self, entry: ReleaseMetadata) -> impl Future<Output = ()> + Send;
fn find_latest_release(&self) -> impl Future<Output = Option<ReleaseMetadata>> + Send;
}
#[cfg(test)]
mockall::mock! {
pub ReleaseStore {}
impl Clone for ReleaseStore {
fn clone(&self) -> Self;
}
impl ReleaseStore for ReleaseStore {
fn insert_release(&self, entry: ReleaseMetadata) -> impl Future<Output = ()> + Send;
fn find_latest_release(&self) -> impl Future<Output = Option<ReleaseMetadata>> + Send;
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ReleaseIdentifier {
pub repo_owner: String,
pub repo_name: String,
pub release_id: u64,
}
pub trait ReleaseTracker: Send + Sync + 'static {
fn filter_scanned_releases(
&self,
releases: &[ReleaseIdentifier],
) -> impl Future<Output = anyhow::Result<std::collections::HashSet<u64>>> + Send;
fn mark_releases_scanned(
&self,
releases: &[ReleaseIdentifier],
) -> impl Future<Output = anyhow::Result<()>> + Send;
}
#[cfg(test)]
mockall::mock! {
pub ReleaseTracker {}
impl Clone for ReleaseTracker {
fn clone(&self) -> Self;
}
impl ReleaseTracker for ReleaseTracker {
fn filter_scanned_releases(
&self,
releases: &[ReleaseIdentifier],
) -> impl Future<Output = anyhow::Result<std::collections::HashSet<u64>>> + Send;
fn mark_releases_scanned(
&self,
releases: &[ReleaseIdentifier],
) -> impl Future<Output = anyhow::Result<()>> + Send;
}
}
pub trait PackageStore: Send + Sync + 'static {
fn insert_packages(
&self,
packages: &[Package],
) -> impl Future<Output = anyhow::Result<()>> + Send;
fn find_package_by_asset_id(
&self,
asset_id: u64,
) -> impl Future<Output = Option<Package>> + Send;
fn list_all_packages(&self) -> impl Future<Output = anyhow::Result<Vec<Package>>> + Send;
}
#[cfg(test)]
mockall::mock! {
pub PackageStore {}
impl Clone for PackageStore {
fn clone(&self) -> Self;
}
impl PackageStore for PackageStore {
fn insert_packages(
&self,
packages: &[Package],
) -> impl Future<Output = anyhow::Result<()>> + Send;
fn find_package_by_asset_id(
&self,
asset_id: u64,
) -> impl Future<Output = Option<Package>> + Send;
fn list_all_packages(&self) -> impl Future<Output = anyhow::Result<Vec<Package>>> + Send;
}
}
pub trait Clock: Send + Sync + 'static {
fn now() -> DateTime<Utc>;
}
impl Clock for chrono::Utc {
fn now() -> DateTime<Utc> {
Utc::now()
}
}
#[cfg(test)]
mockall::mock! {
pub Clock {}
impl Clock for Clock {
fn now() -> chrono::DateTime<chrono::Utc>;
}
}
pub trait PGPCipher: Send + Sync + 'static {
fn sign(&self, data: &str) -> anyhow::Result<String>;
}
#[cfg(test)]
mockall::mock! {
pub PGPCipher {}
impl PGPCipher for PGPCipher {
fn sign(&self, data: &str) -> anyhow::Result<String>;
}
}