Skip to main content

iso_code/
error.rs

1use std::path::PathBuf;
2use crate::types::WorktreeState;
3
4/// Errors returned by iso-code operations.
5#[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}