1use std::path::PathBuf;
2use thiserror::Error;
3
4#[derive(Error, Debug)]
9#[non_exhaustive]
10pub enum DodotError {
11 #[error("filesystem error at {path}: {source}")]
12 Fs {
13 path: PathBuf,
14 source: std::io::Error,
15 },
16
17 #[error("symlink conflict: {path} already exists and is not managed by dodot")]
18 SymlinkConflict { path: PathBuf },
19
20 #[error("protected path: {path} cannot be symlinked")]
21 ProtectedPath { path: PathBuf },
22
23 #[error("pack not found: {name}")]
24 PackNotFound { name: String },
25
26 #[error("pack is invalid: {name}: {reason}")]
27 PackInvalid { name: String, reason: String },
28
29 #[error("handler not found: {name}")]
30 HandlerNotFound { name: String },
31
32 #[error("config error: {0}")]
33 Config(String),
34
35 #[error("command failed: {command} (exit code {exit_code})\n{stderr}")]
36 CommandFailed {
37 command: String,
38 exit_code: i32,
39 stderr: String,
40 },
41
42 #[error("invalid pattern {pattern}: {reason}")]
43 InvalidPattern { pattern: String, reason: String },
44
45 #[error("cross-pack deployment conflict detected (--force does not override this):\n{}", crate::conflicts::format_conflicts(.conflicts))]
46 CrossPackConflict {
47 conflicts: Vec<crate::conflicts::Conflict>,
48 },
49
50 #[error("preprocessing failed for {source_file} ({preprocessor}): {message}")]
51 PreprocessorError {
52 preprocessor: String,
53 source_file: PathBuf,
54 message: String,
55 },
56
57 #[error("preprocessing collision in pack \"{pack}\": {source_file} expands to {expanded_name}, which conflicts with an existing pack file or another preprocessor's output")]
58 PreprocessorCollision {
59 pack: String,
60 source_file: String,
61 expanded_name: String,
62 },
63
64 #[error("template render failed for {}:\n {message}", source_file.display())]
65 TemplateRender {
66 source_file: PathBuf,
67 message: String,
68 },
69
70 #[error("template variable name \"{name}\" is reserved (dodot and env are built-in namespaces); choose a different name in [preprocessor.template.vars]")]
71 TemplateReservedVar { name: String },
72
73 #[error("{0}")]
74 Other(String),
75}
76
77pub type Result<T> = std::result::Result<T, DodotError>;
79
80pub(crate) fn fs_err(path: impl Into<PathBuf>, source: std::io::Error) -> DodotError {
82 DodotError::Fs {
83 path: path.into(),
84 source,
85 }
86}