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}