1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
use crate::config::Config; use crate::errors::RunError; use crate::traces::{CoverageStat, TraceMap}; use coveralls_api::*; use log::{info, trace, warn}; use std::collections::HashMap; use std::fs; use std::path::Path; fn get_git_info(manifest_path: &Path) -> Result<GitInfo, String> { let dir_path = manifest_path .parent() .ok_or_else(|| format!("failed to get parent for path: {}", manifest_path.display()))?; let repo = git2::Repository::discover(dir_path).map_err(|err| { format!( "failed to open git repository: {}: {}", dir_path.display(), err ) })?; let head = repo .head() .map_err(|err| format!("failed to get repository head: {}", err))?; let branch = git2::Branch::wrap(head); let branch_name = branch .name() .map_err(|err| format!("failed to get branch name: {}", err))?; let get_string = |data: Option<&str>| match data { Some(str) => Ok(str.to_string()), None => Err("string is not valid utf-8".to_string()), }; let branch_name = get_string(branch_name)?; let commit = repo .head() .unwrap() .peel_to_commit() .map_err(|err| format!("failed to get commit: {}", err))?; let author = commit.author(); let committer = commit.committer(); Ok(GitInfo { head: Head { id: commit.id().to_string(), author_name: get_string(author.name())?, author_email: get_string(author.email())?, committer_name: get_string(committer.name())?, committer_email: get_string(committer.email())?, message: get_string(commit.message())?, }, branch: branch_name, remotes: Vec::new(), }) } fn get_identity(ci_tool: &Option<CiService>, key: &str) -> Identity { match ci_tool { Some(ref service) => { let service_object = match Service::from_ci(service.clone()) { Some(s) => s, None => Service { name: service.clone(), job_id: Some(key.to_string()), number: None, build_url: None, branch: None, pull_request: None, }, }; let key = if service == &CiService::Travis { String::new() } else { key.to_string() }; Identity::ServiceToken(key, service_object) } _ => Identity::best_match_with_token(key.to_string()), } } pub fn export(coverage_data: &TraceMap, config: &Config) -> Result<(), RunError> { if let Some(ref key) = config.coveralls { let id = get_identity(&config.ci_tool, key); let mut report = CoverallsReport::new(id); for file in &coverage_data.files() { let rel_path = config.strip_base_dir(file); let mut lines: HashMap<usize, usize> = HashMap::new(); let fcov = coverage_data.get_child_traces(file); for c in &fcov { match c.stats { CoverageStat::Line(hits) => { lines.insert(c.line as usize, hits as usize); } _ => { info!("Support for coverage statistic not implemented or supported for coveralls.io"); } } } if let Ok(source) = Source::new(&rel_path, file, &lines, &None, false) { report.add_source(source); } } match get_git_info(&config.manifest) { Ok(git_info) => { report.set_detailed_git_info(git_info); info!("Git info collected"); } Err(err) => warn!("Failed to collect git info: {}", err), } let res = match config.report_uri { Some(ref uri) => { info!("Sending report to endpoint: {}", uri); report.send_to_endpoint(uri) } None => { info!("Sending coverage data to coveralls.io"); report.send_to_coveralls() } }; if config.debug { if let Ok(text) = serde_json::to_string(&report) { info!("Attempting to write coveralls report to coveralls.json"); let file_path = config.output_directory.join("coveralls.json"); let _ = fs::write(file_path, text); } else { warn!("Failed to serialise coverage report"); } } match res { Ok(s) => { trace!("Coveralls response {:?}", s); Ok(()) } Err(e) => Err(RunError::CovReport(format!("Coveralls send failed. {}", e))), } } else { Err(RunError::CovReport( "No coveralls key specified.".to_string(), )) } }