1use git::repository::RepoPath;
2use std::ops::Add;
3use sum_tree::{ContextLessSummary, Item, KeyedItem};
4use worktree::{PathKey, PathSummary};
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7pub enum GitStatus {
8 Staged,
9 Unstaged,
10 Reverted,
11 Unchanged,
12}
13
14#[derive(Clone, Debug, PartialEq, Eq)]
15pub struct PendingOps {
16 pub repo_path: RepoPath,
17 pub ops: Vec<PendingOp>,
18}
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq)]
21pub struct PendingOp {
22 pub id: PendingOpId,
23 pub git_status: GitStatus,
24 pub finished: bool,
25}
26
27#[derive(Clone, Debug)]
28pub struct PendingOpsSummary {
29 pub staged_count: usize,
30 pub staging_count: usize,
31}
32
33#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
34pub struct PendingOpId(pub u16);
35
36impl Item for PendingOps {
37 type Summary = PathSummary<PendingOpsSummary>;
38
39 fn summary(&self, _cx: ()) -> Self::Summary {
40 PathSummary {
41 max_path: self.repo_path.as_ref().clone(),
42 item_summary: PendingOpsSummary {
43 staged_count: self.staged() as usize,
44 staging_count: self.staging() as usize,
45 },
46 }
47 }
48}
49
50impl ContextLessSummary for PendingOpsSummary {
51 fn zero() -> Self {
52 Self {
53 staged_count: 0,
54 staging_count: 0,
55 }
56 }
57
58 fn add_summary(&mut self, summary: &Self) {
59 self.staged_count += summary.staged_count;
60 self.staging_count += summary.staging_count;
61 }
62}
63
64impl KeyedItem for PendingOps {
65 type Key = PathKey;
66
67 fn key(&self) -> Self::Key {
68 PathKey(self.repo_path.as_ref().clone())
69 }
70}
71
72impl Add<u16> for PendingOpId {
73 type Output = PendingOpId;
74
75 fn add(self, rhs: u16) -> Self::Output {
76 Self(self.0 + rhs)
77 }
78}
79
80impl From<u16> for PendingOpId {
81 fn from(id: u16) -> Self {
82 Self(id)
83 }
84}
85
86impl PendingOps {
87 pub fn new(path: &RepoPath) -> Self {
88 Self {
89 repo_path: path.clone(),
90 ops: Vec::new(),
91 }
92 }
93
94 pub fn max_id(&self) -> PendingOpId {
95 self.ops.last().map(|op| op.id).unwrap_or_default()
96 }
97
98 pub fn op_by_id(&self, id: PendingOpId) -> Option<&PendingOp> {
99 self.ops.iter().find(|op| op.id == id)
100 }
101
102 pub fn op_by_id_mut(&mut self, id: PendingOpId) -> Option<&mut PendingOp> {
103 self.ops.iter_mut().find(|op| op.id == id)
104 }
105
106 /// File is staged if the last job is finished and has status Staged.
107 pub fn staged(&self) -> bool {
108 if let Some(last) = self.ops.last() {
109 if last.git_status == GitStatus::Staged && last.finished {
110 return true;
111 }
112 }
113 false
114 }
115
116 /// File is staged if the last job is not finished and has status Staged.
117 pub fn staging(&self) -> bool {
118 if let Some(last) = self.ops.last() {
119 if last.git_status == GitStatus::Staged && !last.finished {
120 return true;
121 }
122 }
123 false
124 }
125}