From 61df18ba4319f4b1f28dc89080cd7b8822ebffba Mon Sep 17 00:00:00 2001 From: Fabio Valentini Date: Fri, 28 Feb 2020 12:05:43 +0100 Subject: [PATCH] print all installed binary packages instead of source packages --- Cargo.lock | 16 ++++++++-------- Cargo.toml | 1 + src/input.rs | 9 +++++++-- src/lib.rs | 2 ++ src/main.rs | 36 +++++++++++++++++++++++++++++------ src/output.rs | 4 ++-- src/sysinfo.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 101 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc42e4b..fead642 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -862,9 +862,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548" +checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" dependencies = [ "unicode-xid", ] @@ -975,9 +975,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae3fc32eacd4a5200c6b34bd6c057b07fb64f5a1e55bb67d624cc1393354621" +checksum = "a9f62f24514117d09a8fc74b803d3d65faa27cea1c7378fb12b0d002913f3831" dependencies = [ "base64", "bytes", @@ -1227,9 +1227,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a0294dc449adc58bb6592fff1a23d3e5e6e235afc6a0ffca2657d19e7bbffe5" +checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" dependencies = [ "proc-macro2", "quote", @@ -1307,9 +1307,9 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fdd17989496f49cdc57978c96f0c9fe5e4a58a8bddc6813c449a4624f6a030b" +checksum = "b34bee1facdc352fba10c9c58b654e6ecb6a2250167772bf86071f7c5f2f5061" dependencies = [ "bytes", "fnv", diff --git a/Cargo.toml b/Cargo.toml index 0a53ed3..a0105dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,4 +26,5 @@ toml = "^0.5.5" [profile.release] codegen-units = 1 lto = true +opt-level = 3 diff --git a/src/input.rs b/src/input.rs index d21d98b..35764ba 100644 --- a/src/input.rs +++ b/src/input.rs @@ -56,7 +56,7 @@ pub fn str_to_karma(string: &str) -> Option { pub fn ask_feedback<'a>( rl: &mut rustyline::Editor<()>, update: &'a Update, - builds: &[String], + builds: &[&str], ) -> Result, String> { print_update(update, builds); @@ -94,7 +94,12 @@ pub fn ask_feedback<'a>( if !comment_lines.is_empty() { // if both the last line and the current line are empty, break - if comment_lines.last().unwrap().is_empty() && line.is_empty() { + if comment_lines + .last() + .expect("Something went wrong. There must be a last item in a non-empty iterable.") + .is_empty() + && line.is_empty() + { break; }; }; diff --git a/src/lib.rs b/src/lib.rs index d709048..ed72024 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,6 @@ #![warn(missing_docs)] +#![warn(clippy::result_unwrap_used)] +#![warn(clippy::option_unwrap_used)] //! This crate contains helper functionality that's used by the `fedora-update-feedback` binary. //! It's contents are probably not useful for external use. But if something turns out to be diff --git a/src/main.rs b/src/main.rs index 4180da1..0a13666 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,6 +26,7 @@ struct Command { clear_ignored: bool, } +#[allow(clippy::cognitive_complexity)] fn main() -> Result<(), String> { let args: Command = Command::from_args(); @@ -68,6 +69,8 @@ fn main() -> Result<(), String> { // query DNF for installed packages println!("Querying dnf for installed packages ..."); let installed_packages = get_installed()?; + // query DNF for source -> binary package map + let src_bin_map = get_src_bin_map()?; println!("Querying bodhi for updates ..."); let mut updates: Vec = Vec::new(); @@ -150,7 +153,7 @@ fn main() -> Result<(), String> { builds_for_update .entry(update.alias.clone()) .and_modify(|e| e.push(nvr.to_string())) - .or_insert(vec![nvr.to_string()]); + .or_insert_with(|| vec![nvr.to_string()]); }; } } @@ -189,7 +192,14 @@ fn main() -> Result<(), String> { // this unwrap is safe since we definitely inserted a value for every update let builds = builds_for_update.get(update.alias.as_str()).unwrap(); - let feedback = ask_feedback(&mut rl, update, &builds)?; + let mut binaries: Vec<&str> = Vec::new(); + for build in builds { + if let Some(list) = src_bin_map.get(build) { + binaries.extend(list.iter().map(|s| s.as_str())); + }; + } + + let feedback = ask_feedback(&mut rl, update, &binaries)?; match feedback { Feedback::Cancel => { @@ -294,7 +304,7 @@ fn main() -> Result<(), String> { builds_for_update .entry(update.alias.clone()) .and_modify(|e| e.push(nvr.to_string())) - .or_insert(vec![nvr.to_string()]); + .or_insert_with(|| vec![nvr.to_string()]); }; } } @@ -307,7 +317,14 @@ fn main() -> Result<(), String> { println!(" - {}:", update.title); // this unwrap is safe since we definitely inserted a value for every update for build in builds_for_update.get(update.alias.as_str()).unwrap() { - println!(" - {}", build); + let mut binaries: Vec<&str> = Vec::new(); + if let Some(list) = src_bin_map.get(build) { + binaries.extend(list.iter().map(|s| s.as_str())); + }; + + for binary in binaries { + println!(" - {}", binary); + } } } }; @@ -354,7 +371,7 @@ fn main() -> Result<(), String> { builds_for_update .entry(update.alias.clone()) .and_modify(|e| e.push(nvr.to_string())) - .or_insert(vec![nvr.to_string()]); + .or_insert_with(|| vec![nvr.to_string()]); }; } } @@ -367,7 +384,14 @@ fn main() -> Result<(), String> { println!(" - {}:", update.title); // this unwrap is safe since we definitely inserted a value for every update for build in builds_for_update.get(update.alias.as_str()).unwrap() { - println!(" - {}", build); + let mut binaries: Vec<&str> = Vec::new(); + if let Some(list) = src_bin_map.get(build) { + binaries.extend(list.iter().map(|s| s.as_str())); + }; + + for binary in binaries { + println!(" - {}", binary); + } } } }; diff --git a/src/output.rs b/src/output.rs index 821ff32..85af42c 100644 --- a/src/output.rs +++ b/src/output.rs @@ -27,11 +27,11 @@ pub fn progress_bar(prefix: &str, p: u32, ps: u32) { ); print!("\r{}", &line); - stdout().flush().unwrap(); + stdout().flush().expect("Failed to write to stdout."); } /// This helper function pretty-prints an update. -pub fn print_update(update: &Update, builds: &[String]) { +pub fn print_update(update: &Update, builds: &[&str]) { let date = match &update.date_submitted { Some(date) => date.to_string(), None => "(None)".to_string(), diff --git a/src/sysinfo.rs b/src/sysinfo.rs index 9f69984..a6d9d89 100644 --- a/src/sysinfo.rs +++ b/src/sysinfo.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::process::Command; use bodhi::FedoraRelease; @@ -90,3 +91,53 @@ pub fn get_installed() -> Result, String> { Ok(packages) } + +/// This helper function returns a map from source -> binary package NVRs for installed packages. +pub fn get_src_bin_map() -> Result>, String> { + // query dnf for installed binary packages and their corresponding source package + let output = match Command::new("dnf") + .arg("--quiet") + .arg("repoquery") + .arg("--cacheonly") + .arg("--installed") + .arg("--qf") + .arg("%{source_name}-%{version}-%{release} %{name}-%{version}-%{release}.%{arch}") + .output() + { + Ok(output) => output, + Err(error) => return Err(format!("{}", error)), + }; + + match output.status.code() { + Some(x) if x != 0 => return Err(String::from("Failed to query dnf.")), + Some(_) => {}, + None => return Err(String::from("Failed to query dnf.")), + } + + let results = match std::str::from_utf8(&output.stdout) { + Ok(result) => result, + Err(error) => return Err(format!("{}", error)), + }; + + let lines: Vec<&str> = results.trim().split('\n').collect(); + + let mut pkg_map: HashMap> = HashMap::new(); + + for line in lines { + let parts: Vec<&str> = line.split(' ').collect(); + + if parts.len() != 2 { + return Err(String::from("Failed to parse dnf output.")); + }; + + let source = parts.get(0).unwrap(); + let binary = parts.get(1).unwrap(); + + pkg_map + .entry((*source).to_string()) + .and_modify(|v| v.push((*binary).to_string())) + .or_insert_with(|| vec![(*binary).to_string()]); + } + + Ok(pkg_map) +}