Skip to main content

newgit_core/
error.rs

1use camino::Utf8PathBuf;
2use thiserror::Error;
3
4pub type Result<T> = std::result::Result<T, NewgitError>;
5
6#[derive(Debug, Error)]
7pub enum NewgitError {
8    #[error("I/O error at {path}: {source}")]
9    Io {
10        path: Utf8PathBuf,
11        source: std::io::Error,
12    },
13
14    #[error("could not parse TOML at {path}: {source}")]
15    TomlRead {
16        path: Utf8PathBuf,
17        source: toml::de::Error,
18    },
19
20    #[error("could not serialize TOML for {label}: {source}")]
21    TomlWrite {
22        label: String,
23        source: toml::ser::Error,
24    },
25
26    #[error(
27        "newgit is not initialized here (no .newgit found from {0} upward); run `newgit init` in the project root"
28    )]
29    MissingMetadata(Utf8PathBuf),
30
31    #[error("already exists at {0}")]
32    AlreadyExists(Utf8PathBuf),
33
34    #[error(
35        "invalid name `{0}`; use letters, numbers, dots, underscores, hyphens, or slashes, starting with a letter or number"
36    )]
37    InvalidName(String),
38
39    #[error(
40        "branch instance `{name}` collides with existing record {path}; instance names must be unique after slugging"
41    )]
42    BranchInstanceExists { name: String, path: Utf8PathBuf },
43
44    #[error("no branch instance named `{0}`")]
45    UnknownBranchInstance(String),
46
47    #[error("workspace directory already exists at {0}; remove it or pick another name")]
48    WorkspaceExists(Utf8PathBuf),
49
50    #[error("{0} is not a Git repository; newgit v1 drives source through Git")]
51    NotAGitRepo(Utf8PathBuf),
52
53    #[error("`{command}` failed: {stderr}")]
54    SourceCommand { command: String, stderr: String },
55
56    #[error("tracker `{tracker}` is invalid: {reason}")]
57    InvalidDefinition { tracker: String, reason: String },
58
59    #[error("trackers `{left}` and `{right}` both own `{path}`; content lanes must be disjoint")]
60    TrackerPathConflict {
61        left: String,
62        right: String,
63        path: camino::Utf8PathBuf,
64    },
65
66    #[error("no tracker named `{0}` is defined in .newgit/trackers/")]
67    UnknownTracker(String),
68
69    #[error("unknown starter template `{0}`")]
70    UnknownTemplate(String),
71
72    #[error("tracker `{tracker}` has no captured content at rev `{rev}`")]
73    NoSnapshot { tracker: String, rev: String },
74
75    #[error("tracker `{0}` owns no paths; there is nothing to capture from a workspace")]
76    TrackerHasNoPaths(String),
77
78    #[error("no resource named `{0}` is defined in .newgit/resources/")]
79    UnknownResource(String),
80
81    #[error("resource `{resource}` has no action named `{action}`")]
82    UnknownAction { resource: String, action: String },
83
84    #[error("resource `{resource}` is already running (pid {pid}); stop it first")]
85    AlreadyRunning { resource: String, pid: u32 },
86
87    #[error("resource dependency cycle: {0:?}")]
88    DependencyCycle(Vec<String>),
89
90    #[error(
91        "resource `{resource}` depends on `{dependency}`, which is neither a tracker nor a resource"
92    )]
93    MissingDependency {
94        resource: String,
95        dependency: String,
96    },
97
98    #[error("no checkpoints exist for `{0}`; create one with `newgit checkpoint {0}`")]
99    NoCheckpoints(String),
100
101    #[error(
102        "no checkpoint `{id}` for `{instance}`; list them with `newgit checkpoints {instance}`"
103    )]
104    UnknownCheckpoint { instance: String, id: String },
105
106    #[error(
107        "checkpoint command for resource `{resource}` exited with {code} (log: {log}); \
108         the checkpoint was aborted — a checkpoint that missed a resource is not coherent"
109    )]
110    CheckpointCommandFailed {
111        resource: String,
112        code: i32,
113        log: Utf8PathBuf,
114    },
115
116    #[error("{0}")]
117    Unsupported(String),
118
119    #[error("path is not valid UTF-8: {0}")]
120    NonUtf8Path(String),
121}
122
123impl NewgitError {
124    pub fn io(path: impl Into<Utf8PathBuf>, source: std::io::Error) -> Self {
125        Self::Io {
126            path: path.into(),
127            source,
128        }
129    }
130}