use crate::{Certainty, LintianIssue, PackageType};
use std::path::PathBuf;
pub use debian_workspace::action::{
Action, ActionPlan, ChangelogAction, Deb822Action, DebcargoAction, Dep3Action,
DesktopIniAction, FilesystemAction, IndentPattern, LintianOverridesAction, MaintscriptAction,
MakefileAction, OverrideLineSelector, ParagraphSelector, RunCommandAction, SystemdAction,
TextRange, WatchAction, YamlAction, YamlPathComponent,
};
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct Diagnostic {
#[serde(skip_serializing_if = "Option::is_none", default)]
pub issue: Option<LintianIssue>,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub certainty: Option<Certainty>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub patch_name: Option<String>,
pub plans: Vec<ActionPlan>,
}
impl Diagnostic {
pub fn with_actions(
issue: LintianIssue,
description: impl Into<String>,
label: impl Into<String>,
actions: Vec<Action>,
) -> Self {
Self::with_plans(
issue,
description,
vec![ActionPlan {
label: label.into(),
opinionated: false,
certainty: None,
actions,
}],
)
}
pub fn with_plans(
issue: LintianIssue,
message: impl Into<String>,
plans: Vec<ActionPlan>,
) -> Self {
Self {
issue: Some(issue),
message: message.into(),
certainty: None,
patch_name: None,
plans,
}
}
pub fn untagged(
description: impl Into<String>,
label: impl Into<String>,
actions: Vec<Action>,
) -> Self {
Self {
issue: None,
message: description.into(),
certainty: None,
patch_name: None,
plans: vec![ActionPlan {
label: label.into(),
opinionated: false,
certainty: None,
actions,
}],
}
}
pub fn untagged_with_plans(description: impl Into<String>, plans: Vec<ActionPlan>) -> Self {
Self {
issue: None,
message: description.into(),
certainty: None,
patch_name: None,
plans,
}
}
pub fn with_certainty(mut self, certainty: Certainty) -> Self {
self.certainty = Some(certainty);
self
}
pub fn with_patch_name(mut self, name: impl Into<String>) -> Self {
self.patch_name = Some(name.into());
self
}
}
pub fn override_action_plan(issue: &LintianIssue) -> Option<ActionPlan> {
let tag = issue.tag.as_ref()?;
let file = match issue.package_type {
Some(PackageType::Binary) => issue
.package
.as_deref()
.map(|p| PathBuf::from(format!("debian/{}.lintian-overrides", p)))
.unwrap_or_else(|| PathBuf::from("debian/source/lintian-overrides")),
_ => PathBuf::from("debian/source/lintian-overrides"),
};
Some(ActionPlan {
label: format!("Add lintian override for {}", tag),
opinionated: false,
certainty: None,
actions: vec![Action::LintianOverrides(LintianOverridesAction::AddLine {
file,
package: issue.package.clone(),
tag: tag.clone(),
info: issue.info.clone(),
})],
})
}
pub fn add_override_plans(diags: &mut Vec<Diagnostic>) {
for diag in diags.iter_mut() {
if let Some(plan) = diag.issue.as_ref().and_then(override_action_plan) {
let already_has_override = diag.plans.iter().any(|p| {
p.actions.iter().any(|a| {
matches!(
a,
Action::LintianOverrides(LintianOverridesAction::AddLine { .. })
)
})
});
if !already_has_override {
diag.plans.push(plan);
}
}
}
}