Skip to main content

grm/repo/worktree/
error.rs

1use 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}