1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! Error types for the VCS engine.
use std::fmt;
/// All errors produced by the VCS engine.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum VcsError {
/// An object was not found in the store.
#[error("object not found: {id}")]
ObjectNotFound {
/// The missing object's ID.
id: crate::ObjectId,
},
/// A ref was not found.
#[error("ref not found: {name}")]
RefNotFound {
/// The missing ref name.
name: String,
},
/// HEAD is detached when a branch was expected.
#[error("HEAD is detached")]
DetachedHead,
/// Nothing is staged for commit.
#[error("nothing staged")]
NothingStaged,
/// Staging validation failed.
#[error("validation failed: {reasons:?}")]
ValidationFailed {
/// The validation errors.
reasons: Vec<String>,
},
/// Merge produced conflicts.
#[error("merge conflict: {count} conflict(s)")]
MergeConflicts {
/// The number of conflicts.
count: usize,
},
/// A branch already exists.
#[error("branch already exists: {name}")]
BranchExists {
/// The branch name.
name: String,
},
/// Not inside a panproto repository.
#[error("not a panproto repository")]
NotARepository,
/// An expected object had the wrong type.
#[error("expected {expected} object, found {found}")]
WrongObjectType {
/// The expected object type.
expected: &'static str,
/// The actual object type.
found: &'static str,
},
/// I/O error.
#[error("io error: {0}")]
Io(#[from] std::io::Error),
/// Serialization / deserialization error.
#[error("serialization error: {0}")]
Serialization(SerializationError),
/// Migration composition error.
#[error("compose error: {0}")]
Compose(#[from] panproto_mig::ComposeError),
/// No common ancestor found for merge.
#[error("no common ancestor found")]
NoCommonAncestor,
/// No path found between two commits.
#[error("no path found between commits")]
NoPath,
/// Branch is not fully merged into HEAD.
#[error("branch '{name}' is not fully merged")]
BranchNotMerged {
/// The branch name.
name: String,
},
/// A merge or cherry-pick is already in progress.
#[error("a {operation} is already in progress")]
OperationInProgress {
/// The operation type (e.g. "merge", "cherry-pick").
operation: String,
},
/// Feature is not yet implemented.
#[error("{feature} is not yet implemented")]
NotImplemented {
/// Description of the unimplemented feature.
feature: String,
},
/// Merge cannot fast-forward but --ff-only was requested.
#[error("cannot fast-forward; refusing to merge")]
FastForwardOnly,
/// Amend requested but no commits exist.
#[error("nothing to amend")]
NothingToAmend,
/// A tag already exists.
#[error("tag already exists: {name}")]
TagExists {
/// The tag name.
name: String,
},
}
/// Wrapper for serialization errors from rmp-serde.
#[derive(Debug)]
pub struct SerializationError(pub String);
impl fmt::Display for SerializationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
impl From<rmp_serde::encode::Error> for VcsError {
fn from(e: rmp_serde::encode::Error) -> Self {
Self::Serialization(SerializationError(e.to_string()))
}
}
impl From<rmp_serde::decode::Error> for VcsError {
fn from(e: rmp_serde::decode::Error) -> Self {
Self::Serialization(SerializationError(e.to_string()))
}
}