1use std::{fmt::Display, io, string};
2
3#[derive(Debug)]
4pub enum Error {
5 StashList(git2::Error),
6 ReadLog(git2::Error),
7 OpenRepo(git2::Error),
8 Term(io::Error),
9 Config(Box<figment::Error>),
10 EditConfig(String),
11 Bindings { bad_key_bindings: Vec<String> },
12 FileWatcher(notify::Error),
13 ReadRebaseStatusFile(io::Error),
14 ReadRebaseTodo(io::Error),
15 ReadPipedInput(io::Error),
16 PagerWithoutInput,
17 WriteRebaseTodo(io::Error),
18 ReadBranchName(io::Error),
19 BranchNameUtf8(Utf8Error),
20 GitDiff(io::Error),
21 GitDiffUtf8(string::FromUtf8Error),
22 GitShow(io::Error),
23 GitShowUtf8(string::FromUtf8Error),
24 GitShowMeta(git2::Error),
25 NotOnBranch,
26 GetHead(git2::Error),
27 CurrentBranchName(git2::Error),
28 GetCurrentBranchUpstream(git2::Error),
29 GetCurrentBranchUpstreamUtf8(Utf8Error),
30 RemoteNameUtf8(Utf8Error),
31 CannotDeleteCurrentBranch,
32 BranchNameRequired,
33 IsBranchMerged(git2::Error),
34 GetRemote(git2::Error),
35 ReadGitConfig(git2::Error),
36 ReadGitConfigUtf8(Utf8Error),
37 DeleteGitConfig(git2::Error),
38 SetGitConfig(git2::Error),
39 RemoteHasNoName,
40 ReadOid(git2::Error),
41 ArgMustBePositiveNumber,
42 ArgInvalidRegex(regex::Error),
43 Clipboard(arboard::Error),
44 FindGitRev(git2::Error),
45 NoEditorSet,
46 GitStatus(git2::Error),
47 CmdAlreadyRunning,
48 StashWorkTreeEmpty,
49 CouldntAwaitCmd(io::Error),
50 NoRepoWorkdir,
51 SpawnCmd(io::Error),
52 CmdBadExit(String, Option<i32>),
53 CouldntReadCmdOutput(io::Error),
54 ListGitReferences(git2::Error),
55 OpenLogFile(io::Error),
56 PromptAborted,
57 ReadPromptHistory(io::Error),
58 WritePromptHistory(io::Error),
59 NoMoreEvents,
60 CannotSpinoffCurrentBranch,
61 SpinoffBranchExists(String),
62 DoesBranchExist(git2::Error),
63 GetBranchName(git2::Error),
64 BaseCommitOid,
65 UpstreamCommitOid,
66 GitBlame(io::Error),
67 NoSearchMatch(String),
68 NoPreviousSearch,
69 InvalidSearchRegex(regex::Error),
70 EditedCommandQuotes,
71 EditedCommandFixed,
72 EditedCommandWrites(String),
73 GitRefusedTheCommand(String),
74}
75
76impl std::error::Error for Error {}
77
78impl Display for Error {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 match self {
81 Error::StashList(e) => f.write_fmt(format_args!("Couldn't list stash: {e}")),
82 Error::ReadLog(e) => f.write_fmt(format_args!("Couldn't read log: {e}")),
83 Error::ReadPipedInput(e) => {
84 f.write_fmt(format_args!("Couldn't read the piped input: {e}"))
85 }
86 Error::PagerWithoutInput => {
87 f.write_str("--pager expects a patch on stdin, e.g. `git show | gitu --pager`")
88 }
89 Error::ReadRebaseTodo(e) => {
90 f.write_fmt(format_args!("Couldn't read the rebase todo list: {e}"))
91 }
92 Error::WriteRebaseTodo(e) => {
93 f.write_fmt(format_args!("Couldn't write the rebase todo list: {e}"))
94 }
95 Error::OpenRepo(e) => match e.code() {
96 git2::ErrorCode::NotFound => f.write_str("No .git found in the current directory"),
97 _ => f.write_fmt(format_args!("Couldn't open repo: {e:?}")),
98 },
99 Error::Term(e) => f.write_fmt(format_args!("Terminal error: {}", e)),
100 Error::Config(e) => f.write_fmt(format_args!("Configuration error: {e}")),
101 Error::EditConfig(e) => {
102 f.write_fmt(format_args!("Couldn't save to the config file: {e}"))
103 }
104 Error::Bindings { bad_key_bindings } => {
105 let mut error_string = String::from("Errors while parsing key bindings:");
106 for item in bad_key_bindings {
107 error_string.push_str(&format!("\n{item}"));
108 }
109 f.write_fmt(format_args!("{error_string}"))
110 }
111 Error::FileWatcher(e) => f.write_fmt(format_args!("File watcher error: {e}")),
112 Error::ReadRebaseStatusFile(e) => {
113 f.write_fmt(format_args!("Couldn't read rebase status file: {e}"))
114 }
115 Error::ReadBranchName(e) => f.write_fmt(format_args!("Couldn't read branch name: {e}")),
116 Error::BranchNameUtf8(_e) => f.write_str("Branch name error"),
117 Error::GitDiff(e) => f.write_fmt(format_args!("Git diff error: {e}")),
118 Error::GitDiffUtf8(e) => {
119 f.write_fmt(format_args!("Git diff output is not valid UTF-8: {e}"))
120 }
121 Error::GitShow(e) => f.write_fmt(format_args!("Git show error: {e}")),
122 Error::GitShowUtf8(e) => {
123 f.write_fmt(format_args!("Git show output is not valid UTF-8: {e}"))
124 }
125 Error::GitShowMeta(e) => f.write_fmt(format_args!("Git show metadata error: {e}")),
126 Error::NotOnBranch => f.write_str("Head is not a branch"),
127 Error::GetHead(e) => f.write_fmt(format_args!("Couldn't get HEAD: {e}")),
128 Error::CurrentBranchName(e) => {
129 f.write_fmt(format_args!("Couldn't get current branch name: {e}"))
130 }
131 Error::GetCurrentBranchUpstream(e) => {
132 f.write_fmt(format_args!("Couldn't get current branch upstream: {e}"))
133 }
134 Error::GetCurrentBranchUpstreamUtf8(_e) => {
135 f.write_str("Current branch upstream is not valid UTF-8")
136 }
137 Error::RemoteNameUtf8(_e) => f.write_str("Remote name is not valid UTF-8"),
138 Error::CannotDeleteCurrentBranch => f.write_str("Cannot delete current branch"),
139 Error::BranchNameRequired => f.write_str("Branch name required"),
140 Error::IsBranchMerged(e) => {
141 f.write_fmt(format_args!("Couldn't check if branch is merged: {e}"))
142 }
143 Error::GetRemote(e) => f.write_fmt(format_args!("Couldn't get remote: {e}")),
144 Error::ReadGitConfig(e) => f.write_fmt(format_args!("Couldn't read git config: {e}")),
145 Error::ReadGitConfigUtf8(_e) => f.write_str("Git config is not valid UTF-8"),
146 Error::DeleteGitConfig(e) => {
147 f.write_fmt(format_args!("Couldn't delete git config: {e}"))
148 }
149 Error::SetGitConfig(e) => f.write_fmt(format_args!("Couldn't set git config: {e}")),
150 Error::RemoteHasNoName => f.write_str("Remote has no name"),
151 Error::ReadOid(e) => f.write_fmt(format_args!("Couldn't read OID: {e}")),
152 Error::ArgMustBePositiveNumber => f.write_str("Value must be a number greater than 0"),
153 Error::ArgInvalidRegex(e) => f.write_fmt(format_args!("Invalid regex: {e}")),
154 Error::Clipboard(e) => f.write_fmt(format_args!("Clipboard error: {e}")),
155 Error::FindGitRev(e) => f.write_fmt(format_args!("Couldn't find git revision: {e}")),
156 Error::NoEditorSet => f.write_fmt(format_args!(
157 "No editor environment variable set ({})",
158 crate::ops::show::EDITOR_VARS.join(", ")
159 )),
160 Error::GitStatus(e) => f.write_fmt(format_args!("Git status error: {e}")),
161 Error::CmdAlreadyRunning => f.write_str("A command is already running"),
162 Error::StashWorkTreeEmpty => f.write_str("Cannot stash: working tree is empty"),
163 Error::CouldntAwaitCmd(e) => f.write_fmt(format_args!("Couldn't await command: {e}")),
164 Error::NoRepoWorkdir => f.write_str("No repository working directory"),
165 Error::SpawnCmd(e) => f.write_fmt(format_args!("Failed to spawn command: {e}")),
166 Error::CmdBadExit(args, code) => f.write_fmt(format_args!(
167 "'{}' exited with code: {}",
168 args,
169 code.map(|c| c.to_string())
170 .unwrap_or_else(|| "".to_string())
171 )),
172 Error::CouldntReadCmdOutput(e) => {
173 f.write_fmt(format_args!("Couldn't read command output: {e}"))
174 }
175 Error::ListGitReferences(e) => {
176 f.write_fmt(format_args!("Couldn't list git references: {e}"))
177 }
178 Error::OpenLogFile(e) => f.write_fmt(format_args!("Couldn't open log file: {e}")),
179 Error::PromptAborted => f.write_str("Aborted"),
180 Error::ReadPromptHistory(e) => {
181 f.write_fmt(format_args!("Couldn't read prompt history: {e}"))
182 }
183 Error::WritePromptHistory(e) => {
184 f.write_fmt(format_args!("Couldn't write prompt history: {e}"))
185 }
186 Error::NoMoreEvents => unimplemented!(),
187 Error::CannotSpinoffCurrentBranch => f.write_str("Cannot spin-off current branch"),
188 Error::SpinoffBranchExists(new_branch_name) => f.write_fmt(format_args!(
189 "Cannot spin-off {new_branch_name}. It already exists"
190 )),
191 Error::DoesBranchExist(e) => {
192 f.write_fmt(format_args!("Couldn't check if branch exists: {}", e))
193 }
194 Error::GetBranchName(e) => f.write_fmt(format_args!("Couldn't get branch name: {}", e)),
195 Error::BaseCommitOid => f.write_str("Could not resolve OID of base commit"),
196 Error::UpstreamCommitOid => {
197 f.write_str("Could not resolve OID of upstream branch commit")
198 }
199 Error::GitBlame(e) => f.write_fmt(format_args!("Git blame error: {e}")),
200 Error::NoSearchMatch(query) => f.write_fmt(format_args!("No match: {query}")),
201 Error::NoPreviousSearch => f.write_str("No previous search"),
202 Error::InvalidSearchRegex(e) => f.write_fmt(format_args!("Invalid search: {e}")),
203 Error::EditedCommandQuotes => f.write_str("Unbalanced quotes"),
204 Error::EditedCommandFixed => f.write_str(
205 "Only git's arguments can be edited, not the program or git's own options",
206 ),
207 Error::EditedCommandWrites(subcommand) => f.write_fmt(format_args!(
208 "gitu re-runs this command on every refresh, so it must only report: {subcommand}"
209 )),
210 Error::GitRefusedTheCommand(stderr) => f.write_str(stderr),
211 }
212 }
213}
214
215#[derive(Debug)]
216pub enum Utf8Error {
217 Str(std::str::Utf8Error),
218 String(string::FromUtf8Error),
219}
220
221impl std::error::Error for Utf8Error {}
222
223impl Display for Utf8Error {
224 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
225 f.write_str("not valid UTF-8")
226 }
227}