git_simple_encrypt/error.rs
1//! Crate-wide error type.
2//!
3//! Library code returns [`Error`] (typed via `thiserror`) so downstream users
4//! can match on error kinds. Internal helpers use other dedicated variants;
5//! [`Error::Other`] serves as a catch-all for opaque error messages from the
6//! binary layer (git config, path absolutization, etc.).
7
8use std::path::PathBuf;
9
10use thiserror::Error;
11
12/// The error type returned by all public library functions.
13#[derive(Debug, Error)]
14pub enum Error {
15 /// `repo` argument was not an absolute path (lib callers must absolutize).
16 #[error("repository path must be absolute: {0}")]
17 RepoPathNotAbsolute(PathBuf),
18
19 /// Repository directory does not exist.
20 #[error("repo not found: {0}")]
21 RepoNotFound(PathBuf),
22
23 /// Repository path is not a directory.
24 #[error("not a directory: {0}")]
25 NotADirectory(PathBuf),
26
27 /// Path supplied for the crypt list does not exist on disk.
28 #[error("file or directory does not exist: {0}")]
29 PathNotExist(PathBuf),
30
31 /// Expected a repo-relative path but got an absolute one.
32 #[error("expected repo-relative path, got absolute: {0}")]
33 PathNotRelative(PathBuf),
34
35 /// Master key/password is empty.
36 #[error("key must not be empty")]
37 EmptyKey,
38
39 /// User entered an empty password interactively.
40 #[error("password must not be empty")]
41 EmptyPassword,
42
43 /// Operation had no target files to act on.
44 #[error("no file to {0}")]
45 NoFile(&'static str),
46
47 /// File does not start with the `GITSE` magic / supported version.
48 #[error("invalid magic bytes")]
49 InvalidMagic,
50
51 /// Header advertises an unsupported format version.
52 #[error("unsupported version: {0}")]
53 UnsupportedVersion(u8),
54
55 /// Header advertises an unsupported encryption algorithm.
56 #[error("unsupported encryption algorithm: {0}")]
57 UnsupportedAlgo(u8),
58
59 /// Header could not be parsed / validated.
60 #[error("corrupt header in {0}")]
61 CorruptHeader(PathBuf),
62
63 /// XChaCha20-Poly1305 encryption failure.
64 #[error("encryption failed: {0}")]
65 EncryptFailed(String),
66
67 /// XChaCha20-Poly1305 decryption failure (wrong password, corrupt or
68 /// tampered data are all reported identically by AEAD).
69 #[error("decryption failed (wrong password, corrupt, or tampered data): {0}")]
70 DecryptFailed(String),
71
72 /// Argon2 key derivation failure.
73 #[error("Argon2 key derivation failed: {0}")]
74 Argon2(String),
75
76 /// Encrypted chunk is missing its ciphertext.
77 #[error("truncated chunk: nonce present but no ciphertext follows")]
78 TruncatedChunk,
79
80 /// Encrypted file ended without a final chunk.
81 #[error("file truncation detected! the ciphertext is incomplete")]
82 FileTruncated,
83
84 /// Atomic temp-file persist failed.
85 #[error("failed to persist atomic write to {0}: {1}")]
86 AtomicPersist(PathBuf, String),
87
88 /// Underlying `git` invocation failed.
89 #[error("git command failed: {0}")]
90 Git(String),
91
92 /// A pre-commit hook already exists at the target path.
93 #[error("a pre-commit hook already exists at {0}; remove it manually before installing")]
94 HookExists(PathBuf),
95
96 /// `check` found unencrypted files. The count is `(unencrypted, total)`.
97 #[error("{0} out of {1} files are not encrypted")]
98 FilesNotEncrypted(usize, usize),
99
100 /// Config file parse/serialize error.
101 #[error("config error: {0}")]
102 Config(String),
103
104 /// Generic I/O error.
105 #[error(transparent)]
106 Io(#[from] std::io::Error),
107
108 /// Rkyv (de)serialization failure for the salt cache.
109 #[error("salt cache serialization error: {0}")]
110 SaltCache(String),
111
112 /// Anything else — an opaque error message.
113 #[error("{0}")]
114 Other(String),
115}
116
117/// Convenience alias used throughout the crate.
118pub type Result<T, E = Error> = std::result::Result<T, E>;