1use std::io;
4use std::path::PathBuf;
5use thiserror::Error;
6
7pub type Result<T> = std::result::Result<T, RtaskError>;
9
10#[derive(Error, Debug)]
12pub enum RtaskError {
13 #[error("Configuration error: {0}")]
15 Config(#[from] ConfigError),
16
17 #[error("Execution error: {0}")]
19 Execution(#[from] ExecutionError),
20
21 #[error("Interpolation error: {0}")]
23 Interpolation(#[from] InterpolationError),
24
25 #[error("I/O error: {0}")]
27 Io(#[from] io::Error),
28
29 #[error("YAML parsing error: {0}")]
31 Yaml(#[from] serde_yaml::Error),
32}
33
34#[derive(Error, Debug)]
36pub enum ConfigError {
37 #[error("Failed to find config file (searched: {0})")]
38 NotFound(String),
39
40 #[error("Invalid configuration: {0}")]
41 Invalid(String),
42
43 #[error("Task source cannot be defined without target")]
44 SourceWithoutTarget,
45
46 #[error("Task target cannot be defined without source")]
47 TargetWithoutSource,
48
49 #[error("Argument and option '{0}' must have unique names within a task")]
50 DuplicateNames(String),
51
52 #[error("Task '{0}' is not defined")]
53 TaskNotFound(String),
54
55 #[error("Circular dependency detected: {0}")]
56 CircularDependency(String),
57
58 #[error("Failed to include file '{path}': {error}")]
59 IncludeFile { path: PathBuf, error: String },
60}
61
62#[derive(Error, Debug)]
64pub enum ExecutionError {
65 #[error("Command failed with exit code {0:?}")]
66 CommandFailed(Option<i32>),
67
68 #[error("Failed condition: {0}")]
69 FailedCondition(String),
70
71 #[error("Option '{0}' is required but not provided")]
72 MissingOption(String),
73
74 #[error("Invalid option value for '{name}': {error}")]
75 InvalidOption { name: String, error: String },
76
77 #[error("Cache error: {0}")]
78 Cache(String),
79
80 #[error("Environment error: {0}")]
81 Environment(String),
82}
83
84#[derive(Error, Debug)]
86pub enum InterpolationError {
87 #[error("Variable '{0}' is not defined")]
88 UndefinedVariable(String),
89
90 #[error("Invalid interpolation syntax: {0}")]
91 InvalidSyntax(String),
92
93 #[error("Recursive interpolation detected")]
94 RecursiveInterpolation,
95}
96
97pub type ConfigResult<T> = std::result::Result<T, ConfigError>;
99
100pub type ExecutionResult<T> = std::result::Result<T, ExecutionError>;
102
103pub type InterpolationResult<T> = std::result::Result<T, InterpolationError>;
105
106pub fn is_failed_condition(err: &ExecutionError) -> bool {
109 matches!(err, ExecutionError::FailedCondition(_))
110}