1use std::path::PathBuf;
2use crate::types::WorktreeState;
3
4#[derive(Debug, thiserror::Error)]
6#[non_exhaustive]
7pub enum WorktreeError {
8 #[error("git not found in PATH — install git 2.20 or later")]
9 GitNotFound,
10
11 #[error("git version too old: required {required}, found {found}")]
12 GitVersionTooOld { required: String, found: String },
13
14 #[error("branch '{branch}' is already checked out at '{worktree}'")]
15 BranchAlreadyCheckedOut { branch: String, worktree: PathBuf },
16
17 #[error("worktree path already exists: {0}")]
18 WorktreePathExists(PathBuf),
19
20 #[error("uncommitted changes in worktree — use force_dirty to override: {files:?}")]
21 UncommittedChanges { files: Vec<String> },
22
23 #[error("unmerged commits on '{branch}': {commit_count} commit(s) not in upstream — use force to override")]
24 UnmergedCommits { branch: String, commit_count: usize },
25
26 #[error("insufficient disk space: {available_mb}MB available, {required_mb}MB required")]
27 DiskSpaceLow { available_mb: u64, required_mb: u64 },
28
29 #[error("aggregate worktree disk usage exceeds limit")]
30 AggregateDiskLimitExceeded,
31
32 #[error("target is on a network filesystem — performance not guaranteed: {mount_point}")]
33 NetworkFilesystem { mount_point: PathBuf },
34
35 #[error("cannot create Windows junction targeting network path: {path}")]
36 NetworkJunctionTarget { path: PathBuf },
37
38 #[error("cannot create worktree across WSL/Windows filesystem boundary")]
39 WslCrossBoundary,
40
41 #[error("submodule context detected — run from superproject root")]
42 SubmoduleContext,
43
44 #[error("state lock contention — another process holds the lock after {timeout_ms}ms")]
45 StateLockContention { timeout_ms: u64 },
46
47 #[error("orphaned worktrees detected: {paths:?}")]
48 OrphanDetected { paths: Vec<PathBuf> },
49
50 #[error("rate limit exceeded: {current} worktrees, maximum is {max}")]
51 RateLimitExceeded { current: usize, max: usize },
52
53 #[error("cannot delete own working directory")]
54 CannotDeleteCwd,
55
56 #[error("worktree is locked: {reason:?}")]
57 WorktreeLocked { reason: Option<String> },
58
59 #[error("cannot create worktree inside existing worktree at '{parent}'")]
60 NestedWorktree { parent: PathBuf },
61
62 #[error("git-crypt encrypted files detected after checkout — unlock the repository first")]
63 GitCryptLocked,
64
65 #[error("CoW (reflink) required but filesystem does not support it")]
66 ReflinkNotSupported,
67
68 #[error("invalid state transition from {from:?} to {to:?}")]
69 InvalidStateTransition {
70 from: WorktreeState,
71 to: WorktreeState,
72 },
73
74 #[error("worktree path not found in git registry: {0}")]
75 WorktreeNotInGitRegistry(PathBuf),
76
77 #[error("branch '{branch}' already exists at {branch_commit} but base was explicitly set to '{requested_base}' ({requested_commit}) — reset the branch or omit base")]
78 BranchExistsWithDifferentBase {
79 branch: String,
80 branch_commit: String,
81 requested_base: String,
82 requested_commit: String,
83 },
84
85 #[error("setup = true was requested but no EcosystemAdapter is registered on this Manager — use Manager::with_adapter()")]
86 SetupRequestedWithoutAdapter,
87
88 #[error("git command failed\n command: {command}\n stderr: {stderr}\n exit: {exit_code}")]
89 GitCommandFailed {
90 command: String,
91 stderr: String,
92 exit_code: i32,
93 },
94
95 #[error("state file corrupted: {reason} — rebuild from git worktree list")]
96 StateCorrupted { reason: String },
97
98 #[error("circuit breaker open: {consecutive_failures} consecutive git failures")]
99 CircuitBreakerOpen { consecutive_failures: u32 },
100
101 #[error("IO error: {0}")]
102 Io(#[from] std::io::Error),
103}