// Copyright 2016 Kitware, Inc.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use crates::git_workarea::CommitId;
use commit::Commit;
use context::CheckGitContext;
use error::Result;
#[derive(Debug, Default)]
/// The results of a check.
pub struct CheckResult {
/// The warnings from running checks.
warnings: Vec<String>,
/// The alerts from running checks.
///
/// These are meant to be directed towards administrators of the repository.
alerts: Vec<String>,
/// The errors from running checks.
///
/// Errors cause the checks to be in a "failed" state.
errors: Vec<String>,
/// Whether any messages may be temporary.
temporary: bool,
/// Whether errors should be ignored or not.
allow: bool,
/// Whether the checks succeeded or not.
pass: bool,
}
/// The severity of a message.
pub enum Severity {
/// The message is a warning.
Warning,
/// The message is an error.
Error,
/// The message should be brought to the attention of project maintainers.
Alert {
/// Whether the checks should fail due to the message or not.
blocking: bool,
},
}
impl CheckResult {
/// Create a new results structure.
pub fn new() -> Self {
CheckResult {
warnings: vec![],
alerts: vec![],
errors: vec![],
temporary: false,
allow: false,
pass: true,
}
}
/// Add a message to the result.
pub fn add_message<S>(&mut self, severity: Severity, message: S) -> &mut Self
where S: ToString,
{
match severity {
Severity::Warning => &mut self.warnings,
Severity::Error => {
self.pass = false;
&mut self.errors
},
Severity::Alert { blocking } => {
if blocking {
self.pass = false;
}
&mut self.alerts
},
}.push(message.to_string());
self
}
/// Adds a warning message to the results.
pub fn add_warning<S: ToString>(&mut self, warning: S) -> &mut Self {
self.add_message(Severity::Warning, warning.to_string())
}
/// Adds an alert to the results.
///
/// These messages should be brought to the attention of those maintaining the deployment of
/// the checks.
pub fn add_alert<S: ToString>(&mut self, alert: S, should_block: bool) -> &mut Self {
self.add_message(Severity::Alert { blocking: should_block }, alert.to_string())
}
/// Adds a error message to the results.
///
/// Also marks the checks as having failed.
pub fn add_error<S: ToString>(&mut self, error: S) -> &mut Self {
self.add_message(Severity::Error, error.to_string())
}
/// Indicates that there are messages which may be temporary.
pub fn make_temporary(&mut self) -> &mut Self {
self.temporary = true;
self
}
/// Allows the checks to pass no matter what.
pub fn whitelist(&mut self) -> &mut Self {
self.allow = true;
self
}
/// The warnings from the checks.
pub fn warnings(&self) -> &Vec<String> {
&self.warnings
}
/// The alerts from the checks.
pub fn alerts(&self) -> &Vec<String> {
&self.alerts
}
/// The errors from the checks.
pub fn errors(&self) -> &Vec<String> {
&self.errors
}
/// Whether there are temporary messages or not.
pub fn temporary(&self) -> bool {
self.temporary
}
/// Whether the checks will allow the commit no matter what.
pub fn allowed(&self) -> bool {
self.allow
}
/// Whether the checks passed or failed.
pub fn pass(&self) -> bool {
self.pass
}
/// Combine two results together.
pub fn combine(self, other: Self) -> Self {
CheckResult {
warnings: self.warnings.into_iter().chain(other.warnings.into_iter()).collect(),
alerts: self.alerts.into_iter().chain(other.alerts.into_iter()).collect(),
errors: self.errors.into_iter().chain(other.errors.into_iter()).collect(),
temporary: self.temporary || other.temporary,
allow: self.allow || other.allow,
pass: self.pass && other.pass,
}
}
}
/// Interface for checks which run for each commit.
pub trait Check: Send + Sync {
/// The name of the check.
fn name(&self) -> &str;
/// Run the check.
fn check(&self, ctx: &CheckGitContext, commit: &Commit) -> Result<CheckResult>;
}
/// Interface for checks which runs once for the entire branch.
pub trait BranchCheck: Send + Sync {
/// The name of the check.
fn name(&self) -> &str;
/// Run the check.
fn check(&self, ctx: &CheckGitContext, commit: &CommitId) -> Result<CheckResult>;
}