1use super::*;
2#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
3pub struct WorktreeIdentity {
4 pub target: TargetIdentity,
5 pub canonical_path: TargetPath,
6 pub common_git_directory_identity: Vec<u8>,
7}
8#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
9pub enum GitHead {
10 Branch { name: Vec<u8>, oid: String },
11 Detached(String),
12 Unborn(Vec<u8>),
13}
14#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
15pub struct GitExpectedState {
16 pub head: GitHead,
17 pub index_fingerprint: [u8; 32],
18 pub worktree_fingerprint: [u8; 32],
19}
20#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
21pub struct GitEntry {
22 pub path: TargetPath,
23 pub previous_path: Option<TargetPath>,
24 pub status: String,
25}
26#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
27pub struct GitSnapshot {
28 pub worktree: WorktreeIdentity,
29 pub state: GitExpectedState,
30 pub staged: Vec<GitEntry>,
31 pub unstaged: Vec<GitEntry>,
32 pub untracked: Vec<GitEntry>,
33 pub conflicts: Vec<GitEntry>,
34}
35#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
36pub enum DiffSource {
37 Index,
38 Worktree,
39 Commit(String),
40}
41#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
42pub struct DiffRequest {
43 pub worktree: WorktreeIdentity,
44 pub path: TargetPath,
45 pub source: DiffSource,
46}
47#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
48pub enum DiffContent {
49 Text,
50 Binary,
51 Unavailable(String),
52}
53#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
54pub enum DiffChange {
55 Modified,
56 Added,
57 Deleted,
58 Renamed,
59 Conflicted,
60}
61#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
62pub struct DiffSnapshot {
63 pub source: DiffSource,
64 pub content: DiffContent,
65 pub change: DiffChange,
66 pub previous_path: Option<TargetPath>,
67 pub expected: GitExpectedState,
68 pub bytes: Vec<u8>,
69}
70#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
71pub struct HistoryFilter {
72 pub authored_since: Option<i64>,
73 pub text: String,
74}
75#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
76pub struct HistoryQuery {
77 pub worktree: WorktreeIdentity,
78 pub ref_filter: Vec<Vec<u8>>,
79 pub cursor: Option<Vec<u8>>,
80 #[serde(default, skip_serializing_if = "Option::is_none")]
81 pub filter: Option<HistoryFilter>,
82}
83#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
84pub struct GraphCommit {
85 pub lane: u32,
86 pub parent_lanes: Vec<u32>,
87 pub author: String,
88 pub authored_at: String,
89 pub message: String,
90 pub oid: String,
91 pub parents: Vec<String>,
92 pub decorations: Vec<Vec<u8>>,
93 pub subject: String,
94}
95#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
96pub struct GraphPage {
97 pub commits: Vec<GraphCommit>,
98 pub continuation_edges: Vec<(String, String)>,
99 pub next_cursor: Option<Vec<u8>>,
100}
101#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
102pub enum GitMutation {
103 Repository(RepositoryAction),
104 Stage(Vec<TargetPath>),
105 Unstage(Vec<TargetPath>),
106 Commit { message: String },
107 Checkout { reference: Vec<u8> },
108 Fetch { remote: Vec<u8> },
109 Push { remote: Vec<u8>, reference: Vec<u8> },
110 PullFastForward { remote: Vec<u8>, reference: Vec<u8> },
111}
112#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
113pub struct GitMutationRequest {
114 pub operation: OperationID,
115 pub worktree: WorktreeIdentity,
116 pub expected: GitExpectedState,
117 pub command: GitMutation,
118}
119
120#[derive(Clone, Debug, PartialEq, Eq)]
121pub struct GitSaveApproval {
122 pub operation: OperationID,
123 pub request_digest: [u8; 32],
124 pub actor: WorkspaceLease,
125}
126
127#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
128pub enum GitNetworkAction {
129 Fetch,
130 Push,
131 PullFastForward,
132}
133#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
134pub struct GitNetworkIntent {
135 pub action: GitNetworkAction,
136 pub remote: Vec<u8>,
137 pub reference: Vec<u8>,
138 pub endpoint_fingerprint: Option<[u8; 32]>,
140 #[serde(default)]
142 pub push_mapping_unconfigured: bool,
143}
144#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
145pub struct GitNetworkObservation {
146 pub remote_oid: Option<String>,
148 pub remote_refs_fingerprint: [u8; 32],
149 pub local_refs_fingerprint: [u8; 32],
150 pub fetch_head_fingerprint: [u8; 32],
151 pub fetch_head_oids: Vec<u8>,
153}
154
155#[derive(Clone, Debug, PartialEq, Eq)]
156pub enum WorktreeChangePhase {
157 Resolving,
158 NeedsSave,
159 Saving,
160 Running,
161 Refreshing,
162}
163#[derive(Clone, Debug)]
164pub struct WorktreeChangeState {
165 pub phase: WorktreeChangePhase,
166 pub documents: Vec<DocumentID>,
167 pub message: String,
168}
169
170#[derive(serde::Serialize, serde::Deserialize, Clone, Copy, Debug, PartialEq, Eq)]
172pub enum GitRead {
173 Upstream,
174 StatusShort,
175 StatusPorcelain,
176 Head,
177 HeadSymbolic,
178 Inside,
179 Refs,
180 Stashes,
181 Remotes,
182 Diff,
183 StagedDiff,
184 Log,
185 Graph,
186}
187#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
188pub struct GitReadOutput {
189 pub stdout: Vec<u8>,
190 pub stderr: Vec<u8>,
191 pub success: bool,
192}
193
194impl GitRead {
195 pub fn from_args(args: &[&str]) -> Option<GitRead> {
196 Some(match args {
197 ["status", "--short", "--branch"] => GitRead::StatusShort,
198 ["status", "--porcelain=v1", "-z", "--untracked-files=all"] => GitRead::StatusPorcelain,
199 ["rev-parse", "--abbrev-ref", "HEAD"] => GitRead::Head,
200 ["symbolic-ref", "--quiet", "--short", "HEAD"] => GitRead::HeadSymbolic,
201 ["rev-parse", "--is-inside-work-tree"] => GitRead::Inside,
202 [
203 "for-each-ref",
204 "--format=%(refname)%00%(HEAD)%00%(symref)",
205 "refs/heads",
206 "refs/remotes",
207 "refs/tags",
208 ] => GitRead::Refs,
209 ["stash", "list", "--format=%gd: %s"] => GitRead::Stashes,
210 ["remote", "-v"] => GitRead::Remotes,
211 ["diff", "--no-ext-diff", "--"] => GitRead::Diff,
212 ["diff", "--cached", "--no-ext-diff", "--"] => GitRead::StagedDiff,
213 ["log", "-30", "--oneline", "--decorate"] => GitRead::Log,
214 ["log", "--graph", "--oneline", "--decorate", "--all", "-100"] => GitRead::Graph,
215 _ => return None,
216 })
217 }
218}
219
220#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
221pub struct GitRef {
222 pub name: Vec<u8>,
223 pub oid: String,
224 pub peeled_oid: Option<String>,
225 pub current: bool,
226}
227#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
228pub struct GitStash {
229 pub selector: Vec<u8>,
230 pub oid: String,
231 pub subject: String,
232}
233#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
234pub struct GitWorktree {
235 pub path: TargetPath,
236 pub branch: Option<Vec<u8>>,
237}
238#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
239pub struct GitMergeState {
240 pub heads: Vec<String>,
241 pub session: Option<OperationID>,
242 pub message: String,
243 pub conflicts: Vec<TargetPath>,
244 pub error: Option<String>,
245}
246#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
247pub struct GitRepositorySnapshot {
248 pub worktree: WorktreeIdentity,
249 pub state: GitExpectedState,
250 pub refs: Vec<GitRef>,
251 pub changes: Vec<GitEntry>,
252 pub stashes: Vec<GitStash>,
253 pub remotes: Vec<Vec<u8>>,
254 pub worktrees: Vec<GitWorktree>,
255 pub merge: Option<GitMergeState>,
256}
257
258#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
259pub struct CommitQuery {
260 pub worktree: WorktreeIdentity,
261 pub oid: String,
262 pub cursor: Option<u64>,
263}
264#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
265pub struct GitCommitFile {
266 pub path: TargetPath,
267 pub previous_path: Option<TargetPath>,
268 pub change: DiffChange,
269}
270#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
271pub struct CommitPage {
272 pub oid: String,
273 pub parents: Vec<String>,
274 pub author: String,
275 pub email: String,
276 pub authored_at: String,
277 pub message: String,
278 pub files: Vec<GitCommitFile>,
279 pub next_cursor: Option<u64>,
280}
281
282#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
283#[serde(deny_unknown_fields)]
284pub enum RepositoryAction {
285 Merge {
286 source_ref: Vec<u8>,
287 source_oid: String,
288 },
289 ContinueMerge {
290 session: Option<OperationID>,
291 expected_heads: Vec<String>,
292 message: String,
293 },
294 AbortMerge {
295 session: OperationID,
296 },
297 SwitchBranch {
298 name: Vec<u8>,
299 expected_oid: String,
300 },
301 CreateBranch {
302 name: Vec<u8>,
303 source_ref: Vec<u8>,
304 start_oid: String,
305 },
306 RenameBranch {
307 name: Vec<u8>,
308 new_name: Vec<u8>,
309 expected_oid: String,
310 },
311 CreateTag {
312 name: Vec<u8>,
313 source_ref: Vec<u8>,
314 start_oid: String,
315 },
316 DeleteBranch {
317 name: Vec<u8>,
318 expected_oid: String,
319 },
320}
321
322impl GitMutation {
323 pub fn changes_worktree(&self) -> bool {
324 matches!(
325 self,
326 Self::Checkout { .. }
327 | Self::PullFastForward { .. }
328 | Self::Repository(
329 RepositoryAction::SwitchBranch { .. }
330 | RepositoryAction::Merge { .. }
331 | RepositoryAction::ContinueMerge { .. }
332 | RepositoryAction::AbortMerge { .. }
333 )
334 )
335 }
336}
337
338#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
339pub enum RepositoryOutcome {
340 RefsUpdated,
341 CheckedOut,
342 Merged { oid: String },
343 MergePending { merge: GitMergeState },
344 MergeAborted,
345}