pending_op.rs

  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}