cargo_detect_package/
types.rs1use std::fmt;
6use std::path::PathBuf;
7
8#[derive(Clone, Debug, Eq, PartialEq)]
10#[non_exhaustive]
11pub enum OutsidePackageAction {
12 Workspace,
14 Ignore,
16 Error,
18}
19
20#[cfg_attr(test, mutants::skip)]
22impl std::str::FromStr for OutsidePackageAction {
23 type Err = String;
24
25 fn from_str(s: &str) -> Result<Self, Self::Err> {
26 match s.to_lowercase().as_str() {
27 "workspace" => Ok(Self::Workspace),
28 "ignore" => Ok(Self::Ignore),
29 "error" => Ok(Self::Error),
30 _ => Err(format!(
31 "Invalid outside-package action: '{s}'. Valid options are: workspace, ignore, error"
32 )),
33 }
34 }
35}
36
37#[doc(hidden)]
41#[derive(Debug)]
42#[allow(
43 clippy::exhaustive_structs,
44 reason = "This is a hidden struct for internal/test use only"
45)]
46pub struct RunInput {
47 pub path: PathBuf,
49 pub via_env: Option<String>,
51 pub outside_package: OutsidePackageAction,
53 pub subcommand: Vec<String>,
55}
56
57#[doc(hidden)]
59#[derive(Clone, Debug, Eq, PartialEq)]
60#[allow(
61 clippy::exhaustive_enums,
62 reason = "This is a hidden enum for internal/test use only"
63)]
64pub enum RunOutcome {
65 PackageDetected {
67 package_name: String,
69 subcommand_succeeded: bool,
71 },
72 WorkspaceScope {
74 subcommand_succeeded: bool,
76 },
77 Ignored,
79}
80
81#[doc(hidden)]
83#[derive(Debug)]
84#[allow(
85 clippy::exhaustive_enums,
86 reason = "This is a hidden enum for internal/test use only"
87)]
88pub enum RunError {
89 WorkspaceValidation(String),
91 PackageDetection(String),
93 OutsidePackage,
95 CommandExecution(std::io::Error),
97}
98
99impl fmt::Display for RunError {
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 match self {
102 Self::WorkspaceValidation(msg) => write!(f, "{msg}"),
103 Self::PackageDetection(msg) => write!(f, "Error detecting package: {msg}"),
104 Self::OutsidePackage => write!(f, "Path is not in any package"),
105 Self::CommandExecution(e) => write!(f, "Error executing command: {e}"),
106 }
107 }
108}
109
110impl std::error::Error for RunError {}
111
112#[cfg(test)]
113#[cfg_attr(coverage_nightly, coverage(off))]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn outside_package_action_parsing() {
119 assert_eq!(
120 "workspace".parse::<OutsidePackageAction>().unwrap(),
121 OutsidePackageAction::Workspace
122 );
123 assert_eq!(
124 "Workspace".parse::<OutsidePackageAction>().unwrap(),
125 OutsidePackageAction::Workspace
126 );
127 assert_eq!(
128 "WORKSPACE".parse::<OutsidePackageAction>().unwrap(),
129 OutsidePackageAction::Workspace
130 );
131
132 assert_eq!(
133 "ignore".parse::<OutsidePackageAction>().unwrap(),
134 OutsidePackageAction::Ignore
135 );
136 assert_eq!(
137 "Ignore".parse::<OutsidePackageAction>().unwrap(),
138 OutsidePackageAction::Ignore
139 );
140
141 assert_eq!(
142 "error".parse::<OutsidePackageAction>().unwrap(),
143 OutsidePackageAction::Error
144 );
145 assert_eq!(
146 "Error".parse::<OutsidePackageAction>().unwrap(),
147 OutsidePackageAction::Error
148 );
149
150 let result = "invalid".parse::<OutsidePackageAction>();
151 assert!(result.is_err());
152 assert!(
153 result
154 .unwrap_err()
155 .contains("Invalid outside-package action")
156 );
157 }
158
159 #[test]
160 fn run_error_display_workspace_validation() {
161 let error = RunError::WorkspaceValidation("some validation error".to_string());
162 let display = format!("{error}");
163 assert_eq!(display, "some validation error");
164 }
165
166 #[test]
167 fn run_error_display_package_detection() {
168 let error = RunError::PackageDetection("could not find package".to_string());
169 let display = format!("{error}");
170 assert_eq!(display, "Error detecting package: could not find package");
171 }
172
173 #[test]
174 fn run_error_display_outside_package() {
175 let error = RunError::OutsidePackage;
176 let display = format!("{error}");
177 assert_eq!(display, "Path is not in any package");
178 }
179
180 #[test]
181 fn run_error_display_command_execution() {
182 let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "command not found");
183 let error = RunError::CommandExecution(io_error);
184 let display = format!("{error}");
185 assert!(display.starts_with("Error executing command:"));
186 assert!(display.contains("command not found"));
187 }
188}