1use thiserror::Error;
7
8#[derive(Error, Debug)]
13pub enum TrackError {
14 #[error("Database error: {0}")]
16 Database(#[from] rusqlite::Error),
17
18 #[error("No active task. Run 'track new' or 'track switch' first.")]
19 NoActiveTask,
20
21 #[error("Task #{0} not found")]
22 TaskNotFound(i64),
23
24 #[error("Task #{0} is archived")]
25 TaskArchived(i64),
26
27 #[error("Task name cannot be empty")]
28 EmptyTaskName,
29
30 #[error("TODO content cannot be empty")]
31 EmptyTodoContent,
32
33 #[error("Scrap content cannot be empty")]
34 EmptyScrapContent,
35
36 #[error("Workspaces have uncommitted changes: {0:?}")]
37 UncommittedWorkspaces(Vec<String>),
38
39 #[error("Ticket '{0}' is already linked to task #{1}")]
40 DuplicateTicket(String, i64),
41
42 #[error("Invalid ticket ID format: {0}")]
43 InvalidTicketFormat(String),
44
45 #[error("TODO #{0} not found")]
46 TodoNotFound(i64),
47
48 #[error("Worktree #{0} not found")]
49 WorktreeNotFound(i64),
50
51 #[error("Invalid status: {0}")]
52 InvalidStatus(String),
53
54 #[error("Cannot transition from '{from}' to '{to}'")]
55 InvalidStatusTransition { from: String, to: String },
56
57 #[error("TODO cannot be reopened from '{from}'. Add a new TODO instead.")]
58 TodoReopenForbidden { from: String },
59
60 #[error("Use 'track todo done <id>' to complete a TODO (merges JJ workspace if present).")]
61 TodoCompleteRequiresDoneCommand,
62
63 #[error(
64 "Workspace was merged (bookmark: {bookmark}) but failed to mark TODO #{todo_index} as done: {detail}"
65 )]
66 TodoCompletionDbFailed {
67 todo_index: i64,
68 bookmark: String,
69 detail: String,
70 },
71
72 #[error("JJ error: {0}")]
73 Jj(String),
74
75 #[error("Path '{0}' is not a JJ repository")]
76 NotJjRepository(String),
77
78 #[error("Bookmark '{0}' already exists")]
79 BookmarkExists(String),
80
81 #[error("Invalid URL format: {0}")]
82 InvalidUrl(String),
83
84 #[error("No repositories registered for this task")]
85 NoRepositoriesRegistered,
86
87 #[error("Failed to check status for {0}")]
88 FailedRepoStatusCheck(String),
89
90 #[error("Repository {0} has pending changes in the base workspace. Please clean before sync.")]
91 RepoHasPendingChanges(String),
92
93 #[error("IO error: {0}")]
94 Io(#[from] std::io::Error),
95
96 #[error("Operation cancelled by user")]
97 #[allow(dead_code)]
98 Cancelled,
99
100 #[error("{0}")]
101 Other(String),
102}
103
104pub type Result<T> = std::result::Result<T, TrackError>;