1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/// Error type for recoverable `sprawl-guard` CLI failures.
#[derive(Debug, thiserror::Error)]
pub enum CliError {
/// A reusable library operation failed.
#[error(transparent)]
Library(#[from] sprawl_guard_lib::SprawlError),
/// The current directory could not be resolved.
#[error("failed to determine current directory: {source}")]
CurrentDirectory {
/// Underlying I/O error.
source: std::io::Error,
},
/// The resolved config could not be rendered.
#[error("failed to render config: {source}")]
RenderConfig {
/// TOML serializer error.
source: toml::ser::Error,
},
/// An init target would overwrite an existing config.
#[error("config file already exists: {path}")]
ExistingConfig {
/// Existing config path.
path: std::path::PathBuf,
},
/// Init could not select any language.
#[error("no supported source files found; pass --languages or --all-languages")]
NoInitLanguages,
/// The initial config could not be written.
#[error("failed to write config {path}: {source}")]
WriteConfig {
/// Target config path.
path: std::path::PathBuf,
/// Underlying I/O error.
source: std::io::Error,
},
/// Init could not finish its advisory scan before writing the proposed config.
#[error("failed to run init advisory scan before writing {path}: {source}")]
InitAdvisoryScan {
/// Proposed config path.
path: std::path::PathBuf,
/// Underlying CLI failure.
source: Box<CliError>,
},
/// JSON output could not be rendered.
#[error("failed to render JSON: {source}")]
RenderJson {
/// JSON serializer error.
source: serde_json::Error,
},
/// The generated TypeScript machine contract could not be rendered.
#[error("failed to render machine contract: {source}")]
RenderMachineContract {
/// Template rendering error.
source: askama::Error,
},
/// The generated CLI reference could not be rendered.
#[error("failed to render CLI reference: {source}")]
RenderCliReference {
/// JSON serializer error.
source: serde_json::Error,
},
/// A Rust-owned machine contract value did not serialize as a string.
#[error("machine contract value {name} did not serialize as a string")]
MachineContractValueNonString {
/// Machine contract value name.
name: &'static str,
},
/// Machine response construction received an impossible process-style exit code.
#[error("machine command produced invalid exit code {exit_code}; expected 0..=255")]
InvalidMachineExitCode {
/// Invalid exit code.
exit_code: i32,
},
/// Machine commands must take root/config/state from the JSON request instead of global flags.
#[error("machine commands do not accept top-level --root, --config, --color, or --quiet")]
MachineGlobalFlagsUnsupported,
/// Machine transport commands cannot be executed through the shared user-command executor.
#[error("machine commands cannot be nested inside machine execution")]
MachineNestedInvocation,
/// The machine request could not be read from stdin.
#[error("failed to read machine request from stdin: {source}")]
ReadStdin {
/// Underlying stdin I/O error.
source: std::io::Error,
},
/// Baseline without a scope would replace an existing ratchet file.
#[error(
"ratchet file already exists; pass PATHS... to replace scoped entries or --all to replace every entry"
)]
AmbiguousRatchetReplacement,
/// Baseline would raise at least one existing ratchet ceiling.
#[error("refusing to raise {count} ratchet ceiling(s) without --allow-raises")]
RatchetRaises {
/// Number of ratchet entries that would increase.
count: usize,
},
/// `ratchet` updates require an existing ratchet file.
#[error("ratchet file does not exist: {path}")]
MissingRatchetFile {
/// Missing ratchet file path.
path: std::path::PathBuf,
},
/// Mutually exclusive scope options were combined.
#[error("--all cannot be combined with PATHS...")]
AllWithPaths,
}
/// Result alias used by `sprawl-guard` CLI code.
pub type Result<T> = std::result::Result<T, CliError>;