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;
fn fetch_apk(
&self,
asset: &ApkAsset,
) -> impl Future<Output = anyhow::Result<temp_file::TempFile>> + Send;
fn stream_apk_releases_with_assets(
&self,
repo: &str,
) -> impl Future<Output = anyhow::Result<Vec<ApkReleaseWithAssets>>> + 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;
fn fetch_apk(
&self,
asset: &ApkAsset,
) -> impl Future<Output = anyhow::Result<temp_file::TempFile>> + Send;
fn stream_apk_releases_with_assets(
&self,
repo: &str,
) -> impl Future<Output = anyhow::Result<Vec<ApkReleaseWithAssets>>> + 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>;
}
}
pub trait ApkRepositoryWriter: Send + Sync + 'static {
fn synchronize(&self) -> impl Future<Output = anyhow::Result<()>> + Send;
}
pub trait ApkRepositoryReader: Send + Sync + 'static {
fn apk_index(&self, arch: &str) -> impl Future<Output = anyhow::Result<Vec<u8>>> + Send;
fn apk_package(
&self,
arch: &str,
filename: &str,
) -> impl Future<Output = anyhow::Result<Option<ApkPackage>>> + Send;
}
#[cfg(test)]
mockall::mock! {
pub ApkRepositoryService {}
impl Clone for ApkRepositoryService {
fn clone(&self) -> Self;
}
impl ApkRepositoryReader for ApkRepositoryService {
fn apk_index(&self, arch: &str) -> impl Future<Output = anyhow::Result<Vec<u8>>> + Send;
fn apk_package(
&self,
arch: &str,
filename: &str,
) -> impl Future<Output = anyhow::Result<Option<ApkPackage>>> + Send;
}
}
pub trait ApkMetadataExtractor: Send + Sync + 'static {
fn extract_metadata(
&self,
path: &std::path::Path,
) -> impl Future<Output = anyhow::Result<ApkMetadata>> + Send;
}
#[cfg(test)]
mockall::mock! {
pub ApkMetadataExtractor {}
impl Clone for ApkMetadataExtractor {
fn clone(&self) -> Self;
}
impl ApkMetadataExtractor for ApkMetadataExtractor {
fn extract_metadata(
&self,
path: &std::path::Path,
) -> impl Future<Output = anyhow::Result<ApkMetadata>> + Send;
}
}
pub trait ApkPackageStore: Send + Sync + 'static {
fn insert_apk_packages(
&self,
packages: &[ApkPackage],
) -> impl Future<Output = anyhow::Result<()>> + Send;
fn find_apk_package_by_asset_id(
&self,
asset_id: u64,
) -> impl Future<Output = anyhow::Result<Option<ApkPackage>>> + Send;
fn list_all_apk_packages(&self)
-> impl Future<Output = anyhow::Result<Vec<ApkPackage>>> + Send;
}
#[cfg(test)]
mockall::mock! {
pub ApkPackageStore {}
impl Clone for ApkPackageStore {
fn clone(&self) -> Self;
}
impl ApkPackageStore for ApkPackageStore {
fn insert_apk_packages(
&self,
packages: &[ApkPackage],
) -> impl Future<Output = anyhow::Result<()>> + Send;
fn find_apk_package_by_asset_id(
&self,
asset_id: u64,
) -> impl Future<Output = anyhow::Result<Option<ApkPackage>>> + Send;
fn list_all_apk_packages(
&self,
) -> impl Future<Output = anyhow::Result<Vec<ApkPackage>>> + Send;
}
}
pub trait RsaSigner: Send + Sync + 'static {
fn sign(&self, data: &[u8]) -> anyhow::Result<Vec<u8>>;
fn key_name(&self) -> &str;
}
#[cfg(test)]
mockall::mock! {
pub RsaSigner {}
impl RsaSigner for RsaSigner {
fn sign(&self, data: &[u8]) -> anyhow::Result<Vec<u8>>;
fn key_name(&self) -> &str;
}
}