use crate::db::*; use sea_orm::{sea_query::IntoCondition, *}; use serde::Deserialize; #[derive(Deserialize)] pub struct Filter { repo: Option, arch: Option, name: Option, } impl IntoCondition for Filter { fn into_condition(self) -> Condition { Condition::all() .add_option(self.repo.map(|repo| package::Column::RepoId.eq(repo))) .add_option(self.arch.map(|arch| package::Column::Arch.eq(arch))) .add_option( self.name .map(|name| package::Column::Name.like(format!("%{}%", name))), ) } } pub async fn page( conn: &DbConn, per_page: u64, page: u64, filter: Filter, ) -> super::Result<(u64, Vec)> { let paginator = Package::find() .filter(filter) .order_by_asc(package::Column::Id) .paginate(conn, per_page); let packages = paginator.fetch_page(page).await?; let total_pages = paginator.num_pages().await?; Ok((total_pages, packages)) } pub async fn by_id(conn: &DbConn, id: i32) -> Result> { package::Entity::find_by_id(id).one(conn).await } pub async fn by_fields( conn: &DbConn, repo_id: i32, arch: &str, name: &str, version: Option<&str>, compression: Option<&str>, ) -> Result> { let mut query = Package::find() .filter(package::Column::RepoId.eq(repo_id)) .filter(package::Column::Name.eq(name)) .filter(package::Column::Arch.eq(arch)); if let Some(version) = version { query = query.filter(package::Column::Version.eq(version)); } if let Some(compression) = compression { query = query.filter(package::Column::Compression.eq(compression)); } query.one(conn).await } pub async fn delete_with_arch(conn: &DbConn, repo_id: i32, arch: &str) -> Result { Package::delete_many() .filter(package::Column::RepoId.eq(repo_id)) .filter(package::Column::Arch.eq(arch)) .exec(conn) .await } pub async fn insert(conn: &DbConn, repo_id: i32, pkg: crate::repo::package::Package) -> Result<()> { let info = pkg.info; let model = package::ActiveModel { id: NotSet, repo_id: Set(repo_id), base: Set(info.base), name: Set(info.name), version: Set(info.version), arch: Set(info.arch), size: Set(info.size), c_size: Set(info.csize), description: Set(info.description), url: Set(info.url), build_date: Set(info.build_date), packager: Set(info.packager), pgp_sig: Set(info.pgpsig), pgp_sig_size: Set(info.pgpsigsize), sha256_sum: Set(info.sha256sum), compression: Set(pkg.compression.extension().unwrap().to_string()), }; let pkg_entry = model.insert(conn).await?; // Insert all the related tables PackageLicense::insert_many(info.licenses.iter().map(|s| package_license::ActiveModel { package_id: Set(pkg_entry.id), name: Set(s.to_string()), })) .on_empty_do_nothing() .exec(conn) .await?; PackageGroup::insert_many(info.groups.iter().map(|s| package_group::ActiveModel { package_id: Set(pkg_entry.id), name: Set(s.to_string()), })) .on_empty_do_nothing() .exec(conn) .await?; let related = info .conflicts .iter() .map(|s| (PackageRelatedEnum::Conflicts, s)) .chain( info.replaces .iter() .map(|s| (PackageRelatedEnum::Replaces, s)), ) .chain( info.provides .iter() .map(|s| (PackageRelatedEnum::Provides, s)), ) .chain(info.depends.iter().map(|s| (PackageRelatedEnum::Depend, s))) .chain( info.makedepends .iter() .map(|s| (PackageRelatedEnum::Depend, s)), ) .chain( info.checkdepends .iter() .map(|s| (PackageRelatedEnum::Checkdepend, s)), ) .chain( info.optdepends .iter() .map(|s| (PackageRelatedEnum::Optdepend, s)), ); PackageRelated::insert_many(related.map(|(t, s)| package_related::ActiveModel { package_id: Set(pkg_entry.id), r#type: Set(t), name: Set(s.to_string()), })) .on_empty_do_nothing() .exec(conn) .await?; PackageFile::insert_many(pkg.files.iter().map(|s| package_file::ActiveModel { package_id: Set(pkg_entry.id), path: Set(s.display().to_string()), })) .on_empty_do_nothing() .exec(conn) .await?; Ok(()) } pub async fn full(conn: &DbConn, id: i32) -> Result> { if let Some(entry) = by_id(conn, id).await? { let licenses = entry .find_related(PackageLicense) .all(conn) .await? .into_iter() .map(|e| e.name) .collect(); let groups = entry .find_related(PackageGroup) .all(conn) .await? .into_iter() .map(|e| e.name) .collect(); let related = entry .find_related(PackageRelated) .all(conn) .await? .into_iter() .map(|e| (e.r#type, e.name)) .collect(); let files = entry .find_related(PackageFile) .all(conn) .await? .into_iter() .map(|e| e.path) .collect(); Ok(Some(FullPackage { entry, licenses, groups, related, files, })) } else { Ok(None) } }