Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added bold text to package and color to CVE only. #36

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/avg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use enums;

#[derive(Clone, Debug)]
pub struct AVG {
pub issues: Vec<String>,
pub issues: Vec<(String, enums::Severity)>,
pub fixed: Option<String>,
pub severity: enums::Severity,
pub status: enums::Status,
Expand Down
206 changes: 155 additions & 51 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,23 +145,29 @@ fn main() {

/// Converts a JSON to an `avg::AVG`
fn to_avg(data: &Value) -> avg::AVG {
let severity = data["severity"]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, this is the reason behind the issue I was describing before.

Here, we set the CVE severity to the severity of the AVG. Which isn't the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can see we don't have that information from the json. So the best option is to return to the start commit 04aa1f5 or close the pull request.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or print the AVG and color only that. But this is outside the scope of this pull request.

.as_str()
.expect("Value::as_str failed")
.to_string()
.parse::<enums::Severity>()
.expect("parse::<Severity> failed");
avg::AVG {
issues: data["issues"]
.as_array()
.expect("Value::as_array failed")
.iter()
.map(|s| s.as_str().expect("Value::as_str failed").to_string())
.map(|s| {
(
s.as_str().expect("Value::as_str failed").to_string(),
severity,
)
})
.collect(),
fixed: match data["fixed"].as_str() {
Some(s) => Some(s.to_string()),
None => None,
},
severity: data["severity"]
.as_str()
.expect("Value::as_str failed")
.to_string()
.parse::<enums::Severity>()
.expect("parse::<Severity> failed"),
severity: severity,
status: data["status"]
.as_str()
.expect("Value::as_str failed")
Expand Down Expand Up @@ -230,7 +236,10 @@ fn test_system_is_affected() {
let db = pacman.localdb();

let avg1 = avg::AVG {
issues: vec!["CVE-1".to_string(), "CVE-2".to_string()],
issues: vec![
("CVE-1".to_string(), enums::Severity::Unknown),
("CVE-2".to_string(), enums::Severity::Unknown),
],
fixed: Some("1.0.0".to_string()),
severity: enums::Severity::Unknown,
status: enums::Status::Unknown,
Expand All @@ -239,7 +248,10 @@ fn test_system_is_affected() {
assert_eq!(false, system_is_affected(&db, &"pacman".to_string(), &avg1));

let avg2 = avg::AVG {
issues: vec!["CVE-1".to_string(), "CVE-2".to_string()],
issues: vec![
("CVE-1".to_string(), enums::Severity::Unknown),
("CVE-2".to_string(), enums::Severity::Unknown),
],
fixed: Some("7.0.0".to_string()),
severity: enums::Severity::Unknown,
status: enums::Status::Unknown,
Expand Down Expand Up @@ -324,14 +336,20 @@ fn test_merge_avgs() {
let mut avgs: BTreeMap<String, Vec<_>> = BTreeMap::new();

let avg1 = avg::AVG {
issues: vec!["CVE-1".to_string(), "CVE-2".to_string()],
issues: vec![
("CVE-1".to_string(), enums::Severity::Unknown),
("CVE-2".to_string(), enums::Severity::Unknown),
],
fixed: Some("1.0.0".to_string()),
severity: enums::Severity::Unknown,
status: enums::Status::Fixed,
};

let avg2 = avg::AVG {
issues: vec!["CVE-4".to_string(), "CVE-10".to_string()],
joshuachp marked this conversation as resolved.
Show resolved Hide resolved
issues: vec![
("CVE-4".to_string(), enums::Severity::Unknown),
("CVE-10".to_string(), enums::Severity::Unknown),
],
fixed: Some("0.9.8".to_string()),
severity: enums::Severity::High,
status: enums::Status::Testing,
Expand Down Expand Up @@ -373,42 +391,53 @@ fn test_merge_avgs() {
/// Print a list of `avg::AVG`
fn print_avgs(options: &Options, avgs: &BTreeMap<String, avg::AVG>) {
let mut t = term::stdout().expect("term::stdout failed");

for (pkg, avg) in avgs {
t.fg(avg.severity.to_color()).expect("term::fg failed");

match avg.fixed {
Some(ref v) if avg.status != enums::Status::Vulnerable => {
if options.quiet >= 2 {
writeln!(t, "{}", pkg).expect("term::writeln failed");
} else if options.quiet == 1 {
writeln!(t, "{}>={}", pkg, v).expect("term::writeln failed");
// Quiet option
if options.quiet != 0 {
t.fg(avg.severity.to_color()).expect("term::fg failed");
if options.quiet >= 2 {
writeln!(t, "{}", pkg).expect("term::writeln failed");
} else if options.quiet == 1 {
writeln!(t, "{}>={}", pkg, v).expect("term::writeln failed");
}
t.reset().expect("term::stdout failed");
} else {
t.fg(term::color::RED).expect("term::color::RED failed");
match options.format {
Some(ref f) => writeln!(
t,
"{}",
f.replace("%n", pkg.as_str())
.replace("%c", avg.issues.iter().join(",").as_str(),)
)
.expect("term::writeln failed"),
Some(ref f) => {
t.fg(term::color::RED).expect("term::color::RED failed");
writeln!(
t,
"{}",
f.replace("%n", pkg.as_str()).replace(
"%c",
avg.issues.iter().map(|issue| &issue.0).join(",").as_str(),
)
)
.expect("term::writeln failed");
t.reset().expect("term::stdout failed");
}
None => {
let msg = format!(
"Package {} is affected by {}. {}!",
pkg,
avg.issues.join(", "),
avg.severity
);

print_avg_colored(&mut t, pkg, avg);
// Colored update
if avg.status == enums::Status::Testing {
writeln!(t, "{} Update to {} from the testing repos!", msg, v)
.expect("term::writeln failed")
// Print: Update to {} for testing repos!"
write!(t, " Update to").expect("term::write failed");
t.attr(term::Attr::Bold).expect("term::attr failed");
t.fg(term::color::GREEN).expect("term::fg failed");
write!(t, " {}", v).expect("term::write failed");
t.reset().expect("term::stdout failed");
writeln!(t, " from the testing repos!")
.expect("term::writeln failed");
} else if avg.status == enums::Status::Fixed {
writeln!(t, "{} Update to {}!", msg, v)
.expect("term::writeln failed")
} else {
writeln!(t, "{}", msg).expect("term::writeln failed")
// Print: Update to {}!
write!(t, " Update to").expect("term::write failed");
t.attr(term::Attr::Bold).expect("term::attr failed");
t.fg(term::color::GREEN).expect("term::fg failed");
write!(t, " {}", v).expect("term::write failed");
t.reset().expect("term::stdout failed");
writeln!(t, "!").expect("term::write failed");
}
}
}
Expand All @@ -417,21 +446,27 @@ fn print_avgs(options: &Options, avgs: &BTreeMap<String, avg::AVG>) {
_ => {
if !options.upgradable_only {
if options.quiet > 0 {
println!("{}", pkg);
t.fg(avg.severity.to_color()).expect("term::fg failed");
writeln!(t, "{}", pkg).expect("term::writeln failed");
t.reset().expect("term::stdout failed");
} else {
match options.format {
Some(ref f) => println!(
"{}",
f.replace("%n", pkg.as_str())
.replace("%c", avg.issues.iter().join(",").as_str(),)
),
Some(ref f) => {
t.fg(avg.severity.to_color()).expect("term::fg failed");
writeln!(
t,
"{}",
f.replace("%n", pkg.as_str()).replace(
"%c",
avg.issues.iter().map(|issue| &issue.0).join(",").as_str(),
joshuachp marked this conversation as resolved.
Show resolved Hide resolved
)
)
.expect("term::writeln failed");
t.reset().expect("term::stdout failed");
}
None => {
println!(
"Package {} is affected by {}. {}!",
pkg,
avg.issues.join(", "),
avg.severity
);
print_avg_colored(&mut t, pkg, avg);
writeln!(t).expect("term::writeln failed");
}
}
}
Expand All @@ -440,3 +475,72 @@ fn print_avgs(options: &Options, avgs: &BTreeMap<String, avg::AVG>) {
}
}
}

/// Prints "Package {pkg} is affected by {issues}. {severity}." colored
fn print_avg_colored(t: &mut Box<term::StdoutTerminal>, pkg: &String, avg: &avg::AVG) {
t.reset().expect("term::stdout failed");
// Bold package
write!(t, "Package").expect("term::write failed");
t.attr(term::Attr::Bold).expect("term::attr failed");
write!(t, " {}", pkg).expect("term::writeln failed");
// Normal "is affected by"
t.reset().expect("term::stdout failed");
write!(t, " is affected by").expect("term::write failed");
// Colored issues
if let Some((first, elements)) = avg.issues.split_first() {
t.fg(first.1.to_color()).expect("term::fg failed");
write!(t, " {}", first.0).expect("term::write failed");
t.reset().expect("term::stdout failed");
for issue in elements {
write!(t, ",").expect("term::write failed");
t.fg(issue.1.to_color()).expect("term::fg failed");
write!(t, " {}", issue.0).expect("term::write failed");
t.reset().expect("term::stdout failed");
}
}
write!(t, ".").expect("term::write failed");
// Colored severity
t.fg(avg.severity.to_color()).expect("term::fg failed");
write!(t, " {}.", avg.severity).expect("term::write failed");
t.reset().expect("term::stdout failed");
}

#[test]
fn test_print_avgs() {
let mut avgs: BTreeMap<String, Vec<_>> = BTreeMap::new();

let avg1 = avg::AVG {
issues: vec![
("CVE-1".to_string(), enums::Severity::Unknown),
("CVE-2".to_string(), enums::Severity::Low),
("CVE-3".to_string(), enums::Severity::Medium),
],
fixed: Some("1.0.0".to_string()),
severity: enums::Severity::Unknown,
status: enums::Status::Fixed,
};

let avg2 = avg::AVG {
issues: vec![
("CVE-4".to_string(), enums::Severity::High),
("CVE-5".to_string(), enums::Severity::Critical),
],
fixed: Some("0.9.8".to_string()),
severity: enums::Severity::High,
status: enums::Status::Testing,
};

avgs.insert("package".to_string(), vec![avg1.clone(), avg2.clone()]);

avgs.insert("package2".to_string(), vec![avg1, avg2]);

let merged = merge_avgs(&avgs);

let options = Options {
format: None,
quiet: 0,
upgradable_only: false,
};

print_avgs(&options, &merged);
}