use crate::{
cache::{Cache, CachePackage, CachePackageSource, MprCache},
message,
};
use ansi_term::{Colour, Style};
use chrono::{TimeZone, Utc};
use rust_apt::cache::Cache as AptCache;
use std::{collections::HashMap, fmt::Write};
pub fn search(args: &clap::ArgMatches) {
let pkglist: Vec<&String> = args.get_many("pkg").unwrap().collect();
let mpr_url: &String = args.get_one("mpr-url").unwrap();
let apt_only = args.is_present("apt-only");
let mpr_only = args.is_present("mpr-only");
let apt_cache = AptCache::new();
let mpr_cache = MprCache::new(mpr_url);
let cache = Cache::new(&apt_cache, &mpr_cache);
let mut matches: Vec<&String> = Vec::new();
let package_map = cache.package_map();
for pkgname in cache.get_unique_pkgnames() {
if ((apt_only && mpr_only)
&& !(cache.available_apt(&package_map, pkgname)
&& cache.available_mpr(&package_map, pkgname)))
|| (apt_only && !cache.available_apt(&package_map, pkgname))
|| (mpr_only && !cache.available_mpr(&package_map, pkgname))
{
continue;
}
let pkg = package_map.get(pkgname).unwrap()[0];
for arg in &pkglist {
if pkg.pkgname.contains(arg.as_str()) {
matches.push(&pkg.pkgname);
}
match &pkg.pkgdesc {
Some(pkgdesc) => {
if pkgdesc.to_lowercase().contains(arg.as_str()) {
matches.push(&pkg.pkgname);
}
}
None => (),
}
}
}
matches.sort_unstable();
matches.dedup();
let matches_length = matches.len();
if matches_length == 0 {
message::info("No results.");
return;
}
matches.sort_by_key(|a| a.to_lowercase());
let matches_length = matches_length - 1;
let mut result = String::new();
for (index, pkg) in matches.iter().enumerate() {
result.push_str(&pkg_info(&package_map, pkg));
if index < matches_length {
result.push('\n');
}
}
print!("{}", result);
}
pub fn pkg_info(package_map: &HashMap<&String, Vec<&CachePackage>>, pkg_str: &String) -> String {
let mut result = String::new();
let packages = package_map.get(pkg_str).unwrap();
let mut sources: Vec<&str> = Vec::new();
let pkg;
if packages.len() == 2 {
sources.push("APT");
sources.push("MPR");
let apt_pkg;
let mpr_pkg;
match packages[0].source {
CachePackageSource::Apt => {
apt_pkg = packages[0];
mpr_pkg = packages[1];
}
_ => {
apt_pkg = packages[1];
mpr_pkg = packages[2];
}
};
if apt_pkg.is_installed.unwrap() && apt_pkg.version == mpr_pkg.version {
pkg = mpr_pkg;
} else if apt_pkg.is_installed.unwrap() {
pkg = apt_pkg;
} else {
pkg = mpr_pkg;
};
} else {
pkg = packages[0];
match pkg.source {
CachePackageSource::Apt => sources.push("APT"),
_ => sources.push("MPR"),
}
};
let mut sources_str = String::from("[");
for source in sources {
write!(sources_str, "{}, ", Colour::Fixed(63).paint(source)).unwrap();
}
sources_str.pop();
sources_str.pop();
sources_str.push(']');
writeln!(
result,
"{}/{} {}",
Colour::Fixed(214).paint(pkg.pkgname.as_str()),
pkg.version,
sources_str
)
.unwrap();
match &pkg.pkgdesc {
Some(pkgdesc) => {
writeln!(
result,
"{} {}",
Style::new().bold().paint("Description:"),
pkgdesc
)
.unwrap();
}
None => (),
}
match &pkg.maintainer {
Some(maintainer) => {
writeln!(
result,
"{} {}",
Style::new().bold().paint("Maintainer:"),
maintainer
)
.unwrap();
}
None => (),
}
match &pkg.num_votes {
Some(num_votes) => writeln!(
result,
"{} {}",
Style::new().bold().paint("Votes:"),
num_votes
)
.unwrap(),
None => (),
}
match &pkg.popularity {
Some(popularity) => writeln!(
result,
"{} {}",
Style::new().bold().paint("Popularity:"),
popularity
)
.unwrap(),
None => (),
}
if let CachePackageSource::Mpr = pkg.source {
match &pkg.ood {
Some(ood) => {
let dt = Utc.timestamp(*ood as i64, 0).format("%Y-%m-%d").to_string();
writeln!(
result,
"{} {}",
Style::new().bold().paint("Out of Date:"),
dt
)
.unwrap();
}
None => {
writeln!(result, "{} N/A", Style::new().bold().paint("Out of Date:")).unwrap();
}
}
}
result
}