khive_vcs/error.rs
1//! Error types for the VCS layer.
2//!
3//! Remote-server and custom-push/pull error variants (`RemoteUnreachable`,
4//! `AuthFailed`, `NonFastForward`, `MergeRequired`) were removed: git is the
5//! remote protocol; there is no custom `khive-sync` server.
6//! `MergeNotImplemented` was removed because the custom merge engine is
7//! superseded for v1.
8
9use thiserror::Error;
10
11use crate::types::SnapshotId;
12
13/// Errors that can occur in the khive VCS layer (snapshot hashing, NDJSON sync, remote fetch).
14#[derive(Debug, Error)]
15pub enum VcsError {
16 /// The archive stored at the remote has a different hash than expected.
17 /// Indicates corruption or tampering.
18 #[error("hash mismatch: expected {expected}, actual {actual}")]
19 HashMismatch {
20 expected: SnapshotId,
21 actual: SnapshotId,
22 },
23
24 /// `checkout` was blocked because there are uncommitted changes.
25 /// Pass `force: true` to discard them.
26 #[error("uncommitted changes: {count} entities/edges modified since last commit")]
27 UncommittedChanges { count: usize },
28
29 /// A `SnapshotId` string failed validation.
30 #[error("invalid snapshot id: {0}")]
31 InvalidSnapshotId(String),
32
33 /// A branch name failed validation (must match `^[a-zA-Z0-9_-]{1,64}$`).
34 #[error("invalid branch name: {0:?}")]
35 InvalidBranchName(String),
36
37 /// A remote name failed validation (must be a single path segment
38 /// matching `[A-Za-z0-9._-]+`, and not `.` or `..`). Rejected before any
39 /// filesystem path is built from it, to prevent path traversal into
40 /// `.khive/kg/remotes/`.
41 #[error("invalid remote name {0:?}: must be one path segment [A-Za-z0-9._-]+ and not . or ..")]
42 InvalidRemoteName(String),
43
44 /// An underlying storage operation failed.
45 #[error("storage: {0}")]
46 Storage(String),
47
48 /// JSON serialization or deserialization failed.
49 #[error("json: {0}")]
50 Json(#[from] serde_json::Error),
51
52 /// An I/O operation failed (file system).
53 #[error("io: {0}")]
54 Io(#[from] std::io::Error),
55
56 /// An unexpected internal error.
57 #[error("internal: {0}")]
58 Internal(String),
59}
60
61impl From<khive_runtime::error::RuntimeError> for VcsError {
62 fn from(e: khive_runtime::error::RuntimeError) -> Self {
63 VcsError::Storage(e.to_string())
64 }
65}