1use std::path::PathBuf;
5
6use objects::HeddleError;
7use repo::{FsMonitorMode, Repository, WorktreeStatusOptions};
8
9pub struct ExecutionContext {
14 repo: Option<Repository>,
15 start_path: Option<PathBuf>,
16 principal_fallback: Option<(String, String)>,
17 fsmonitor_mode: FsMonitorMode,
18}
19
20impl ExecutionContext {
21 pub fn builder() -> ExecutionContextBuilder {
22 ExecutionContextBuilder::default()
23 }
24
25 pub fn require_repo(&self) -> Result<&Repository, HeddleError> {
26 self.repo
27 .as_ref()
28 .ok_or_else(|| HeddleError::RepositoryNotFound(PathBuf::from(".")))
29 }
30
31 pub fn repo(&self) -> Option<&Repository> {
32 self.repo.as_ref()
33 }
34
35 pub fn start_path(&self) -> Option<&std::path::Path> {
36 self.start_path.as_deref()
37 }
38
39 pub fn principal_fallback(&self) -> Option<(&str, &str)> {
41 self.principal_fallback
42 .as_ref()
43 .map(|(name, email)| (name.as_str(), email.as_str()))
44 }
45
46 pub fn fsmonitor_mode(&self) -> FsMonitorMode {
48 self.fsmonitor_mode
49 }
50
51 pub fn worktree_status_options(&self) -> WorktreeStatusOptions {
52 WorktreeStatusOptions {
53 fsmonitor: repo::FsMonitorSettings {
54 mode: self.fsmonitor_mode,
55 },
56 }
57 }
58}
59
60#[derive(Default)]
62pub struct ExecutionContextBuilder {
63 repo: Option<Repository>,
64 start_path: Option<PathBuf>,
65 principal_fallback: Option<(String, String)>,
66 fsmonitor_mode: FsMonitorMode,
67}
68
69impl ExecutionContextBuilder {
70 pub fn repo(mut self, repo: Repository) -> Self {
71 self.repo = Some(repo);
72 self
73 }
74
75 pub fn start_path(mut self, path: impl Into<PathBuf>) -> Self {
76 self.start_path = Some(path.into());
77 self
78 }
79
80 pub fn principal_fallback(mut self, principal: Option<(String, String)>) -> Self {
81 self.principal_fallback = principal;
82 self
83 }
84
85 pub fn fsmonitor_mode(mut self, mode: FsMonitorMode) -> Self {
86 self.fsmonitor_mode = mode;
87 self
88 }
89
90 pub fn build(self) -> ExecutionContext {
91 ExecutionContext {
92 repo: self.repo,
93 start_path: self.start_path,
94 principal_fallback: self.principal_fallback,
95 fsmonitor_mode: self.fsmonitor_mode,
96 }
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn default_context_has_no_repo_and_noop_sinks() {
106 let ctx = ExecutionContext::builder().build();
107
108 assert!(matches!(
109 ctx.require_repo(),
110 Err(HeddleError::RepositoryNotFound(_))
111 ));
112 assert_eq!(ctx.fsmonitor_mode(), FsMonitorMode::Off);
113 assert!(ctx.principal_fallback().is_none());
114 }
115
116 #[test]
117 fn builder_sets_non_repo_fields() {
118 let ctx = ExecutionContext::builder()
119 .start_path("/tmp/heddle-verbs-context-test")
120 .principal_fallback(Some(("Luke".into(), "luke@example.com".into())))
121 .fsmonitor_mode(FsMonitorMode::Watchman)
122 .build();
123
124 assert_eq!(
125 ctx.start_path(),
126 Some(std::path::Path::new("/tmp/heddle-verbs-context-test"))
127 );
128 assert_eq!(ctx.principal_fallback(), Some(("Luke", "luke@example.com")));
129 assert_eq!(
130 ctx.worktree_status_options().fsmonitor.mode,
131 FsMonitorMode::Watchman
132 );
133 }
134}