grm/repo/worktree/
error.rs1use std::fmt;
2
3use super::{BranchName, RemoteName, RepoChanges, WorktreeName, config, path, repo};
4
5use camino::Utf8PathBuf as PathBuf;
6use thiserror::Error;
7
8#[derive(Debug, Error)]
9pub enum Error {
10 #[error(transparent)]
11 Libgit(#[from] git2::Error),
12 #[error(transparent)]
13 Repo(#[from] repo::Error),
14 #[error(transparent)]
15 Config(#[from] config::Error),
16 #[error(transparent)]
17 InvalidWorktreeName(#[from] WorktreeValidationError),
18 #[error("Remote \"{name}\" not found")]
19 RemoteNotFound { name: RemoteName },
20 #[error("Cannot push to non-pushable remote \"{name}\"")]
21 RemoteNotPushable { name: RemoteName },
22 #[error(transparent)]
23 Io(#[from] std::io::Error),
24 #[error("Current directory does not contain a worktree setup")]
25 NotAWorktreeSetup,
26 #[error("Worktree {name} already exists")]
27 WorktreeAlreadyExists { name: WorktreeName },
28 #[error("Branch \"{0}\" not found")]
29 BranchNotFound(BranchName),
30 #[error("Worktree name is not valid utf-8")]
31 WorktreeNameNotUtf8,
32 #[error(transparent)]
33 Path(#[from] path::Error),
34 #[error("Could not determine base directory from \"{git_dir}\"")]
35 InvalidBaseDirectory { git_dir: PathBuf },
36}
37
38#[derive(Debug, Error)]
39#[error("invalid worktree name \"{name}\": {reason}")]
40pub struct WorktreeValidationError {
41 pub(super) name: String,
42 pub(super) reason: WorktreeValidationErrorReason,
43}
44
45#[derive(Debug)]
46pub enum WorktreeValidationErrorReason {
47 SlashAtStartOrEnd,
48 ConsecutiveSlashes,
49 ContainsWhitespace,
50}
51
52impl fmt::Display for WorktreeValidationErrorReason {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 write!(
55 f,
56 "{}",
57 match *self {
58 Self::SlashAtStartOrEnd => "Cannot start or end with a slash",
59 Self::ConsecutiveSlashes => "Cannot contain two consecutive slashes",
60 Self::ContainsWhitespace => "Cannot contain whitespace",
61 }
62 )
63 }
64}
65
66#[derive(Debug, Error)]
67pub enum WorktreeRemoveError {
68 #[error(transparent)]
69 RepoError(repo::Error),
70 #[error("Worktree at {0} does not exist")]
71 DoesNotExist(PathBuf),
72 #[error(
73 "Branch \"{branch_name}\" is checked out in worktree \"{worktree_name}\", this does not look correct"
74 )]
75 BranchNameMismatch {
76 worktree_name: WorktreeName,
77 branch_name: BranchName,
78 },
79 #[error("Branch {0} not found")]
80 BranchNotFound(BranchName),
81 #[error("Changes found in worktree: {0}")]
82 Changes(RepoChanges),
83 #[error("Branch {branch_name} is not merged into any persistent branches")]
84 NotMerged { branch_name: BranchName },
85 #[error("Branch {branch_name} is not in line with remote branch")]
86 NotInSyncWithRemote { branch_name: BranchName },
87 #[error("Removing {path} failed: {error}")]
88 RemoveError {
89 path: PathBuf,
90 error: std::io::Error,
91 },
92 #[error("Error getting directory entry {path}: {error}")]
93 ReadDirectoryError {
94 path: PathBuf,
95 error: std::io::Error,
96 },
97}
98
99impl From<repo::Error> for WorktreeRemoveError {
100 fn from(value: repo::Error) -> Self {
101 Self::RepoError(value)
102 }
103}
104
105#[derive(Debug, Error)]
106pub enum WorktreeConversionError {
107 #[error(transparent)]
108 RepoError(repo::Error),
109 #[error("Changes found in worktree: {0}")]
110 Changes(RepoChanges),
111 #[error("Ignored files found")]
112 Ignored,
113 #[error("{}", .0)]
114 RenameError(String),
115 #[error(transparent)]
116 Path(#[from] path::Error),
117 #[error("Opening directory failed: {0}")]
118 OpenDirectoryError(std::io::Error),
119 #[error("Removing {path} failed: {error}")]
120 RemoveError {
121 path: PathBuf,
122 error: std::io::Error,
123 },
124 #[error("Error getting directory entry: {0}")]
125 ReadDirectoryError(std::io::Error),
126}
127
128impl From<repo::Error> for WorktreeConversionError {
129 fn from(value: repo::Error) -> Self {
130 Self::RepoError(value)
131 }
132}
133
134#[derive(Debug, Error)]
135pub enum CleanupWorktreeError {
136 #[error(transparent)]
137 RepoError(#[from] Error),
138 #[error(transparent)]
139 RemoveError(#[from] WorktreeRemoveError),
140 #[error("Could not get default branch: {0}")]
141 DefaultBranch(repo::Error),
142 #[error("Branch name error: {0}")]
143 BranchName(repo::Error),
144 #[error("Branch \"{branch_name}\" not found")]
145 BranchNotFound { branch_name: BranchName },
146}
147
148pub struct CleanupWorktreeWarning {
149 pub worktree_name: WorktreeName,
150 pub reason: CleanupWorktreeWarningReason,
151}
152
153pub enum CleanupWorktreeWarningReason {
154 UncommittedChanges(RepoChanges),
155 NotMerged { branch_name: BranchName },
156 NoDirectory,
157}