use std::path::PathBuf;
use thiserror::Error;
pub type Result<T> = std::result::Result<T, JjjError>;
#[derive(Error, Debug)]
pub enum JjjError {
#[error("Failed to execute jj command '{args}': {source}")]
JjIo {
args: String,
#[source]
source: std::io::Error,
},
#[error("jj command '{args}' failed:\n{stderr}")]
JjCommandFailed { args: String, stderr: String },
#[error("jj executable not found in PATH.\n\nPlease install Jujutsu:\n macOS: brew install jj\n From source: cargo install --git https://github.com/martinvonz/jj jj-cli")]
JjNotFound,
#[error("Not in a jj repository.\n\nPlease run this command from within a jj repository,\nor initialize one with: jj git init")]
NotInRepository,
#[error(
"jjj not initialized in this repository.\n\nRun 'jjj init' to set up project management."
)]
MetaBranchNotFound,
#[error("Problem {0} not found.\n\nUse 'jjj problem list' to see all problems.")]
ProblemNotFound(String),
#[error("Solution {0} not found.\n\nUse 'jjj solution list' to see all solutions.")]
SolutionNotFound(String),
#[error("Critique {0} not found.\n\nUse 'jjj critique list' to see all critiques.")]
CritiqueNotFound(String),
#[error("Milestone {0} not found.\n\nUse 'jjj milestone list' to see all milestones.")]
MilestoneNotFound(String),
#[error("Conflict detected in {0}. Run 'jj resolve' to fix conflicts in the working copy.")]
Conflict(String),
#[error("Invalid change ID: {0}")]
InvalidChangeId(String),
#[error("Cannot mark problem as solved: {0}")]
CannotSolveProblem(String),
#[error("Cannot approve solution: {0}")]
CannotApproveSolution(String),
#[error("Failed to parse {entity_type} '{entity_id}': {message}\n\nRun 'jjj db validate' to check for corrupted entities.")]
FrontmatterParse {
entity_type: String,
entity_id: String,
message: String,
},
#[error("Failed to parse JSON: {0}")]
JsonParse(#[from] serde_json::Error),
#[error("Failed to parse YAML: {0}")]
YamlParse(#[from] serde_yml::Error),
#[error("Failed to parse TOML: {0}")]
TomlParse(#[from] toml::de::Error),
#[error("Failed to serialize TOML: {0}")]
TomlSerialize(#[from] toml::ser::Error),
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("Path error: {0}")]
PathError(PathBuf),
#[error("TUI error: {0}")]
Tui(String),
#[error("Database error: {0}")]
Database(#[from] rusqlite::Error),
#[error("Selection cancelled: {0}")]
Cancelled(String),
#[error("{0}")]
AmbiguousMatch(String),
#[error("Entity not found: {0}")]
EntityNotFound(String),
#[error("Ambiguous ID prefix '{prefix}' matches multiple entities: {matches:?}")]
AmbiguousId {
prefix: String,
matches: Vec<String>,
},
#[error("gh CLI not found in PATH.\n\nPlease install GitHub CLI:\n macOS: brew install gh\n See: https://cli.github.com/")]
GhNotFound,
#[error("Failed to execute gh command '{args}': {source}")]
GhIo {
args: String,
#[source]
source: std::io::Error,
},
#[error("gh command '{args}' failed:\n{stderr}")]
GhCommandFailed { args: String, stderr: String },
#[error("GitHub authentication failed.\n\nRun 'gh auth login' to authenticate.")]
GhAuthFailed,
#[error("Could not detect GitHub repository.\n\nEnsure this repo has a GitHub remote, or set github.repo in config.")]
GhRepoNotDetected,
#[error("Sync conflict for entity {entity_id}: local state '{local_state}' vs remote state '{remote_state}'.\n{suggestion}")]
SyncConflict {
entity_id: String,
local_state: String,
remote_state: String,
suggestion: String,
},
#[error("Validation failed: {0}")]
Validation(String),
#[error("Configuration error: {0}")]
Config(String),
}