use crate::checks::{RepoStatus, RuleId, RuleReport};
use crate::submodules::Entry;
pub fn print_default(entries: &[Entry]) {
for e in entries {
let middle = e.status.problem.as_deref().unwrap_or(&e.status.branch);
let (path, ok) = (e.path.display(), e.status.ok());
match e.status.base_sync.marker() {
Some(m) => println!("{path} {middle} {ok} {m}"),
None => println!("{path} {middle} {ok}"),
}
}
}
pub fn print_verbose(entries: &[Entry], reasons: bool) {
for e in entries {
let p = e.path.display().to_string();
let s = &e.status;
if let Some(reason) = &s.problem {
println!("{p}\tRESULT\t{reason}\tfalse");
continue;
}
emit_check(&p, s, RuleId::Committed, reasons);
emit_check(&p, s, RuleId::AllCommitsPushed, reasons);
emit_check(&p, s, RuleId::BranchesHaveRemote, reasons);
emit_check(&p, s, RuleId::NotBehindRemote, reasons);
if reasons {
println!("{p}\tbase-branch\t{}", s.base.describe());
println!("{p}\tbranch-rule\t{}", s.rule.describe());
}
emit_check(&p, s, RuleId::CorrectBranch, reasons);
emit_check(&p, s, RuleId::NotBehindBase, reasons);
match s.base_sync.marker() {
Some(m) => println!("{p}\tRESULT\t{}\t{}\t{m}", s.branch, s.ok()),
None => println!("{p}\tRESULT\t{}\t{}", s.branch, s.ok()),
}
}
}
fn emit_check(p: &str, s: &RepoStatus, rule: RuleId, reasons: bool) {
let passed = s.rule_passed(rule);
if reasons {
println!("{p}\t{} {}\t{}", rule.tag(), rule.key(), passed);
if let Some(why) = s.failure_reason(rule) {
println!("{p}\t{} reason\t{why}", rule.tag());
}
} else {
println!("{p}\t{}\t{}", rule.key(), passed);
}
}
pub fn print_rules() {
for r in RuleId::ALL {
println!("{}\t{}\t{}", r.tag(), r.key(), r.description());
}
}
pub fn print_rule_detail(r: &RuleReport) {
let status = if r.passed { "PASS" } else { "FAIL" };
println!("{} {} [this repo: {status}]", r.id.tag(), r.id.key());
println!("\n What it checks");
for line in wrap(r.id.description(), 72) {
println!(" {line}");
}
println!("\n This repo now");
let label_w = r
.facts
.iter()
.map(|(l, _)| l.len())
.chain(std::iter::once("verdict".len()))
.max()
.unwrap_or(0);
for (label, value) in &r.facts {
println!(" {label:<label_w$} {value}");
}
println!(" {:<label_w$} {}", "verdict", r.verdict);
println!("\n Examples");
let scen_w =
r.id.examples()
.iter()
.map(|(s, _)| s.len())
.max()
.unwrap_or(0);
for (scenario, outcome) in r.id.examples() {
println!(" {scenario:<scen_w$} {outcome}");
}
}
fn wrap(text: &str, width: usize) -> Vec<String> {
let mut out = Vec::new();
let mut line = String::new();
for word in text.split_whitespace() {
if !line.is_empty() && line.len() + 1 + word.len() > width {
out.push(std::mem::take(&mut line));
}
if !line.is_empty() {
line.push(' ');
}
line.push_str(word);
}
if !line.is_empty() {
out.push(line);
}
out
}
pub fn all_ok(entries: &[Entry]) -> bool {
entries.iter().all(|e| e.status.ok())
}