Skip to main content

hx_plugins/
hooks.rs

1//! Hook events and dispatch for the plugin system.
2
3use std::fmt;
4use std::time::Duration;
5
6/// Events that can trigger plugin hooks.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum HookEvent {
9    /// Before build starts
10    PreBuild,
11    /// After build completes
12    PostBuild,
13    /// Before tests run
14    PreTest,
15    /// After tests complete
16    PostTest,
17    /// Before run command
18    PreRun,
19    /// After run completes
20    PostRun,
21    /// Before clean
22    PreClean,
23    /// After clean completes
24    PostClean,
25    /// Before lock generation
26    PreLock,
27    /// After lock completes
28    PostLock,
29    /// Project initialization
30    Init,
31}
32
33impl HookEvent {
34    /// Get all hook events.
35    pub fn all() -> &'static [HookEvent] {
36        &[
37            HookEvent::PreBuild,
38            HookEvent::PostBuild,
39            HookEvent::PreTest,
40            HookEvent::PostTest,
41            HookEvent::PreRun,
42            HookEvent::PostRun,
43            HookEvent::PreClean,
44            HookEvent::PostClean,
45            HookEvent::PreLock,
46            HookEvent::PostLock,
47            HookEvent::Init,
48        ]
49    }
50
51    /// Get the hook name as used in configuration.
52    pub fn config_key(&self) -> &'static str {
53        match self {
54            HookEvent::PreBuild => "pre_build",
55            HookEvent::PostBuild => "post_build",
56            HookEvent::PreTest => "pre_test",
57            HookEvent::PostTest => "post_test",
58            HookEvent::PreRun => "pre_run",
59            HookEvent::PostRun => "post_run",
60            HookEvent::PreClean => "pre_clean",
61            HookEvent::PostClean => "post_clean",
62            HookEvent::PreLock => "pre_lock",
63            HookEvent::PostLock => "post_lock",
64            HookEvent::Init => "init",
65        }
66    }
67
68    /// Get the Scheme function name for this hook.
69    pub fn scheme_function(&self) -> &'static str {
70        match self {
71            HookEvent::PreBuild => "pre-build-hook",
72            HookEvent::PostBuild => "post-build-hook",
73            HookEvent::PreTest => "pre-test-hook",
74            HookEvent::PostTest => "post-test-hook",
75            HookEvent::PreRun => "pre-run-hook",
76            HookEvent::PostRun => "post-run-hook",
77            HookEvent::PreClean => "pre-clean-hook",
78            HookEvent::PostClean => "post-clean-hook",
79            HookEvent::PreLock => "pre-lock-hook",
80            HookEvent::PostLock => "post-lock-hook",
81            HookEvent::Init => "init-hook",
82        }
83    }
84
85    /// Check if this is a "pre" event.
86    pub fn is_pre(&self) -> bool {
87        matches!(
88            self,
89            HookEvent::PreBuild
90                | HookEvent::PreTest
91                | HookEvent::PreRun
92                | HookEvent::PreClean
93                | HookEvent::PreLock
94        )
95    }
96
97    /// Check if this is a "post" event.
98    pub fn is_post(&self) -> bool {
99        matches!(
100            self,
101            HookEvent::PostBuild
102                | HookEvent::PostTest
103                | HookEvent::PostRun
104                | HookEvent::PostClean
105                | HookEvent::PostLock
106        )
107    }
108}
109
110impl fmt::Display for HookEvent {
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        write!(f, "{}", self.config_key())
113    }
114}
115
116/// Result of running a hook.
117#[derive(Debug, Clone)]
118pub struct HookResult {
119    /// Whether the hook succeeded.
120    pub success: bool,
121    /// How long the hook took to run.
122    pub duration: Duration,
123    /// Output from the hook (if any).
124    pub output: Option<String>,
125    /// Error message if failed.
126    pub error: Option<String>,
127}
128
129impl HookResult {
130    /// Create a successful result.
131    pub fn success(duration: Duration) -> Self {
132        HookResult {
133            success: true,
134            duration,
135            output: None,
136            error: None,
137        }
138    }
139
140    /// Create a successful result with output.
141    pub fn success_with_output(duration: Duration, output: String) -> Self {
142        HookResult {
143            success: true,
144            duration,
145            output: Some(output),
146            error: None,
147        }
148    }
149
150    /// Create a failed result.
151    pub fn failure(duration: Duration, error: String) -> Self {
152        HookResult {
153            success: false,
154            duration,
155            output: None,
156            error: Some(error),
157        }
158    }
159
160    /// Create a skipped result (hook not defined).
161    pub fn skipped() -> Self {
162        HookResult {
163            success: true,
164            duration: Duration::ZERO,
165            output: None,
166            error: None,
167        }
168    }
169}