From 97e8e49b89a4b80181aece02411111371e9909bc Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Wed, 17 Aug 2022 16:55:29 +0900 Subject: [PATCH 1/9] feat(utils): resurrect the `AlpmExt` trait This required fixing `find_local_satisfier` which wasn't compiling. This module had been previously left out of the module tree, so the broken code was never compiled and thus never detected. --- alpm-utils/src/alpm.rs | 20 +++++++++++++------- alpm-utils/src/depends.rs | 8 ++------ alpm-utils/src/lib.rs | 5 +++++ 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/alpm-utils/src/alpm.rs b/alpm-utils/src/alpm.rs index ae3e10a..9b20f75 100644 --- a/alpm-utils/src/alpm.rs +++ b/alpm-utils/src/alpm.rs @@ -1,22 +1,28 @@ use crate::depends::satisfies_ver; +use alpm::{Alpm, Depend, Package, Result}; -use alpm::{Alpm, Result, Package, Depend}; - +/// Extension methods to the [`Alpm`] type. pub trait AlpmExt { - fn find_local_satisfier>(&self, pkg: S) -> Result>; + /// Try to find a [`Package`] that satisfies a given dependency. + fn find_local_satisfier(&self, pkg: S) -> Result> + where + S: Into; } impl AlpmExt for Alpm { - fn find_local_satisfier>(&self, pkg: S) -> Result> { + fn find_local_satisfier(&self, pkg: S) -> Result> + where + S: Into, + { let localdb = self.localdb(); let pkg = pkg.into(); - if let Ok(alpm_pkg) = localdb.pkg(&pkg) { - if satisfies_ver(&Depend::new(&pkg), alpm_pkg.version()) { + if let Ok(alpm_pkg) = localdb.pkg(pkg.as_str()) { + if satisfies_ver(Depend::new(pkg.as_str()), alpm_pkg.version()) { return Ok(Some(alpm_pkg)); } } - return Ok(localdb.pkgs()?.find_satisfier(pkg)); + Ok(localdb.pkgs().find_satisfier(pkg)) } } diff --git a/alpm-utils/src/depends.rs b/alpm-utils/src/depends.rs index 70c734c..c46a886 100644 --- a/alpm-utils/src/depends.rs +++ b/alpm-utils/src/depends.rs @@ -1,11 +1,7 @@ use alpm::{AsDep, DepModVer, Ver}; /// Checks if a dependency is satisfied by a package (name + version). -pub fn satisfies_dep, V: AsRef>( - dep: impl AsDep, - name: S, - version: V, -) -> bool { +pub fn satisfies_dep, V: AsRef>(dep: impl AsDep, name: S, version: V) -> bool { let name = name.as_ref(); let dep = dep.as_dep(); @@ -66,7 +62,7 @@ pub fn satisfies_provide_nover(dep: impl AsDep, provide: impl AsDep) -> bool { dep.as_dep().name() == provide.as_dep().name() } -fn satisfies_ver>(dep: impl AsDep, version: V) -> bool { +pub(crate) fn satisfies_ver>(dep: impl AsDep, version: V) -> bool { let version = version.as_ref(); let dep = dep.as_dep(); diff --git a/alpm-utils/src/lib.rs b/alpm-utils/src/lib.rs index 8576dde..efb9742 100644 --- a/alpm-utils/src/lib.rs +++ b/alpm-utils/src/lib.rs @@ -6,8 +6,11 @@ #[cfg(feature = "conf")] mod conf; + #[cfg(feature = "alpm")] +mod alpm; mod db; + /// Utils for dependency checking. #[cfg(feature = "alpm")] pub mod depends; @@ -15,6 +18,8 @@ mod target; #[cfg(feature = "conf")] pub use crate::conf::*; + #[cfg(feature = "alpm")] +pub use crate::alpm::*; pub use crate::db::*; pub use crate::target::*; From b7e35e1a7a3975fd26913879ee28a33ecca511c7 Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Wed, 17 Aug 2022 16:59:33 +0900 Subject: [PATCH 2/9] feat(utils): upstream a few common functions --- alpm-utils/src/alpm.rs | 48 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/alpm-utils/src/alpm.rs b/alpm-utils/src/alpm.rs index 9b20f75..ca78f3a 100644 --- a/alpm-utils/src/alpm.rs +++ b/alpm-utils/src/alpm.rs @@ -1,16 +1,18 @@ use crate::depends::satisfies_ver; -use alpm::{Alpm, Depend, Package, Result}; +use crate::DbListExt; +use alpm::{Alpm, Depend, Package, PackageReason, Result, SigLevel}; +use std::path::Path; /// Extension methods to the [`Alpm`] type. pub trait AlpmExt { /// Try to find a [`Package`] that satisfies a given dependency. - fn find_local_satisfier(&self, pkg: S) -> Result> + fn find_local_satisfier(&self, pkg: S) -> Result>> where S: Into; } impl AlpmExt for Alpm { - fn find_local_satisfier(&self, pkg: S) -> Result> + fn find_local_satisfier(&self, pkg: S) -> Result>> where S: Into, { @@ -26,3 +28,43 @@ impl AlpmExt for Alpm { Ok(localdb.pkgs().find_satisfier(pkg)) } } + +/// All orphaned packages. +/// +/// An orphan is a package that was installed as a dependency, but whose parent +/// package is no longer installed. +pub fn orphans(alpm: &Alpm) -> impl Iterator> { + alpm.localdb().pkgs().into_iter().filter(|p| { + p.reason() == PackageReason::Depend + && p.required_by().is_empty() + && p.optional_for().is_empty() + }) +} + +/// All official packages. +pub fn officials(alpm: &Alpm) -> impl Iterator> { + let syncs = alpm.syncdbs(); + + alpm.localdb() + .pkgs() + .into_iter() + .filter_map(move |p| syncs.pkg(p.name()).ok()) +} + +/// All foreign packages as an `Iterator`. +pub fn foreigns(alpm: &Alpm) -> impl Iterator> { + let syncs = alpm.syncdbs(); + + alpm.localdb() + .pkgs() + .into_iter() + .filter(move |p| syncs.pkg(p.name()).is_err()) +} + +/// Does the given `Path` point to a valid tarball that can can loaded by ALPM? +pub fn is_valid_package(alpm: &Alpm, path: &Path) -> bool { + match path.to_str() { + None => false, + Some(p) => path.exists() && alpm.pkg_load(p, true, SigLevel::USE_DEFAULT).is_ok(), + } +} From 7c4e9ab3c490864e4a470809a5c3cd34608e8749 Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Wed, 17 Aug 2022 17:04:00 +0900 Subject: [PATCH 3/9] lint: minor cleanup --- alpm-utils/src/alpm.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/alpm-utils/src/alpm.rs b/alpm-utils/src/alpm.rs index ca78f3a..f441d0d 100644 --- a/alpm-utils/src/alpm.rs +++ b/alpm-utils/src/alpm.rs @@ -1,31 +1,32 @@ +//! Extension methods for the [`Alpm`] type. + use crate::depends::satisfies_ver; use crate::DbListExt; -use alpm::{Alpm, Depend, Package, PackageReason, Result, SigLevel}; +use alpm::{Alpm, Depend, Package, PackageReason, SigLevel}; use std::path::Path; /// Extension methods to the [`Alpm`] type. pub trait AlpmExt { /// Try to find a [`Package`] that satisfies a given dependency. - fn find_local_satisfier(&self, pkg: S) -> Result>> + fn find_local_satisfier(&self, pkg: S) -> Option> where S: Into; } impl AlpmExt for Alpm { - fn find_local_satisfier(&self, pkg: S) -> Result>> + fn find_local_satisfier(&self, pkg: S) -> Option> where S: Into, { let localdb = self.localdb(); let pkg = pkg.into(); - if let Ok(alpm_pkg) = localdb.pkg(pkg.as_str()) { - if satisfies_ver(Depend::new(pkg.as_str()), alpm_pkg.version()) { - return Ok(Some(alpm_pkg)); + match localdb.pkg(pkg.as_str()) { + Ok(alpm_pkg) if satisfies_ver(Depend::new(pkg.as_str()), alpm_pkg.version()) => { + Some(alpm_pkg) } + _ => localdb.pkgs().find_satisfier(pkg), } - - Ok(localdb.pkgs().find_satisfier(pkg)) } } From 7dc220d26a4d3e30d28af216f6f3398a8869da26 Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Wed, 17 Aug 2022 17:33:35 +0900 Subject: [PATCH 4/9] fix: correct the module tree --- alpm-utils/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/alpm-utils/src/lib.rs b/alpm-utils/src/lib.rs index efb9742..2ca822f 100644 --- a/alpm-utils/src/lib.rs +++ b/alpm-utils/src/lib.rs @@ -8,7 +8,7 @@ mod conf; #[cfg(feature = "alpm")] -mod alpm; +pub mod alpm; mod db; /// Utils for dependency checking. @@ -20,6 +20,5 @@ mod target; pub use crate::conf::*; #[cfg(feature = "alpm")] -pub use crate::alpm::*; pub use crate::db::*; pub use crate::target::*; From 21c36c23513876d4dbbb7b032b572219ab98ad8d Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Fri, 26 Aug 2022 14:00:41 +0900 Subject: [PATCH 5/9] feat(utils): drop unneeded functionality And rename a few functions. --- alpm-utils/src/alpm.rs | 53 +++--------------------------------------- 1 file changed, 3 insertions(+), 50 deletions(-) diff --git a/alpm-utils/src/alpm.rs b/alpm-utils/src/alpm.rs index f441d0d..67e10f8 100644 --- a/alpm-utils/src/alpm.rs +++ b/alpm-utils/src/alpm.rs @@ -1,49 +1,10 @@ //! Extension methods for the [`Alpm`] type. -use crate::depends::satisfies_ver; use crate::DbListExt; -use alpm::{Alpm, Depend, Package, PackageReason, SigLevel}; -use std::path::Path; - -/// Extension methods to the [`Alpm`] type. -pub trait AlpmExt { - /// Try to find a [`Package`] that satisfies a given dependency. - fn find_local_satisfier(&self, pkg: S) -> Option> - where - S: Into; -} - -impl AlpmExt for Alpm { - fn find_local_satisfier(&self, pkg: S) -> Option> - where - S: Into, - { - let localdb = self.localdb(); - let pkg = pkg.into(); - - match localdb.pkg(pkg.as_str()) { - Ok(alpm_pkg) if satisfies_ver(Depend::new(pkg.as_str()), alpm_pkg.version()) => { - Some(alpm_pkg) - } - _ => localdb.pkgs().find_satisfier(pkg), - } - } -} - -/// All orphaned packages. -/// -/// An orphan is a package that was installed as a dependency, but whose parent -/// package is no longer installed. -pub fn orphans(alpm: &Alpm) -> impl Iterator> { - alpm.localdb().pkgs().into_iter().filter(|p| { - p.reason() == PackageReason::Depend - && p.required_by().is_empty() - && p.optional_for().is_empty() - }) -} +use alpm::{Alpm, Package}; /// All official packages. -pub fn officials(alpm: &Alpm) -> impl Iterator> { +pub fn native_packages(alpm: &Alpm) -> impl Iterator> { let syncs = alpm.syncdbs(); alpm.localdb() @@ -53,7 +14,7 @@ pub fn officials(alpm: &Alpm) -> impl Iterator> { } /// All foreign packages as an `Iterator`. -pub fn foreigns(alpm: &Alpm) -> impl Iterator> { +pub fn foreign_packages(alpm: &Alpm) -> impl Iterator> { let syncs = alpm.syncdbs(); alpm.localdb() @@ -61,11 +22,3 @@ pub fn foreigns(alpm: &Alpm) -> impl Iterator> { .into_iter() .filter(move |p| syncs.pkg(p.name()).is_err()) } - -/// Does the given `Path` point to a valid tarball that can can loaded by ALPM? -pub fn is_valid_package(alpm: &Alpm, path: &Path) -> bool { - match path.to_str() { - None => false, - Some(p) => path.exists() && alpm.pkg_load(p, true, SigLevel::USE_DEFAULT).is_ok(), - } -} From 1fc2aa3dd65c9c270c6b2cbb1557e98a5ab84f70 Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Fri, 26 Aug 2022 14:05:11 +0900 Subject: [PATCH 6/9] feat(utils): rework module structure --- alpm-utils/src/depends.rs | 2 +- alpm-utils/src/lib.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/alpm-utils/src/depends.rs b/alpm-utils/src/depends.rs index c46a886..49ebb13 100644 --- a/alpm-utils/src/depends.rs +++ b/alpm-utils/src/depends.rs @@ -62,7 +62,7 @@ pub fn satisfies_provide_nover(dep: impl AsDep, provide: impl AsDep) -> bool { dep.as_dep().name() == provide.as_dep().name() } -pub(crate) fn satisfies_ver>(dep: impl AsDep, version: V) -> bool { +fn satisfies_ver>(dep: impl AsDep, version: V) -> bool { let version = version.as_ref(); let dep = dep.as_dep(); diff --git a/alpm-utils/src/lib.rs b/alpm-utils/src/lib.rs index 2ca822f..efb9742 100644 --- a/alpm-utils/src/lib.rs +++ b/alpm-utils/src/lib.rs @@ -8,7 +8,7 @@ mod conf; #[cfg(feature = "alpm")] -pub mod alpm; +mod alpm; mod db; /// Utils for dependency checking. @@ -20,5 +20,6 @@ mod target; pub use crate::conf::*; #[cfg(feature = "alpm")] +pub use crate::alpm::*; pub use crate::db::*; pub use crate::target::*; From cf070a15c186063951ed23e92c4d49839c416d00 Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Fri, 12 May 2023 10:28:30 +0900 Subject: [PATCH 7/9] feat(utils): revive `AlpmExt` yet again This required implementing some custom iterator structs, since `impl Foo` is not allowed for the return types of trait methods. --- alpm-utils/src/alpm.rs | 80 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/alpm-utils/src/alpm.rs b/alpm-utils/src/alpm.rs index 67e10f8..43314ce 100644 --- a/alpm-utils/src/alpm.rs +++ b/alpm-utils/src/alpm.rs @@ -1,24 +1,74 @@ //! Extension methods for the [`Alpm`] type. use crate::DbListExt; -use alpm::{Alpm, Package}; +use alpm::{Alpm, AlpmList, Db, IntoIter, Package}; -/// All official packages. -pub fn native_packages(alpm: &Alpm) -> impl Iterator> { - let syncs = alpm.syncdbs(); +/// Extension methods for [`Alpm`] which aren't critical enough to live in the +/// main crate, directly within `Alpm`. +pub trait AlpmExt { + /// An iterator of [`Package`]s that are found in "sync databases", + /// typically registered in one's `pacman.conf`. + fn native_packages<'a>(&'a self) -> NativePkgs<'a>; - alpm.localdb() - .pkgs() - .into_iter() - .filter_map(move |p| syncs.pkg(p.name()).ok()) + /// The opposite of [`AlpmExt::native_packages`]; installed packages that + /// aren't found in any registered "sync database". + fn foreign_packages<'a>(&'a self) -> ForeignPkgs<'a>; } -/// All foreign packages as an `Iterator`. -pub fn foreign_packages(alpm: &Alpm) -> impl Iterator> { - let syncs = alpm.syncdbs(); +impl AlpmExt for Alpm { + fn native_packages<'a>(&'a self) -> NativePkgs<'a> { + NativePkgs::new(self) + } - alpm.localdb() - .pkgs() - .into_iter() - .filter(move |p| syncs.pkg(p.name()).is_err()) + fn foreign_packages<'a>(&'a self) -> ForeignPkgs<'a> { + ForeignPkgs::new(self) + } +} + +/// [`Package`]s that are found in registered "sync databases". +pub struct NativePkgs<'a> { + local: IntoIter<'a, Package<'a>>, + sync: AlpmList<'a, Db<'a>>, +} + +impl<'a> NativePkgs<'a> { + fn new(alpm: &'a Alpm) -> NativePkgs<'a> { + let local = alpm.localdb().pkgs().into_iter(); + let sync = alpm.syncdbs(); + + NativePkgs { local, sync } + } +} + +impl<'a> Iterator for NativePkgs<'a> { + type Item = Package<'a>; + + fn next(&mut self) -> Option { + let s = self.sync; + self.local.find(|p| s.pkg(p.name()).is_ok()) + } +} + +/// Installed [`Package`]s that are _not_ found in registered "sync databases". +pub struct ForeignPkgs<'a> { + local: IntoIter<'a, Package<'a>>, + sync: AlpmList<'a, Db<'a>>, +} + +impl<'a> ForeignPkgs<'a> { + fn new(alpm: &'a Alpm) -> ForeignPkgs<'a> { + let local = alpm.localdb().pkgs().into_iter(); + let sync = alpm.syncdbs(); + + ForeignPkgs { local, sync } + } +} + +impl<'a> Iterator for ForeignPkgs<'a> { + type Item = Package<'a>; + + fn next(&mut self) -> Option { + let s = self.sync; + self.local.find(|p| s.pkg(p.name()).is_err()) + } } From 1cef5c66593c56339f30bd256d3e46102126b16b Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Fri, 12 May 2023 10:29:52 +0900 Subject: [PATCH 8/9] lint: silence `cargo doc` warning --- alpm-utils/src/db.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alpm-utils/src/db.rs b/alpm-utils/src/db.rs index f0b0a3f..8e8bb77 100644 --- a/alpm-utils/src/db.rs +++ b/alpm-utils/src/db.rs @@ -2,7 +2,7 @@ use alpm::{AlpmList, Db, Package, Result}; use crate::AsTarg; -/// Extention for AlpmList +/// Extentions for `AlpmList`. pub trait DbListExt<'a> { /// Similar to find_satisfier() but expects a Target instead of a &str. fn find_target_satisfier(&self, target: T) -> Option>; From 4be3deeace1d4943c761a9a352b08fda0ab79d49 Mon Sep 17 00:00:00 2001 From: Colin Woodbury Date: Fri, 12 May 2023 10:32:10 +0900 Subject: [PATCH 9/9] lint: appease Clippy --- alpm-utils/src/alpm.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/alpm-utils/src/alpm.rs b/alpm-utils/src/alpm.rs index 43314ce..762bb8d 100644 --- a/alpm-utils/src/alpm.rs +++ b/alpm-utils/src/alpm.rs @@ -8,19 +8,19 @@ use alpm::{Alpm, AlpmList, Db, IntoIter, Package}; pub trait AlpmExt { /// An iterator of [`Package`]s that are found in "sync databases", /// typically registered in one's `pacman.conf`. - fn native_packages<'a>(&'a self) -> NativePkgs<'a>; + fn native_packages(&self) -> NativePkgs<'_>; /// The opposite of [`AlpmExt::native_packages`]; installed packages that /// aren't found in any registered "sync database". - fn foreign_packages<'a>(&'a self) -> ForeignPkgs<'a>; + fn foreign_packages(&self) -> ForeignPkgs<'_>; } impl AlpmExt for Alpm { - fn native_packages<'a>(&'a self) -> NativePkgs<'a> { + fn native_packages(&self) -> NativePkgs<'_> { NativePkgs::new(self) } - fn foreign_packages<'a>(&'a self) -> ForeignPkgs<'a> { + fn foreign_packages(&self) -> ForeignPkgs<'_> { ForeignPkgs::new(self) } }