From 07fe36bb2b95a7bc17ae4e9c1591d10f0f40732e Mon Sep 17 00:00:00 2001 From: Bastian Schubert Date: Wed, 28 Sep 2022 09:14:18 +0200 Subject: [PATCH] [#496 multiple outputs] --- src/cobertura.rs | 25 +++++---- src/defs.rs | 1 - src/main.rs | 121 +++++++++++++++++++++--------------------- src/output.rs | 34 +++++++----- src/path_rewriting.rs | 8 +-- 5 files changed, 97 insertions(+), 92 deletions(-) diff --git a/src/cobertura.rs b/src/cobertura.rs index 6b7ba1a86..d838506ab 100644 --- a/src/cobertura.rs +++ b/src/cobertura.rs @@ -3,14 +3,16 @@ use quick_xml::{ Writer, }; use rustc_hash::FxHashMap; -use std::io::{BufWriter, Cursor, Write}; use std::path::Path; use std::time::{SystemTime, UNIX_EPOCH}; +use std::{ + io::{BufWriter, Cursor, Write}, + path::PathBuf, +}; use symbolic_common::Name; use symbolic_demangle::{Demangle, DemangleOptions}; -use crate::defs::CovResultIter; -use crate::output::get_target_output_writable; +use crate::{output::get_target_output_writable, CovResult}; macro_rules! demangle { ($name: expr, $demangle: expr, $options: expr) => {{ @@ -229,12 +231,13 @@ impl ToString for ConditionType { } fn get_coverage( - results: CovResultIter, + results: &[(PathBuf, PathBuf, CovResult)], sources: Vec, demangle: bool, demangle_options: DemangleOptions, ) -> Coverage { let packages: Vec = results + .iter() .map(|(_, rel_path, result)| { let all_lines: Vec = result.lines.iter().map(|(k, _)| k).cloned().collect(); @@ -246,13 +249,12 @@ fn get_coverage( } start_indexes.sort_unstable(); - let functions = result.functions; - let result_lines = result.lines; - let result_branches = result.branches; + // let result_lines = result.lines.clone(); + // let result_branches = result.branches.clone(); let line_from_number = |number| { - let hits = result_lines.get(&number).cloned().unwrap_or_default(); - if let Some(branches) = result_branches.get(&number) { + let hits = result.lines.get(&number).cloned().unwrap_or_default(); + if let Some(branches) = result.branches.get(&number) { let conditions = branches .iter() .enumerate() @@ -272,7 +274,8 @@ fn get_coverage( } }; - let methods: Vec = functions + let methods: Vec = result + .functions .iter() .map(|(name, function)| { let mut func_end = end; @@ -329,7 +332,7 @@ fn get_coverage( pub fn output_cobertura( source_dir: Option<&Path>, - results: CovResultIter, + results: &[(PathBuf, PathBuf, CovResult)], output_file: Option<&Path>, demangle: bool, ) { diff --git a/src/defs.rs b/src/defs.rs index 842d4fbf1..1fd27296d 100644 --- a/src/defs.rs +++ b/src/defs.rs @@ -58,7 +58,6 @@ pub type JobSender = Sender>; pub type CovResultMap = FxHashMap; pub type SyncCovResultMap = Mutex; -pub type CovResultIter = Box>; #[derive(Debug, Default)] pub struct CDStats { diff --git a/src/main.rs b/src/main.rs index 36b82a429..2e34f36c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -87,7 +87,7 @@ struct Opt { short = "t", long, long_help = "\ - Sets a custom output type:\n\ + Comma separated list of custom output types:\n\ - *html* for a HTML coverage report;\n\ - *coveralls* for the Coveralls specific format;\n\ - *lcov* for the lcov INFO format;\n\ @@ -96,6 +96,7 @@ struct Opt { - *ade* for the ActiveData-ETL specific format;\n\ - *files* to only return a list of files.\n\ - *markdown* for human easy read.\n\ + - *cobertura* for output in coberura format.\n\ ", value_name = "OUTPUT TYPE", default_value = "lcov", @@ -103,19 +104,10 @@ struct Opt { ("coveralls", "coveralls-auth"), ("coveralls+", "coveralls-auth"), ], - possible_values = &[ - "ade", - "lcov", - "coveralls", - "coveralls+", - "files", - "covdir", - "html", - "cobertura", - "markdown", - ], + + use_delimiter = true )] - output_type: OutputType, + output_types: Vec, /// Specifies the output path. #[structopt(short, long, value_name = "PATH", alias = "output-file")] output_path: Option, @@ -422,52 +414,59 @@ fn main() { file_filter, ); - match opt.output_type { - OutputType::Ade => output_activedata_etl(iterator, opt.output_path.as_deref(), demangle), - OutputType::Lcov => output_lcov(iterator, opt.output_path.as_deref(), demangle), - OutputType::Coveralls => output_coveralls( - iterator, - opt.token.as_deref(), - opt.service_name.as_deref(), - &opt.service_number.unwrap_or_default(), - opt.service_job_id.as_deref(), - &opt.service_pull_request.unwrap_or_default(), - &opt.commit_sha.unwrap_or_default(), - false, - opt.output_path.as_deref(), - &opt.vcs_branch, - opt.parallel, - demangle, - ), - OutputType::CoverallsPlus => output_coveralls( - iterator, - opt.token.as_deref(), - opt.service_name.as_deref(), - &opt.service_number.unwrap_or_default(), - opt.service_job_id.as_deref(), - &opt.service_pull_request.unwrap_or_default(), - &opt.commit_sha.unwrap_or_default(), - true, - opt.output_path.as_deref(), - &opt.vcs_branch, - opt.parallel, - demangle, - ), - OutputType::Files => output_files(iterator, opt.output_path.as_deref()), - OutputType::Covdir => output_covdir(iterator, opt.output_path.as_deref()), - OutputType::Html => output_html( - iterator, - opt.output_path.as_deref(), - num_threads, - opt.branch, - opt.output_config_file.as_deref(), - ), - OutputType::Cobertura => output_cobertura( - source_root.as_deref(), - iterator, - opt.output_path.as_deref(), - demangle, - ), - OutputType::Markdown => output_markdown(iterator, opt.output_path.as_deref()), - }; + let service_number = opt.service_number.unwrap_or_default(); + let service_pull_request = opt.service_pull_request.unwrap_or_default(); + let commit_sha = opt.commit_sha.unwrap_or_default(); + for output_type in &opt.output_types { + match output_type { + OutputType::Ade => { + output_activedata_etl(&iterator, opt.output_path.as_deref(), demangle) + } + OutputType::Lcov => output_lcov(&iterator, opt.output_path.as_deref(), demangle), + OutputType::Coveralls => output_coveralls( + &iterator, + opt.token.as_deref(), + opt.service_name.as_deref(), + &service_number, + opt.service_job_id.as_deref(), + &service_pull_request, + &commit_sha, + false, + opt.output_path.as_deref(), + &opt.vcs_branch, + opt.parallel, + demangle, + ), + OutputType::CoverallsPlus => output_coveralls( + &iterator, + opt.token.as_deref(), + opt.service_name.as_deref(), + &service_number, + opt.service_job_id.as_deref(), + &service_pull_request, + &commit_sha, + true, + opt.output_path.as_deref(), + &opt.vcs_branch, + opt.parallel, + demangle, + ), + OutputType::Files => output_files(&iterator, opt.output_path.as_deref()), + OutputType::Covdir => output_covdir(&iterator, opt.output_path.as_deref()), + OutputType::Html => output_html( + &iterator, + opt.output_path.as_deref(), + num_threads, + opt.branch, + opt.output_config_file.as_deref(), + ), + OutputType::Cobertura => output_cobertura( + source_root.as_deref(), + &iterator, + opt.output_path.as_deref(), + demangle, + ), + OutputType::Markdown => output_markdown(&iterator, opt.output_path.as_deref()), + }; + } } diff --git a/src/output.rs b/src/output.rs index 94d52cbce..57a875acc 100644 --- a/src/output.rs +++ b/src/output.rs @@ -70,7 +70,11 @@ pub fn get_target_output_writable(output_file: Option<&Path>) -> Box write_target } -pub fn output_activedata_etl(results: CovResultIter, output_file: Option<&Path>, demangle: bool) { +pub fn output_activedata_etl( + results: &[(PathBuf, PathBuf, CovResult)], + output_file: Option<&Path>, + demangle: bool, +) { let demangle_options = DemangleOptions::name_only(); let mut writer = BufWriter::new(get_target_output_writable(output_file)); @@ -180,7 +184,7 @@ pub fn output_activedata_etl(results: CovResultIter, output_file: Option<&Path>, } } -pub fn output_covdir(results: CovResultIter, output_file: Option<&Path>) { +pub fn output_covdir(results: &[(PathBuf, PathBuf, CovResult)], output_file: Option<&Path>) { let mut writer = BufWriter::new(get_target_output_writable(output_file)); let mut relative: FxHashMap>> = FxHashMap::default(); let global = Rc::new(RefCell::new(CDDirStats::new("".to_string()))); @@ -226,7 +230,7 @@ pub fn output_covdir(results: CovResultIter, output_file: Option<&Path>) { prev_stats.borrow_mut().files.push(CDFileStats::new( path.file_name().unwrap().to_str().unwrap().to_string(), - result.lines, + result.lines.clone(), )); } @@ -236,7 +240,11 @@ pub fn output_covdir(results: CovResultIter, output_file: Option<&Path>) { serde_json::to_writer(&mut writer, &global.into_json()).unwrap(); } -pub fn output_lcov(results: CovResultIter, output_file: Option<&Path>, demangle: bool) { +pub fn output_lcov( + results: &[(PathBuf, PathBuf, CovResult)], + output_file: Option<&Path>, + demangle: bool, +) { let demangle_options = DemangleOptions::name_only(); let mut writer = BufWriter::new(get_target_output_writable(output_file)); writer.write_all(b"TN:\n").unwrap(); @@ -413,7 +421,7 @@ fn get_coveralls_git_info(commit_sha: &str, vcs_branch: &str) -> Value { } pub fn output_coveralls( - results: CovResultIter, + results: &[(PathBuf, PathBuf, CovResult)], repo_token: Option<&str>, service_name: Option<&str>, service_number: &str, @@ -455,7 +463,7 @@ pub fn output_coveralls( if !with_function_info { source_files.push(json!({ "name": rel_path, - "source_digest": get_digest(abs_path), + "source_digest": get_digest(abs_path.clone()), "coverage": coverage, "branches": branches, })); @@ -471,7 +479,7 @@ pub fn output_coveralls( source_files.push(json!({ "name": rel_path, - "source_digest": get_digest(abs_path), + "source_digest": get_digest(abs_path.clone()), "coverage": coverage, "branches": branches, "functions": functions, @@ -505,7 +513,7 @@ pub fn output_coveralls( serde_json::to_writer(&mut writer, &result).unwrap(); } -pub fn output_files(results: CovResultIter, output_file: Option<&Path>) { +pub fn output_files(results: &[(PathBuf, PathBuf, CovResult)], output_file: Option<&Path>) { let mut writer = BufWriter::new(get_target_output_writable(output_file)); for (_, rel_path, _) in results { writeln!(writer, "{}", rel_path.display()).unwrap(); @@ -513,7 +521,7 @@ pub fn output_files(results: CovResultIter, output_file: Option<&Path>) { } pub fn output_html( - results: CovResultIter, + results: &[(PathBuf, PathBuf, CovResult)], output_dir: Option<&Path>, num_threads: usize, branch_enabled: bool, @@ -559,9 +567,9 @@ pub fn output_html( for (abs_path, rel_path, result) in results { sender .send(Some(HtmlItem { - abs_path, - rel_path, - result, + abs_path: abs_path.to_path_buf(), + rel_path: rel_path.to_path_buf(), + result: result.clone(), })) .unwrap(); } @@ -587,7 +595,7 @@ pub fn output_html( html::gen_coverage_json(&global.stats, &config, &output); } -pub fn output_markdown(results: CovResultIter, output_file: Option<&Path>) { +pub fn output_markdown(results: &[(PathBuf, PathBuf, CovResult)], output_file: Option<&Path>) { #[derive(Tabled)] struct LineSummary { file: String, diff --git a/src/path_rewriting.rs b/src/path_rewriting.rs index 73468c95f..7f9b9b770 100644 --- a/src/path_rewriting.rs +++ b/src/path_rewriting.rs @@ -235,7 +235,7 @@ pub fn rewrite_paths( to_keep_dirs: &[impl AsRef], filter_option: Option, file_filter: crate::FileFilter, -) -> CovResultIter { +) -> Vec<(PathBuf, PathBuf, CovResult)> { let to_ignore_globset = to_globset(to_ignore_dirs); let to_keep_globset = to_globset(to_keep_dirs); @@ -341,11 +341,7 @@ pub fn rewrite_paths( Some((abs_path, rel_path, result)) }); - Box::new( - results - .collect::>() - .into_iter(), - ) + results.collect() } #[cfg(test)]