use console::style;
use crate::model::{AuditResult, CheckResult, CheckStatus, CommandResult, UpdateResult};
use super::format::{format_columns, severity_style, truncate_middle_pad};
pub(crate) trait OutputLine: CommandResult {
fn version_value(&self) -> String;
fn print_line(&self);
}
impl OutputLine for CheckResult {
fn version_value(&self) -> String {
self.current_version.clone()
}
fn print_line(&self) {
let (styled_artifact, version, source) = format_columns(self);
match &self.status {
CheckStatus::UpToDate { .. } => {
println!(
" {} {} {} {} {}",
style("\u{2713}").green().bold(),
styled_artifact,
style(version).white(),
style(source).dim(),
style("up-to-date").green()
);
}
CheckStatus::Outdated { latest } => {
println!(
" {} {} {} {} {}",
style("\u{2192}").yellow().bold(),
styled_artifact,
style(version).white(),
style(source).dim(),
style(format!("\u{2192} {latest}")).yellow()
);
}
CheckStatus::Skipped => {
println!(
" {} {} {} {} {}",
style("-").dim().bold(),
styled_artifact,
style(version).dim(),
style(source).dim(),
style("skipped").dim()
);
}
CheckStatus::Error { message } => {
println!(
" {} {} {} {} {}",
style("\u{2717}").red().bold(),
styled_artifact,
style(version).white(),
style(source).dim(),
style(message).red()
);
}
}
}
}
impl OutputLine for UpdateResult {
fn version_value(&self) -> String {
format!("{} \u{2192} {}", self.old_version, self.new_version)
}
fn print_line(&self) {
let (styled_artifact, version, source) = format_columns(self);
match &self.status {
crate::model::UpdateStatus::Updated => {
println!(
" {} {} {} {} {}",
style("\u{2713}").green().bold(),
styled_artifact,
style(version).white(),
style(source).dim(),
style("updated").green()
);
}
crate::model::UpdateStatus::Error { message } => {
println!(
" {} {} {} {} {}",
style("\u{2717}").red().bold(),
styled_artifact,
style(version).white(),
style(source).dim(),
style(message).red()
);
}
}
}
}
impl OutputLine for AuditResult {
fn version_value(&self) -> String {
self.version.clone()
}
fn print_line(&self) {
let (styled_artifact, version, source) = format_columns(self);
if self.vulnerabilities.is_empty() {
println!(
" {} {} {} {} {}",
style("\u{2713}").green().bold(),
styled_artifact,
style(version).white(),
style(source).dim(),
style("no vulnerabilities").green()
);
} else {
let count = self.vulnerabilities.len();
let max_sev = self.max_severity();
let label = if count == 1 {
"vulnerability"
} else {
"vulnerabilities"
};
println!(
" {} {} {} {} {}",
style("\u{2717}").red().bold(),
styled_artifact,
style(version).white(),
style(source).dim(),
severity_style(max_sev).apply_to(format!("{count} {label}")),
);
for vuln in &self.vulnerabilities {
let id_and_aliases = if vuln.aliases.is_empty() {
vuln.id.clone()
} else {
format!("{} ({})", vuln.id, vuln.aliases.join(", "))
};
let summary = if vuln.summary.is_empty() {
String::new()
} else {
let truncated = truncate_middle_pad(&vuln.summary, 60);
format!(" {truncated}")
};
println!(
" {} {}{}",
severity_style(vuln.severity).apply_to(format!("[{}]", vuln.severity)),
style(id_and_aliases).dim(),
style(summary).dim(),
);
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::model::{Dependency, DependencyKind, Ecosystem};
#[test]
fn version_value_check() {
let r = CheckResult::checked(
Dependency::new(
Ecosystem::Maven,
DependencyKind::Dependency,
"g:a".into(),
Some("version.junit".into()),
String::new(),
),
"5.10.0".into(),
"5.12.0".into(),
true,
);
assert_eq!(r.version_value(), "5.10.0");
}
#[test]
fn version_value_update() {
let check = CheckResult::checked(
Dependency::new(
Ecosystem::Maven,
DependencyKind::Dependency,
"g:a".into(),
Some("version.junit".into()),
String::new(),
),
"5.10.0".into(),
"5.12.0".into(),
true,
);
let update = UpdateResult::updated(&check, "5.12.0".into());
assert_eq!(update.version_value(), "5.10.0 \u{2192} 5.12.0");
}
#[test]
fn version_value_audit() {
let r = AuditResult {
dep: Dependency::new(
Ecosystem::Maven,
DependencyKind::Dependency,
"g:a".into(),
Some("version.junit".into()),
String::new(),
),
version: "5.10.0".into(),
vulnerabilities: Vec::new(),
};
assert_eq!(r.version_value(), "5.10.0");
}
}