diff options
27 files changed, 164 insertions, 140 deletions
diff --git a/librepology/src/lib.rs b/librepology/src/lib.rs index 514cac4..8ca04da 100644 --- a/librepology/src/lib.rs +++ b/librepology/src/lib.rs @@ -1,13 +1,17 @@ -extern crate thiserror; +extern crate curl; extern crate serde; extern crate serde_json; +extern crate thiserror; extern crate url; extern crate url_serde; -extern crate curl; -#[macro_use] extern crate serde_derive; -#[macro_use] extern crate log; -#[macro_use] extern crate derive_more; -#[macro_use] extern crate derive_new; +#[macro_use] +extern crate serde_derive; +#[macro_use] +extern crate log; +#[macro_use] +extern crate derive_more; +#[macro_use] +extern crate derive_new; pub mod v1; diff --git a/librepology/src/v1/api.rs b/librepology/src/v1/api.rs index 3d659df..1c8cd6e 100644 --- a/librepology/src/v1/api.rs +++ b/librepology/src/v1/api.rs @@ -1,6 +1,6 @@ use crate::v1::error::Result; -use crate::v1::types::Problem; use crate::v1::types::Package; +use crate::v1::types::Problem; /// The high-level functionality of the repology API is represented in this trait /// @@ -17,5 +17,3 @@ pub trait Api { fn problems_for_maintainer<M: AsRef<str>>(&self, maintainer: M) -> Result<Vec<Problem>>; } - - diff --git a/librepology/src/v1/buffer.rs b/librepology/src/v1/buffer.rs index 534ab4c..e2eb67a 100644 --- a/librepology/src/v1/buffer.rs +++ b/librepology/src/v1/buffer.rs @@ -1,20 +1,20 @@ use std::io::Read; -use crate::v1::error::Result; +use crate::v1::api::Api; use crate::v1::error::RepologyError as Error; -use crate::v1::types::Problem; +use crate::v1::error::Result; use crate::v1::types::Package; -use crate::v1::api::Api; +use crate::v1::types::Problem; #[derive(Debug)] pub struct BufferApi { buf: String, } -impl BufferApi -{ +impl BufferApi { pub fn read_from<R>(mut input: R) -> Result<BufferApi> - where R: Read, + where + R: Read, { let mut buf = String::new(); let read = input.read_to_string(&mut buf)?; @@ -24,7 +24,6 @@ impl BufferApi } impl Api for BufferApi { - fn project<N: AsRef<str>>(&self, _name: N) -> Result<Vec<Package>> { serde_json::de::from_str(&self.buf).map_err(Error::from) } @@ -36,6 +35,4 @@ impl Api for BufferApi { fn problems_for_maintainer<M: AsRef<str>>(&self, _maintainer: M) -> Result<Vec<Problem>> { serde_json::de::from_str(&self.buf).map_err(Error::from) } - } - diff --git a/librepology/src/v1/mod.rs b/librepology/src/v1/mod.rs index aa1cd9b..781cc0f 100644 --- a/librepology/src/v1/mod.rs +++ b/librepology/src/v1/mod.rs @@ -1,5 +1,5 @@ -pub mod restapi; -pub mod buffer; pub mod api; -pub mod types; +pub mod buffer; pub mod error; +pub mod restapi; +pub mod types; diff --git a/librepology/src/v1/restapi.rs b/librepology/src/v1/restapi.rs index e9a6cd1..1f68c41 100644 --- a/librepology/src/v1/restapi.rs +++ b/librepology/src/v1/restapi.rs @@ -2,10 +2,10 @@ use std::result::Result as RResult; use curl::easy::Easy2; -use crate::v1::error::Result; +use crate::v1::api::Api; use crate::v1::error::RepologyError as Error; +use crate::v1::error::Result; use crate::v1::types::{Package, Problem}; -use crate::v1::api::Api; /// Private helper type for collecting data from the curl library struct Collector(Vec<u8>); @@ -39,27 +39,32 @@ impl RestApi { } impl Api for RestApi { - fn project<N: AsRef<str>>(&self, name: N) -> Result<Vec<Package>> { let url = format!("{}api/v1/project/{}", self.repology, name.as_ref()); trace!("Request: {}", url); let response = self.send_request(url)?; - serde_json::from_str(&response) - .map_err(Error::from) + serde_json::from_str(&response).map_err(Error::from) } fn problems_for_repo<R: AsRef<str>>(&self, repo: R) -> Result<Vec<Problem>> { - let url = format!("{}api/v1/repository/{}/problems", self.repology, repo.as_ref()); + let url = format!( + "{}api/v1/repository/{}/problems", + self.repology, + repo.as_ref() + ); trace!("Request: {}", url); let response = self.send_request(url)?; serde_json::from_str(&response).map_err(Error::from) } fn problems_for_maintainer<M: AsRef<str>>(&self, maintainer: M) -> Result<Vec<Problem>> { - let url = format!("{}api/v1/maintainer/{}/problems", self.repology, maintainer.as_ref()); + let url = format!( + "{}api/v1/maintainer/{}/problems", + self.repology, + maintainer.as_ref() + ); trace!("Request: {}", url); let response = self.send_request(url)?; serde_json::from_str(&response).map_err(Error::from) } - } diff --git a/librepology/src/v1/types/category.rs b/librepology/src/v1/types/category.rs index 975fe7f..ad118d0 100644 --- a/librepology/src/v1/types/category.rs +++ b/librepology/src/v1/types/category.rs @@ -11,4 +11,3 @@ impl Deref for Category { &self.0 } } - diff --git a/librepology/src/v1/types/download.rs b/librepology/src/v1/types/download.rs index d52a2db..e4d64d1 100644 --- a/librepology/src/v1/types/download.rs +++ b/librepology/src/v1/types/download.rs @@ -13,4 +13,3 @@ impl Deref for Download { &self.0 } } - diff --git a/librepology/src/v1/types/effname.rs b/librepology/src/v1/types/effname.rs index 118f56e..d940b63 100644 --- a/librepology/src/v1/types/effname.rs +++ b/librepology/src/v1/types/effname.rs @@ -11,4 +11,3 @@ impl Deref for EffName { &self.0 } } - diff --git a/librepology/src/v1/types/license.rs b/librepology/src/v1/types/license.rs index f755888..3c5fe4f 100644 --- a/librepology/src/v1/types/license.rs +++ b/librepology/src/v1/types/license.rs @@ -11,4 +11,3 @@ impl Deref for License { &self.0 } } - diff --git a/librepology/src/v1/types/maintainer.rs b/librepology/src/v1/types/maintainer.rs index f97fc91..4dbf506 100644 --- a/librepology/src/v1/types/maintainer.rs +++ b/librepology/src/v1/types/maintainer.rs @@ -11,4 +11,3 @@ impl Deref for Maintainer { &self.0 } } - diff --git a/librepology/src/v1/types/mod.rs b/librepology/src/v1/types/mod.rs index f192c49..434274b 100644 --- a/librepology/src/v1/types/mod.rs +++ b/librepology/src/v1/types/mod.rs @@ -33,4 +33,3 @@ pub use status::Status; pub use summary::Summary; pub use version::Version; pub use www::Www; - diff --git a/librepology/src/v1/types/name.rs b/librepology/src/v1/types/name.rs index 70e3317..0097f99 100644 --- a/librepology/src/v1/types/name.rs +++ b/librepology/src/v1/types/name.rs @@ -11,4 +11,3 @@ impl Deref for Name { &self.0 } } - diff --git a/librepology/src/v1/types/package.rs b/librepology/src/v1/types/package.rs index 4623fd3..1286b15 100644 --- a/librepology/src/v1/types/package.rs +++ b/librepology/src/v1/types/package.rs @@ -96,6 +96,4 @@ impl Package { pub fn downloads(&self) -> Option<&Vec<Download>> { self.downloads.as_ref() } - } - diff --git a/librepology/src/v1/types/repo.rs b/librepology/src/v1/types/repo.rs index 062358e..e5ddc87 100644 --- a/librepology/src/v1/types/repo.rs +++ b/librepology/src/v1/types/repo.rs @@ -11,4 +11,3 @@ impl Deref for Repo { &self.0 } } - diff --git a/librepology/src/v1/types/status.rs b/librepology/src/v1/types/status.rs index c42d510..726359e 100644 --- a/librepology/src/v1/types/status.rs +++ b/librepology/src/v1/types/status.rs @@ -41,4 +41,3 @@ pub enum Status { #[display(fmt = "ignored")] Ignored, } - diff --git a/librepology/src/v1/types/summary.rs b/librepology/src/v1/types/summary.rs index 0595fef..b1fc874 100644 --- a/librepology/src/v1/types/summary.rs +++ b/librepology/src/v1/types/summary.rs @@ -11,4 +11,3 @@ impl Deref for Summary { &self.0 } } - diff --git a/librepology/src/v1/types/version.rs b/librepology/src/v1/types/version.rs index 7ae7b85..2350316 100644 --- a/librepology/src/v1/types/version.rs +++ b/librepology/src/v1/types/version.rs @@ -11,4 +11,3 @@ impl Deref for Version { &self.0 } } - diff --git a/librepology/src/v1/types/www.rs b/librepology/src/v1/types/www.rs index 1b5b89e..04507a7 100644 --- a/librepology/src/v1/types/www.rs +++ b/librepology/src/v1/types/www.rs @@ -12,4 +12,3 @@ impl Deref for Www { &self.0 } } - diff --git a/src/backend.rs b/src/backend.rs index feba9d9..e260e8c 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,9 +1,9 @@ use clap::ArgMatches; use librepology::v1::api::Api; +use librepology::v1::buffer::BufferApi; use librepology::v1::error::Result; use librepology::v1::restapi::RestApi; -use librepology::v1::buffer::BufferApi; use librepology::v1::types::*; use crate::config::Configuration; @@ -44,7 +44,9 @@ impl Api for Backend { pub fn new_backend(app: &ArgMatches, config: &Configuration) -> anyhow::Result<Backend> { if app.is_present("input_stdin") { trace!("Building new STDIN backend"); - BufferApi::read_from(std::io::stdin()).map(Backend::Buffer).map_err(anyhow::Error::from) + BufferApi::read_from(std::io::stdin()) + .map(Backend::Buffer) + .map_err(anyhow::Error::from) } else { trace!("Building new remote backend"); let url = config.repology_url().as_str().into(); @@ -177,5 +177,4 @@ pub fn build_cli<'a>() -> App<'a, 'a> { fetched from repology.org/api/v1 via curl (or some other method). In this case, repolocli is only a easier-to-use 'jq' (if you don't know jq, look it up NOW!). "#) - } diff --git a/src/compare.rs b/src/compare.rs index c13d01e..047fc99 100644 --- a/src/compare.rs +++ b/src/compare.rs @@ -12,4 +12,4 @@ impl ComparePackage { pub fn version(&self) -> &String { &self.version } -}
\ No newline at end of file +} diff --git a/src/config.rs b/src/config.rs index fde6c1e..240b13f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -25,6 +25,4 @@ impl Configuration { pub fn blacklist(&self) -> &Vec<String> { &self.blacklist } - } - diff --git a/src/frontend/json.rs b/src/frontend/json.rs index 6ef5e0c..42e44d1 100644 --- a/src/frontend/json.rs +++ b/src/frontend/json.rs @@ -8,9 +8,9 @@ use librepology::v1::types::Package; use librepology::v1::types::Problem; use librepology::v1::types::Repo; -use crate::frontend::Frontend; use crate::backend::Backend; use crate::compare::ComparePackage; +use crate::frontend::Frontend; use librepology::v1::api::Api; pub struct JsonFrontend(Stdout); @@ -38,14 +38,18 @@ impl JsonFrontend { impl Frontend for JsonFrontend { fn list_packages(&self, packages: Vec<Package>) -> Result<()> { self.write(serde_json::ser::to_string_pretty(&packages).map_err(Error::from)?) - } fn list_problems(&self, problems: Vec<Problem>) -> Result<()> { self.write(serde_json::ser::to_string_pretty(&problems).map_err(Error::from)?) } - fn compare_packages(&self, packages: Vec<ComparePackage>, backend: &Backend, filter_repos: Vec<Repo>) -> Result<()> { + fn compare_packages( + &self, + packages: Vec<ComparePackage>, + backend: &Backend, + filter_repos: Vec<Repo>, + ) -> Result<()> { #[derive(Serialize)] struct PackageComp { // not optimal, as we have to clone the inner variables from the package @@ -64,7 +68,6 @@ impl Frontend for JsonFrontend { let mut output: Vec<PackageComp> = vec![]; for package in packages.iter() { - let comparisons = backend .project(package.name().deref())? .into_iter() @@ -85,4 +88,3 @@ impl Frontend for JsonFrontend { self.write(serde_json::ser::to_string_pretty(&output)?) } } - diff --git a/src/frontend/list.rs b/src/frontend/list.rs index 61aa670..469d6ec 100644 --- a/src/frontend/list.rs +++ b/src/frontend/list.rs @@ -9,9 +9,9 @@ use librepology::v1::types::Package; use librepology::v1::types::Problem; use librepology::v1::types::Repo; -use crate::frontend::Frontend; use crate::backend::Backend; use crate::compare::ComparePackage; +use crate::frontend::Frontend; use librepology::v1::api::Api; pub struct ListFrontend(Stdout); @@ -31,13 +31,13 @@ impl Frontend for ListFrontend { packages.iter().fold(Ok(()), |accu, package| { accu.and_then(|_| { - let status= if let Some(stat) = package.status() { + let status = if let Some(stat) = package.status() { stat.deref().to_string() } else { String::from("No status") }; // not optimal, but works for now. - let url= if let Some(url) = package.www() { + let url = if let Some(url) = package.www() { if let Some(url) = url.first() { url.deref().to_string() } else { @@ -47,13 +47,21 @@ impl Frontend for ListFrontend { String::from("") }; // not optimal, but works for now - writeln!(outlock, - "{name:10} - {version:8} - {repo:15} - {status:5} - {www}", - name = package.any_name().map(Name::deref).map(String::deref).unwrap_or_else(|| "<unknown>"), - version = package.version().deref(), - repo = package.repo().deref(), - status = status, - www = url).map(|_| ()).map_err(Error::from) + writeln!( + outlock, + "{name:10} - {version:8} - {repo:15} - {status:5} - {www}", + name = package + .any_name() + .map(Name::deref) + .map(String::deref) + .unwrap_or_else(|| "<unknown>"), + version = package.version().deref(), + repo = package.repo().deref(), + status = status, + www = url + ) + .map(|_| ()) + .map_err(Error::from) }) }) } @@ -63,20 +71,27 @@ impl Frontend for ListFrontend { problems.iter().fold(Ok(()), |accu, problem| { accu.and_then(|_| { - writeln!(outlock, - "{repo:10} - {name:10} - {effname:10} - {maintainer:15} - {desc}", - repo = problem.repo().deref(), - name = problem.name().deref(), - effname = problem.effname().deref(), - maintainer = problem.maintainer().deref(), - desc = problem.problem_description()) - .map(|_| ()) - .map_err(Error::from) + writeln!( + outlock, + "{repo:10} - {name:10} - {effname:10} - {maintainer:15} - {desc}", + repo = problem.repo().deref(), + name = problem.name().deref(), + effname = problem.effname().deref(), + maintainer = problem.maintainer().deref(), + desc = problem.problem_description() + ) + .map(|_| ()) + .map_err(Error::from) }) }) } - fn compare_packages(&self, packages: Vec<ComparePackage>, backend: &Backend, filter_repos: Vec<Repo>) -> Result<()> { + fn compare_packages( + &self, + packages: Vec<ComparePackage>, + backend: &Backend, + filter_repos: Vec<Repo>, + ) -> Result<()> { let mut output = self.0.lock(); for package in packages { @@ -99,4 +114,3 @@ impl Frontend for ListFrontend { Ok(()) } } - diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs index e2dda0e..c9ef381 100644 --- a/src/frontend/mod.rs +++ b/src/frontend/mod.rs @@ -3,22 +3,27 @@ use clap::ArgMatches; use librepology::v1::types::*; +use crate::backend::Backend; +use crate::compare::ComparePackage; use crate::config::Configuration; -use crate::frontend::list::ListFrontend; use crate::frontend::json::JsonFrontend; +use crate::frontend::list::ListFrontend; use crate::frontend::table::TableFrontend; -use crate::compare::ComparePackage; -use crate::backend::Backend; /// A Frontend represents a way to show the data to the user pub trait Frontend { fn list_packages(&self, packages: Vec<Package>) -> Result<()>; fn list_problems(&self, problems: Vec<Problem>) -> Result<()>; - fn compare_packages(&self, packages: Vec<ComparePackage>, backend: &Backend, filter_repos: Vec<Repo>) -> Result<()>; + fn compare_packages( + &self, + packages: Vec<ComparePackage>, + backend: &Backend, + filter_repos: Vec<Repo>, + ) -> Result<()>; } -pub mod list; pub mod json; +pub mod list; pub mod table; /// Helper function for building a new Frontend object based on the commandline parameters @@ -27,19 +32,18 @@ pub fn new_frontend(app: &ArgMatches, _config: &Configuration) -> Result<Box<dyn None | Some("lines") => { debug!("No output specified, using default"); Ok(Box::new(ListFrontend::new(::std::io::stdout()))) - }, + } Some("json") => { debug!("Using JSON Frontend"); Ok(Box::new(JsonFrontend::new(::std::io::stdout()))) - }, + } Some("table") => { debug!("Using table Frontend"); Ok(Box::new(TableFrontend::new(::std::io::stdout()))) - }, + } Some(other) => Err(format_err!("Unknown Frontend '{}'", other)), } - } diff --git a/src/frontend/table.rs b/src/frontend/table.rs index 12452a8..6bb42d2 100644 --- a/src/frontend/table.rs +++ b/src/frontend/table.rs @@ -9,9 +9,9 @@ use librepology::v1::types::Repo; use prettytable::format; use prettytable::Table; -use crate::frontend::Frontend; use crate::backend::Backend; use crate::compare::ComparePackage; +use crate::frontend::Frontend; use librepology::v1::api::Api; /// A Frontend that formats the output in a nice ASCII-art table @@ -28,8 +28,12 @@ impl TableFrontend { .column_separator('|') .borders('|') .separators( - &[format::LinePosition::Title, format::LinePosition::Top, format::LinePosition::Bottom], - format::LineSeparator::new('-', '+', '+', '+') + &[ + format::LinePosition::Title, + format::LinePosition::Top, + format::LinePosition::Bottom, + ], + format::LineSeparator::new('-', '+', '+', '+'), ) .padding(1, 1) .build(); @@ -65,7 +69,8 @@ impl Frontend for TableFrontend { String::from("") }; // not optimal, but works for now - let name = package.any_name() + let name = package + .any_name() .map(Name::deref) .map(String::clone) .unwrap_or_else(|| String::from("<unknown>")); @@ -90,7 +95,12 @@ impl Frontend for TableFrontend { self.print(table) } - fn compare_packages(&self, packages: Vec<ComparePackage>, backend: &Backend, filter_repos: Vec<Repo>) -> Result<()> { + fn compare_packages( + &self, + packages: Vec<ComparePackage>, + backend: &Backend, + filter_repos: Vec<Repo>, + ) -> Result<()> { let mut table = self.mktable(); for package in packages { backend @@ -99,14 +109,13 @@ impl Frontend for TableFrontend { .filter(|p| filter_repos.contains(p.repo())) .for_each(|upstream_package| { table.add_row(row![ - package.name().clone(), - package.version().clone(), - upstream_package.repo().clone(), - upstream_package.version().clone(), - ]); + package.name().clone(), + package.version().clone(), + upstream_package.repo().clone(), + upstream_package.version().clone(), + ]); }); } self.print(table) } } - diff --git a/src/main.rs b/src/main.rs index c963f63..6a171a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,48 +1,52 @@ +extern crate boolinator; +extern crate filters; +extern crate flexi_logger; +extern crate itertools; +extern crate semver; extern crate serde; extern crate serde_json; extern crate toml; extern crate url; extern crate xdg; -extern crate flexi_logger; -extern crate filters; -extern crate boolinator; -extern crate itertools; -extern crate semver; #[cfg(feature = "compare_csv")] extern crate csv; -#[macro_use] extern crate serde_derive; -#[macro_use] extern crate log; -#[macro_use] extern crate anyhow; -#[macro_use] extern crate prettytable; +#[macro_use] +extern crate serde_derive; +#[macro_use] +extern crate log; +#[macro_use] +extern crate anyhow; +#[macro_use] +extern crate prettytable; -mod config; mod backend; -mod frontend; mod cli; mod compare; +mod config; +mod frontend; -use std::path::PathBuf; use std::cmp::Ordering; +use std::path::PathBuf; #[cfg(feature = "compare_csv")] use std::io::Cursor; -use anyhow::Error; use anyhow::Context; +use anyhow::Error; use anyhow::Result; +use boolinator::Boolinator; use clap::ArgMatches; use filters::filter::Filter; -use boolinator::Boolinator; use itertools::Itertools; use semver::Version as SemverVersion; -use config::Configuration; use compare::ComparePackage; +use config::Configuration; use librepology::v1::api::Api; -use librepology::v1::types::Repo; use librepology::v1::types::Package; +use librepology::v1::types::Repo; fn initialize_logging(app: &ArgMatches) -> Result<()> { let verbosity = app.occurrences_of("verbose"); @@ -80,14 +84,12 @@ fn deserialize_package_list(s: String, filepath: &str) -> Result<Vec<ComparePack .ok_or_else(|| format_err!("Not valid Unicode: {}", filepath))?; match ext { - "json" => { - serde_json::from_str(&s).map_err(Error::from) - }, + "json" => serde_json::from_str(&s).map_err(Error::from), #[cfg(feature = "compare_csv")] "csv" => { let cursor = Cursor::new(s); - let mut v : Vec<ComparePackage> = vec![]; + let mut v: Vec<ComparePackage> = vec![]; let mut reader = csv::ReaderBuilder::new() .has_headers(true) .delimiter(b';') @@ -97,7 +99,7 @@ fn deserialize_package_list(s: String, filepath: &str) -> Result<Vec<ComparePack v.push(element?); } Ok(v) - }, + } other => Err(format_err!("Unknown file extension: {}", other)), } @@ -106,19 +108,16 @@ fn deserialize_package_list(s: String, filepath: &str) -> Result<Vec<ComparePack fn app() -> Result<()> { let app = cli::build_cli().get_matches(); initialize_logging(&app)?; - let config : Configuration = { - let path = if let Some(path) = app - .value_of("config") - .map(PathBuf::from) - { - debug!("Found passed configuration file at {}", path.display()); - Ok(path) - } else { - debug!("Searching for configuration in XDG"); - xdg::BaseDirectories::new()? - .find_config_file("repolocli.toml") - .ok_or_else(|| anyhow!("Cannot find repolocli.toml")) - }?; + let config: Configuration = { + let path = if let Some(path) = app.value_of("config").map(PathBuf::from) { + debug!("Found passed configuration file at {}", path.display()); + Ok(path) + } else { + debug!("Searching for configuration in XDG"); + xdg::BaseDirectories::new()? + .find_config_file("repolocli.toml") + .ok_or_else(|| anyhow!("Cannot find repolocli.toml")) + }?; debug!("Parsing configuration from file: {}", path.display()); @@ -176,7 +175,7 @@ fn app() -> Result<()> { // works for now "" } else { - mtch.value_of("project_name").unwrap() // safe by clap + mtch.value_of("project_name").unwrap() // safe by clap }; let mut packages: Vec<Package> = { @@ -186,7 +185,7 @@ fn app() -> Result<()> { .into_iter() .filter(|package| repository_filter.filter(package.repo())); - if mtch.is_present("sort-version"){ + if mtch.is_present("sort-version") { trace!("Sorting by version"); iter.sorted_by(|a, b| Ord::cmp(a.version(), b.version())) .collect() @@ -215,7 +214,11 @@ fn app() -> Result<()> { packages.sort_by(comp); } else { - packages.sort_by(|a, b| a.version().partial_cmp(b.version()).unwrap_or(Ordering::Equal)); + packages.sort_by(|a, b| { + a.version() + .partial_cmp(b.version()) + .unwrap_or(Ordering::Equal) + }); } packages.pop().into_iter().collect::<Vec<_>>() } else { @@ -224,7 +227,7 @@ fn app() -> Result<()> { debug!("Listing packages in frontend"); frontend.list_pac |