use crate::input::InputResolveError;
use crate::model::{GamePath, GamePathBuf};
use std::fmt;
use std::path::{Path, PathBuf};
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum MergeErrorSubject {
Game(GamePathBuf),
Host(PathBuf),
Named(String),
}
impl fmt::Display for MergeErrorSubject {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Game(path) => fmt::Display::fmt(path, f),
Self::Host(path) => fmt::Display::fmt(&path.display(), f),
Self::Named(name) => f.write_str(name),
}
}
}
impl From<&GamePath> for MergeErrorSubject {
fn from(path: &GamePath) -> Self {
Self::Game(path.to_owned())
}
}
impl From<&Path> for MergeErrorSubject {
fn from(path: &Path) -> Self {
Self::Host(path.to_path_buf())
}
}
#[derive(Debug)]
pub enum MergeError {
Cancelled,
ReplacementAuthorizationRequired { path: PathBuf },
ReplacementTargetChanged { path: PathBuf },
AnalyzedArtifactChanged,
AnalyzedOutputChanged { path: PathBuf },
InputResolve { path: PathBuf, message: String },
Parse {
subject: Option<MergeErrorSubject>,
message: String,
},
Validation {
subject: Option<MergeErrorSubject>,
message: String,
},
Io(std::io::Error),
}
impl fmt::Display for MergeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Cancelled => write!(f, "merge analysis cancelled"),
Self::ReplacementAuthorizationRequired { path } => write!(
f,
"commit requires explicit authorization to replace non-empty output {}",
path.display()
),
Self::ReplacementTargetChanged { path } => write!(
f,
"merge output changed after replacement confirmation: {}",
path.display()
),
Self::AnalyzedArtifactChanged => {
write!(f, "frozen merge analysis artifacts changed before commit")
}
Self::AnalyzedOutputChanged { path } => write!(
f,
"output used by merge analysis changed before commit: {}",
path.display()
),
Self::InputResolve { message, .. } => {
write!(f, "input resolve: {message}")
}
Self::Parse { subject, message } => {
if let Some(subject) = subject {
write!(f, "parse error in {subject}: {message}")
} else {
write!(f, "parse error: {message}")
}
}
Self::Validation { subject, message } => {
if let Some(subject) = subject {
write!(f, "validation error in {subject}: {message}")
} else {
write!(f, "validation error: {message}")
}
}
Self::Io(e) => write!(f, "io error: {e}"),
}
}
}
impl std::error::Error for MergeError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Io(e) => Some(e),
_ => None,
}
}
}
impl From<std::io::Error> for MergeError {
fn from(e: std::io::Error) -> Self {
Self::Io(e)
}
}
impl From<InputResolveError> for MergeError {
fn from(e: InputResolveError) -> Self {
Self::InputResolve {
path: e.path,
message: e.message,
}
}
}