1use std::path::PathBuf;
2
3use callisto_model::{CommitSha, Package, Severity, Version};
4use callisto_vcs::GitAccess;
5
6use crate::config::PreMajorInferencePolicy;
7use crate::error::GraphError;
8
9pub trait SeverityInference: Send + Sync {
10 fn infer(
15 &self,
16 pkg: &Package,
17 git: &GitAccess<'_>,
18 window: InferenceWindowSpec<'_>,
19 ) -> Result<Option<InferenceOutcome>, GraphError>;
20}
21
22pub struct InferenceWindowSpec<'a> {
23 pub pathspecs: &'a [PathBuf],
24 pub since: Option<CommitSha>,
25 pub current_version: &'a Version,
26 pub has_prior_release: bool,
27 pub policy: PreMajorInferencePolicy,
28}
29
30#[derive(Clone, Debug, PartialEq, Eq)]
31pub struct InferenceOutcome {
32 pub severity: Severity,
33 pub commit_count: usize,
34 pub remapped: bool,
35 pub commits: Vec<(CommitSha, String)>,
36}
37
38pub struct NoInference;
39
40impl SeverityInference for NoInference {
41 fn infer(
42 &self,
43 _pkg: &Package,
44 _git: &GitAccess<'_>,
45 _window: InferenceWindowSpec<'_>,
46 ) -> Result<Option<InferenceOutcome>, GraphError> {
47 Ok(None)
48 }
49}
50
51#[cfg(feature = "inference")]
56pub struct CommitInference;
57
58#[cfg(feature = "inference")]
59impl SeverityInference for CommitInference {
60 fn infer(
61 &self,
62 pkg: &Package,
63 git: &GitAccess<'_>,
64 window: InferenceWindowSpec<'_>,
65 ) -> Result<Option<InferenceOutcome>, GraphError> {
66 use callisto_conventional::{infer_severity, InferenceInput, InferenceWindow};
67
68 let inf_window = match window.since {
69 Some(sha) => InferenceWindow::SinceCommit(sha),
70 None => InferenceWindow::FullHistory,
71 };
72
73 let input = InferenceInput {
74 package: &pkg.id,
75 pathspecs: window.pathspecs,
76 window: inf_window,
77 current_version: window.current_version,
78 has_prior_release: window.has_prior_release,
79 };
80
81 let raw = infer_severity(git, &input)?;
84 if raw.commit_count == 0 {
85 return Ok(None);
86 }
87
88 let (severity, remapped) = crate::aggregate::apply_pre_major(
89 raw.severity,
90 window.policy,
91 window.current_version,
92 window.has_prior_release,
93 );
94
95 let commits = raw
96 .commits
97 .into_iter()
98 .map(|c| (c.sha().clone(), c.subject().to_string()))
99 .collect();
100
101 Ok(Some(InferenceOutcome {
102 severity,
103 commit_count: raw.commit_count,
104 remapped,
105 commits,
106 }))
107 }
108}