1use camino::Utf8PathBuf;
2
3#[derive(Debug)]
4pub struct IoError(pub std::io::Error);
5
6impl std::fmt::Display for IoError {
7 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8 write!(f, "{}", self.0)
9 }
10}
11
12pub struct PatchFailed {
13 pub file: Utf8PathBuf,
14 pub output: String,
15}
16
17impl std::fmt::Display for PatchFailed {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 write!(f, "failed to apply patch: {}", self.file)?;
20 if !self.output.is_empty() {
21 write!(f, "\n{}", self.output.trim_end())?;
22 }
23 Ok(())
24 }
25}
26
27pub struct AstGrepFailed {
28 pub file: Utf8PathBuf,
29 pub output: String,
30}
31
32impl std::fmt::Display for AstGrepFailed {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 write!(f, "failed to apply ast-grep rule: {}", self.file)?;
35 if !self.output.is_empty() {
36 write!(f, "\n{}", self.output.trim_end())?;
37 }
38 Ok(())
39 }
40}
41
42pub struct CargoFailed(pub i32);
43
44impl std::fmt::Display for CargoFailed {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 write!(f, "cargo exited with status {}", self.0)
47 }
48}
49
50pub struct MissingEnvVar(pub &'static str);
51
52impl std::fmt::Display for MissingEnvVar {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 write!(f, "missing environment variable: {}", self.0)
55 }
56}
57
58pub struct MissingTool(pub &'static str);
59
60impl std::fmt::Display for MissingTool {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 write!(
63 f,
64 "required tool not found: {} (is it installed and in PATH?)",
65 self.0
66 )
67 }
68}
69
70pub struct MissingWorkspaceRoot(pub Utf8PathBuf);
71
72impl std::fmt::Display for MissingWorkspaceRoot {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 write!(
75 f,
76 "could not find workspace root from manifest directory: {}",
77 self.0
78 )
79 }
80}
81
82pub struct MissingStitchSet(pub String);
83
84impl std::fmt::Display for MissingStitchSet {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 write!(f, "stitch set not found: stitches/{}/", self.0)
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn patch_failed_display_empty_output() {
96 let err = PatchFailed {
97 file: Utf8PathBuf::from("stitches/default/crate-a/001.patch"),
98 output: String::new(),
99 };
100 assert_eq!(
101 err.to_string(),
102 "failed to apply patch: stitches/default/crate-a/001.patch"
103 );
104 }
105
106 #[test]
107 fn patch_failed_display_with_output() {
108 let err = PatchFailed {
109 file: Utf8PathBuf::from("fix.patch"),
110 output: "Hunk #1 FAILED\n".to_string(),
111 };
112 assert_eq!(
113 err.to_string(),
114 "failed to apply patch: fix.patch\nHunk #1 FAILED"
115 );
116 }
117
118 #[test]
119 fn ast_grep_failed_display_empty_output() {
120 let err = AstGrepFailed {
121 file: Utf8PathBuf::from("rule.yaml"),
122 output: String::new(),
123 };
124 assert_eq!(err.to_string(), "failed to apply ast-grep rule: rule.yaml");
125 }
126
127 #[test]
128 fn ast_grep_failed_display_with_output() {
129 let err = AstGrepFailed {
130 file: Utf8PathBuf::from("rule.yaml"),
131 output: "error details\n".to_string(),
132 };
133 assert_eq!(
134 err.to_string(),
135 "failed to apply ast-grep rule: rule.yaml\nerror details"
136 );
137 }
138
139 #[test]
140 fn cargo_failed_display() {
141 let err = CargoFailed(42);
142 assert_eq!(err.to_string(), "cargo exited with status 42");
143 }
144
145 #[test]
146 fn missing_env_var_display() {
147 let err = MissingEnvVar("CARGO_PKG_NAME");
148 assert_eq!(
149 err.to_string(),
150 "missing environment variable: CARGO_PKG_NAME"
151 );
152 }
153
154 #[test]
155 fn missing_tool_display() {
156 let err = MissingTool("patch");
157 assert_eq!(
158 err.to_string(),
159 "required tool not found: patch (is it installed and in PATH?)"
160 );
161 }
162
163 #[test]
164 fn missing_workspace_root_display() {
165 let err = MissingWorkspaceRoot(Utf8PathBuf::from("/tmp/foo"));
166 assert_eq!(
167 err.to_string(),
168 "could not find workspace root from manifest directory: /tmp/foo"
169 );
170 }
171
172 #[test]
173 fn missing_stitch_set_display() {
174 let err = MissingStitchSet("custom".to_string());
175 assert_eq!(err.to_string(), "stitch set not found: stitches/custom/");
176 }
177}