Skip to main content

clankerdiff_git/
error.rs

1//! Errors produced by native Git and filesystem operations.
2
3use clankerdiff_core::{DiffError, RepoPathError};
4use std::{io, path::PathBuf};
5
6/// An error from repository discovery, Git execution, or worktree access.
7#[derive(Debug, thiserror::Error)]
8pub enum GitError {
9    /// The supplied location is not inside a Git worktree.
10    #[error("path is not inside a Git worktree")]
11    NotRepository,
12    /// Git returned a repository root that cannot be represented as UTF-8.
13    #[error("repository root is not valid UTF-8")]
14    UnsupportedRepositoryPath,
15    /// A repository-relative path failed validation.
16    #[error("invalid repository path: {0}")]
17    InvalidPath(#[from] RepoPathError),
18    /// A validated path resolved outside the repository root.
19    #[error("repository path escapes the worktree: {path}")]
20    PathEscapesRepository {
21        /// The rejected path.
22        path: String,
23    },
24    /// A file operation unexpectedly targeted a directory.
25    #[error("repository path is not a file: {path}")]
26    NotAFile {
27        /// The rejected path.
28        path: String,
29    },
30    /// A commit message was empty or only whitespace.
31    #[error("commit message must not be empty")]
32    EmptyCommitMessage,
33    /// The Git process could not be started or awaited.
34    #[error("could not execute git operation `{operation}`: {source}")]
35    Spawn {
36        /// A non-sensitive operation label.
37        operation: &'static str,
38        /// The subprocess I/O error.
39        #[source]
40        source: io::Error,
41    },
42    /// Git exited unsuccessfully.
43    ///
44    /// `stderr` is retained for diagnostics, but omitted from `Display` to
45    /// avoid leaking file contents or other sensitive command output.
46    #[error("git operation `{operation}` failed with status {status:?}")]
47    CommandFailed {
48        /// A non-sensitive operation label.
49        operation: &'static str,
50        /// The process exit code, when one was available.
51        status: Option<i32>,
52        /// Git's standard error bytes, decoded lossily.
53        stderr: String,
54    },
55    /// A filesystem operation failed.
56    #[error("filesystem operation failed for {path}")]
57    Io {
58        /// The affected host path.
59        path: PathBuf,
60        /// The filesystem error.
61        #[source]
62        source: io::Error,
63    },
64    /// A source version exceeded the per-file capture limit.
65    #[error("source version is too large ({bytes} bytes)")]
66    SourceTooLarge { bytes: u64 },
67    /// Repository metadata or worktree content changed during capture.
68    #[error("repository changed while capturing the snapshot")]
69    UnstableSnapshot,
70    /// Core diff normalization failed.
71    #[error("could not normalize Git snapshot: {0}")]
72    Diff(#[from] DiffError),
73}