1pub mod backend_id;
4pub mod models;
5
6pub use crate::backend_id::BackendId;
7
8#[doc(hidden)]
9pub use log as __log;
10
11#[cfg(feature = "backend-registry")]
12pub mod backend_descriptor;
13
14#[cfg(feature = "plugin-protocol")]
15pub mod plugin_protocol;
16
17#[cfg(feature = "plugin-protocol")]
18pub mod plugin_stdio;
19
20#[cfg(feature = "plugin-protocol")]
21pub mod host;
22
23#[cfg(feature = "plugin-protocol")]
24pub mod plugin_runtime;
25
26#[cfg(feature = "plugin-protocol")]
27pub mod events;
28
29#[cfg(feature = "plugin-protocol")]
30mod plugin_logging;
31
32#[doc(hidden)]
33pub fn __ensure_plugin_logging_initialized() {
34 #[cfg(feature = "plugin-protocol")]
35 crate::plugin_logging::ensure_initialized();
36}
37
38#[macro_export]
39macro_rules! trace {
40 (target: $target:expr, $($arg:tt)+) => {{
41 $crate::__ensure_plugin_logging_initialized();
42 $crate::__log::trace!(target: $target, $($arg)+);
43 }};
44 ($($arg:tt)+) => {{
45 $crate::__ensure_plugin_logging_initialized();
46 $crate::__log::trace!($($arg)+);
47 }};
48}
49
50#[macro_export]
51macro_rules! debug {
52 (target: $target:expr, $($arg:tt)+) => {{
53 $crate::__ensure_plugin_logging_initialized();
54 $crate::__log::debug!(target: $target, $($arg)+);
55 }};
56 ($($arg:tt)+) => {{
57 $crate::__ensure_plugin_logging_initialized();
58 $crate::__log::debug!($($arg)+);
59 }};
60}
61
62#[macro_export]
63macro_rules! info {
64 (target: $target:expr, $($arg:tt)+) => {{
65 $crate::__ensure_plugin_logging_initialized();
66 $crate::__log::info!(target: $target, $($arg)+);
67 }};
68 ($($arg:tt)+) => {{
69 $crate::__ensure_plugin_logging_initialized();
70 $crate::__log::info!($($arg)+);
71 }};
72}
73
74#[macro_export]
75macro_rules! warn {
76 (target: $target:expr, $($arg:tt)+) => {{
77 $crate::__ensure_plugin_logging_initialized();
78 $crate::__log::warn!(target: $target, $($arg)+);
79 }};
80 ($($arg:tt)+) => {{
81 $crate::__ensure_plugin_logging_initialized();
82 $crate::__log::warn!($($arg)+);
83 }};
84}
85
86#[macro_export]
87macro_rules! error {
88 (target: $target:expr, $($arg:tt)+) => {{
89 $crate::__ensure_plugin_logging_initialized();
90 $crate::__log::error!(target: $target, $($arg)+);
91 }};
92 ($($arg:tt)+) => {{
93 $crate::__ensure_plugin_logging_initialized();
94 $crate::__log::error!($($arg)+);
95 }};
96}
97
98#[cfg(feature = "plugin-protocol")]
99pub use crate::plugin_protocol::{PluginMessage, RpcRequest, RpcResponse};
100
101#[cfg(feature = "vcs")]
102pub use crate::models::{Capabilities, FetchOptions, OnEvent};
103
104#[cfg(feature = "vcs")]
105use std::path::{Path, PathBuf};
106
107#[cfg(feature = "vcs")]
108#[derive(thiserror::Error, Debug)]
109pub enum VcsError {
110 #[error("not a repository: {0}")]
111 NotARepo(String),
112 #[error("branch not found: {0}")]
113 NoSuchBranch(String),
114 #[error("no upstream configured")]
115 NoUpstream,
116 #[error("nothing to commit")]
117 NothingToCommit,
118 #[error("non-fast-forward; merge or rebase required")]
119 NonFastForward,
120 #[error("unsupported backend: {0}")]
121 Unsupported(BackendId),
122 #[error("io: {0}")]
123 Io(#[from] std::io::Error),
124 #[error("{backend}: {msg}")]
125 Backend { backend: BackendId, msg: String },
126}
127
128#[cfg(feature = "vcs")]
129pub type Result<T> = std::result::Result<T, VcsError>;
130
131#[cfg(feature = "vcs")]
133pub trait Vcs: Send + Sync {
134 fn id(&self) -> BackendId;
135 fn caps(&self) -> models::Capabilities;
136
137 fn open(path: &Path) -> Result<Self>
139 where
140 Self: Sized;
141 fn clone(url: &str, dest: &Path, on: Option<models::OnEvent>) -> Result<Self>
142 where
143 Self: Sized;
144
145 fn workdir(&self) -> &Path;
147
148 fn current_branch(&self) -> Result<Option<String>>;
150 fn branches(&self) -> Result<Vec<models::BranchItem>>;
151
152 #[deprecated(
153 since = "0.1.0",
154 note = "This function is being replaced by `branches`."
155 )]
156 fn local_branches(&self) -> Result<Vec<String>>;
157 fn create_branch(&self, name: &str, checkout: bool) -> Result<()>;
158 fn checkout_branch(&self, name: &str) -> Result<()>;
159
160 fn ensure_remote(&self, name: &str, url: &str) -> Result<()>;
162 fn list_remotes(&self) -> Result<Vec<(String, String)>>;
163 fn remove_remote(&self, name: &str) -> Result<()>;
164 fn fetch(&self, remote: &str, refspec: &str, on: Option<models::OnEvent>) -> Result<()>;
165 fn fetch_with_options(
166 &self,
167 remote: &str,
168 refspec: &str,
169 _opts: models::FetchOptions,
170 on: Option<models::OnEvent>,
171 ) -> Result<()> {
172 self.fetch(remote, refspec, on)
173 }
174 fn push(&self, remote: &str, refspec: &str, on: Option<models::OnEvent>) -> Result<()>;
175 fn pull_ff_only(&self, remote: &str, branch: &str, on: Option<models::OnEvent>) -> Result<()>;
176
177 fn commit(&self, message: &str, name: &str, email: &str, paths: &[PathBuf]) -> Result<String>;
179 fn commit_index(&self, message: &str, name: &str, email: &str) -> Result<String>;
180 fn status_summary(&self) -> Result<models::StatusSummary>;
181 fn status_payload(&self) -> Result<models::StatusPayload>;
182 fn log_commits(&self, query: &models::LogQuery) -> Result<Vec<models::CommitItem>>;
183 fn diff_file(&self, path: &Path) -> Result<Vec<String>>;
184 fn diff_commit(&self, rev: &str) -> Result<Vec<String>>;
185
186 fn conflict_details(&self, _path: &Path) -> Result<models::ConflictDetails> {
188 Err(VcsError::Unsupported(self.id()))
189 }
190 fn checkout_conflict_side(&self, _path: &Path, _side: models::ConflictSide) -> Result<()> {
191 Err(VcsError::Unsupported(self.id()))
192 }
193 fn write_merge_result(&self, _path: &Path, _content: &[u8]) -> Result<()> {
194 Err(VcsError::Unsupported(self.id()))
195 }
196
197 fn stage_patch(&self, patch: &str) -> Result<()>;
198 fn discard_paths(&self, paths: &[PathBuf]) -> Result<()>;
199 fn apply_reverse_patch(&self, patch: &str) -> Result<()>;
200
201 fn delete_branch(&self, name: &str, force: bool) -> Result<()>;
203 fn rename_branch(&self, old: &str, new: &str) -> Result<()>;
204 fn merge_into_current(&self, name: &str) -> Result<()>;
205 fn merge_into_current_with_message(&self, name: &str, message: Option<&str>) -> Result<()> {
206 let _ = message;
207 self.merge_into_current(name)
208 }
209 fn merge_abort(&self) -> Result<()> {
210 Err(VcsError::Unsupported(self.id()))
211 }
212 fn merge_continue(&self) -> Result<()> {
213 Err(VcsError::Unsupported(self.id()))
214 }
215 fn merge_in_progress(&self) -> Result<bool> {
216 Ok(false)
217 }
218 fn set_branch_upstream(&self, _branch: &str, _upstream: &str) -> Result<()> {
219 Err(VcsError::Unsupported(self.id()))
220 }
221 fn branch_upstream(&self, _branch: &str) -> Result<Option<String>> {
222 Err(VcsError::Unsupported(self.id()))
223 }
224
225 fn hard_reset_head(&self) -> Result<()>;
227 fn reset_soft_to(&self, _rev: &str) -> Result<()> {
228 Err(VcsError::Unsupported(self.id()))
229 }
230
231 fn get_identity(&self) -> Result<Option<(String, String)>>;
233 fn set_identity_local(&self, name: &str, email: &str) -> Result<()>;
234
235 fn stash_list(&self) -> Result<Vec<models::StashItem>> {
237 Err(VcsError::Unsupported(self.id()))
238 }
239 fn stash_push(
240 &self,
241 _message: &str,
242 _include_untracked: bool,
243 _paths: &[PathBuf],
244 ) -> Result<()> {
245 Err(VcsError::Unsupported(self.id()))
246 }
247 fn stash_apply(&self, _selector: &str) -> Result<()> {
248 Err(VcsError::Unsupported(self.id()))
249 }
250 fn stash_pop(&self, _selector: &str) -> Result<()> {
251 Err(VcsError::Unsupported(self.id()))
252 }
253 fn stash_drop(&self, _selector: &str) -> Result<()> {
254 Err(VcsError::Unsupported(self.id()))
255 }
256 fn stash_show(&self, _selector: &str) -> Result<Vec<String>> {
257 Err(VcsError::Unsupported(self.id()))
258 }
259
260 fn lfs_fetch(&self) -> Result<()> {
262 Err(VcsError::Unsupported(self.id()))
263 }
264 fn lfs_pull(&self) -> Result<()> {
265 Err(VcsError::Unsupported(self.id()))
266 }
267 fn lfs_prune(&self) -> Result<()> {
268 Err(VcsError::Unsupported(self.id()))
269 }
270 fn lfs_track(&self, _paths: &[PathBuf]) -> Result<()> {
271 Err(VcsError::Unsupported(self.id()))
272 }
273 fn lfs_untrack(&self, _paths: &[PathBuf]) -> Result<()> {
274 Err(VcsError::Unsupported(self.id()))
275 }
276 fn lfs_is_tracked(&self, _path: &Path) -> Result<bool> {
277 Err(VcsError::Unsupported(self.id()))
278 }
279
280 fn cherry_pick(&self, _rev: &str) -> Result<()> {
282 Err(VcsError::Unsupported(self.id()))
283 }
284 fn revert_commit(&self, _rev: &str, _no_edit: bool) -> Result<()> {
285 Err(VcsError::Unsupported(self.id()))
286 }
287}