From b4671eee293da1d1d9337fa1f387a14e22d8b400 Mon Sep 17 00:00:00 2001 From: Ningyuan Li Date: Sat, 10 Jun 2023 22:43:04 +0900 Subject: [PATCH] refactoring --- Cargo.lock | 6 ++- ipk-verify/Cargo.toml | 2 + ipk-verify/src/main.rs | 92 +++++++++++++++------------------------- ipk-verify/src/output.rs | 69 ++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 59 deletions(-) create mode 100644 ipk-verify/src/output.rs diff --git a/Cargo.lock b/Cargo.lock index b9e3e51..0f163f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -422,9 +422,9 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi", "libc", @@ -438,12 +438,14 @@ dependencies = [ "clap", "common", "debpkg", + "is-terminal", "path-slash", "prettytable-rs", "semver", "serde", "serde_json", "tempfile", + "term", ] [[package]] diff --git a/ipk-verify/Cargo.toml b/ipk-verify/Cargo.toml index f42dcc7..372651a 100644 --- a/ipk-verify/Cargo.toml +++ b/ipk-verify/Cargo.toml @@ -13,6 +13,8 @@ tempfile = "3.5.0" path-slash = "0.2.1" prettytable-rs = "^0.10" semver = "1.0.17" +is-terminal = "0.4.7" +term = "0.7.0" [dependencies.clap] version = "4.2.4" diff --git a/ipk-verify/src/main.rs b/ipk-verify/src/main.rs index 035f44b..31ff347 100644 --- a/ipk-verify/src/main.rs +++ b/ipk-verify/src/main.rs @@ -5,8 +5,8 @@ use std::iter; use std::path::PathBuf; use clap::Parser; -use prettytable::format::{FormatBuilder, LinePosition, LineSeparator}; -use prettytable::{color, Attr, Cell, Row, Table}; +use is_terminal::IsTerminal; +use prettytable::{Cell, Row, Table}; use semver::VersionReq; use serde::Deserialize; @@ -14,8 +14,11 @@ use common::{ BinVerifyResult, BinaryInfo, Firmware, LibraryInfo, VerifyResult, VerifyWithFirmware, }; +use crate::output::ReportOutput; + mod component; mod links; +mod output; mod package; #[derive(Parser, Debug)] @@ -24,8 +27,8 @@ struct Args { packages: Vec, #[arg(short, long)] output: Option, - #[arg(short, long, value_enum, default_value = "plain")] - format: OutputFormat, + #[arg(short, long, value_enum)] + format: Option, #[arg(long)] fw_releases: Option, #[arg(short, long, action = clap::ArgAction::Count)] @@ -39,13 +42,26 @@ enum OutputFormat { Plain, } +impl Args { + fn report_output(&self) -> Box { + return if let Some(path) = &self.output { + Box::new(File::create(path).unwrap()) + } else { + Box::new(std::io::stdout()) + }; + } +} + fn main() { let args = Args::parse(); let to_file: bool = args.output.is_some(); - let mut output: Box = if let Some(path) = args.output { - Box::new(File::create(path).unwrap()) + let mut output = args.report_output(); + let format = if let Some(format) = args.format { + format + } else if std::io::stdout().is_terminal() { + OutputFormat::Terminal } else { - Box::new(std::io::stdout()) + OutputFormat::Plain }; let firmwares: Vec = Firmware::list(Firmware::data_path()) .unwrap() @@ -94,7 +110,7 @@ fn main() { print_component_results( results.iter().map(|(fw, res)| (*fw, &res.app)).collect(), &mut output, - &args.format, + &format, ) .unwrap(); for idx in 0..result.services.len() { @@ -113,53 +129,22 @@ fn main() { .map(|(fw, res)| (*fw, res.services.get(idx).unwrap())) .collect(), &mut output, - &args.format, + &format, ) .unwrap(); } } } -fn print_component_results( +fn print_component_results( results: Vec<(&Firmware, &ComponentVerifyResult)>, - out: &mut Output, + out: &mut Box, out_fmt: &OutputFormat, -) -> Result<(), Error> -where - Output: Write + ?Sized, -{ +) -> Result<(), Error> { let (_, result) = *results.first().unwrap(); - fn result_cell(result: &BinVerifyResult) -> Cell { - return if result.is_good() { - let mut cell = Cell::new("OK"); - cell.style(Attr::ForegroundColor(color::BRIGHT_GREEN)); - cell - } else { - let mut cell = Cell::new("NG"); - cell.style(Attr::ForegroundColor(color::BRIGHT_RED)); - cell - }; - } if let Some(exe) = &result.exe { let mut table = Table::new(); - match out_fmt { - OutputFormat::Markdown => { - table.set_format( - FormatBuilder::new() - .column_separator('|') - .borders('|') - .padding(1, 1) - .separator(LinePosition::Title, LineSeparator::new('-', '|', '|', '|')) - .build(), - ); - } - OutputFormat::Terminal => { - table.set_format(*prettytable::format::consts::FORMAT_BOX_CHARS); - } - OutputFormat::Plain => { - table.set_format(*prettytable::format::consts::FORMAT_DEFAULT); - } - } + table.set_format(out.table_format(out_fmt)); table.set_titles(Row::from_iter( iter::once(String::new()).chain( results @@ -172,7 +157,7 @@ where .chain( results .iter() - .map(|(_, result)| result_cell(result.exe.as_ref().unwrap())), + .map(|(_, result)| out.result_cell(result.exe.as_ref().unwrap(), out_fmt)), ) .collect(), )); @@ -184,22 +169,15 @@ where }; table.add_row(Row::new( iter::once(name) - .chain( - results - .iter() - .map(|(_, result)| result_cell(&result.libs.get(idx).unwrap().1)), - ) + .chain(results.iter().map(|(_, result)| { + out.result_cell(&result.libs.get(idx).unwrap().1, out_fmt) + })) .collect(), )); } - if *out_fmt == OutputFormat::Terminal { - table.print_tty(true)?; - } else { - table.print(out)?; - } - out.write_all(b"\n")?; + out.print_table(&table)?; } else { - println!("Skip because this component is not native"); + out.write_fmt(format_args!("Skip because this component is not native\n"))?; } return Ok(()); } diff --git a/ipk-verify/src/output.rs b/ipk-verify/src/output.rs new file mode 100644 index 0000000..7502fde --- /dev/null +++ b/ipk-verify/src/output.rs @@ -0,0 +1,69 @@ +use std::fs::File; +use std::io::{Error, Stdout, Write}; + +use crate::OutputFormat; +use common::{BinVerifyResult, VerifyResult}; +use prettytable::format::{FormatBuilder, LinePosition, LineSeparator, TableFormat}; +use prettytable::{Cell, Table}; +use term::{color, Attr}; + +pub trait PrintTable { + fn result_cell(&self, result: &BinVerifyResult, out_fmt: &OutputFormat) -> Cell { + return if result.is_good() { + let mut cell = Cell::new(if *out_fmt == OutputFormat::Markdown { + ":ok:" + } else { + "OK" + }); + cell.style(Attr::ForegroundColor(color::BRIGHT_GREEN)); + cell + } else { + let mut cell = Cell::new(if *out_fmt == OutputFormat::Markdown { + ":x:" + } else { + "FAIL" + }); + cell.style(Attr::ForegroundColor(color::BRIGHT_RED)); + cell + }; + } + + fn table_format(&self, out_fmt: &OutputFormat) -> TableFormat { + match out_fmt { + OutputFormat::Markdown => FormatBuilder::new() + .column_separator('|') + .borders('|') + .padding(1, 1) + .separator(LinePosition::Title, LineSeparator::new('-', '|', '|', '|')) + .build(), + OutputFormat::Terminal => *prettytable::format::consts::FORMAT_BOX_CHARS, + OutputFormat::Plain => *prettytable::format::consts::FORMAT_DEFAULT, + } + } + + fn print_table(&mut self, table: &Table) -> Result<(), Error>; + + fn print_details(&mut self, ); +} + +pub trait ReportOutput: PrintTable + Write {} + +impl PrintTable for Stdout { + fn print_table(&mut self, table: &Table) -> Result<(), Error> { + table.print_tty(false)?; + println!("\n"); + return Ok(()); + } +} + +impl PrintTable for File { + fn print_table(&mut self, table: &Table) -> Result<(), Error> { + table.print(self)?; + self.write_all(b"\n")?; + return Ok(()); + } +} + +impl ReportOutput for Stdout {} + +impl ReportOutput for File {}