From 4eb2b6a4544f0c2cfd0d72b1fac27bfb2882a4b4 Mon Sep 17 00:00:00 2001 From: Matthias Beyer Date: Wed, 24 Apr 2019 09:46:43 +0200 Subject: Add "compare" functionality in main() Including the new dependency "csv" which is included by default. With this, one can pass a CSV file to compare against, as well as a JSON file. --- Cargo.toml | 8 ++++++++ src/main.rs | 45 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 877701b..290c61a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,3 +26,11 @@ filters = "0.3" version = ">=2.33" default-features = false features = [ "suggestions", "color", "wrap_help" ] + +[dependencies.csv] +version = "1" +optional = true + +[features] +default = ["compare_csv"] +compare_csv = ["csv"] \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index dddbe42..62e193d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,9 @@ extern crate reqwest; extern crate tokio; extern crate filters; +#[cfg(feature = "compare_csv")] +extern crate csv; + #[macro_use] extern crate serde_derive; #[macro_use] extern crate log; #[macro_use] extern crate failure; @@ -20,6 +23,10 @@ mod frontend; mod cli; use std::path::PathBuf; + +#[cfg(feature = "compare_csv")] +use std::io::Cursor; + use failure::err_msg; use failure::Error; use failure::Fallible as Result; @@ -29,6 +36,7 @@ use filters::filter::Filter; use config::Configuration; use librepology::v1::api::Api; use librepology::v1::types::Repo; +use librepology::v1::types::Package; fn initialize_logging(app: &ArgMatches) -> Result<()> { let verbosity = app.occurrences_of("verbose"); @@ -57,6 +65,33 @@ fn initialize_logging(app: &ArgMatches) -> Result<()> { .map_err(Error::from) } +fn deserialize_package_list(s: String, filepath: &str) -> Result> { + let pb = PathBuf::from(filepath); + let ext = pb + .extension() + .ok_or_else(|| format_err!("Couldn't get file extension: {}", filepath))? + .to_str() + .ok_or_else(|| format_err!("Not valid Unicode: {}", filepath))?; + + match ext { + "json" => { + serde_json::from_str(&s).map_err(Error::from) + }, + + #[cfg(feature = "compare_csv")] + "csv" => { + let cursor = Cursor::new(s); + let mut v : Vec = vec![]; + for element in csv::Reader::from_reader(cursor).deserialize() { + v.push(element?); + } + Ok(v) + }, + + other => Err(format_err!("Unknown file extension: {}", other))?, + } +} + fn main() -> Result<()> { let app = cli::build_cli().get_matches(); initialize_logging(&app)?; @@ -145,7 +180,15 @@ fn main() -> Result<()> { .collect(); frontend.list_problems(problems)?; - } + }, + ("compare", Some(mtch)) => { + let repos = mtch.values_of("compare-distros").unwrap().map(|s| Repo::new(String::from(s))).collect(); + let file_path = mtch.value_of("compare-list").unwrap(); // safe by clap + let content = ::std::fs::read_to_string(file_path).map_err(Error::from)?; + let pkgs : Vec = deserialize_package_list(content, file_path)?; + + frontend.compare_packages(pkgs, &backend, repos)?; + }, (other, _mtch) => { if app.is_present("input_stdin") { -- cgit v1.2.3