@@ -1,6 +1,7 @@
pub mod branch_diff;
mod conflict_set;
pub mod git_traversal;
+pub mod pending_op;
use crate::{
ProjectEnvironment, ProjectItem, ProjectPath,
@@ -31,8 +32,8 @@ use git::{
},
stash::{GitStash, StashEntry},
status::{
- DiffTreeType, FileStatus, GitSummary, StageStatus, StatusCode, TrackedStatus, TreeDiff,
- TreeDiffStatus, UnmergedStatus, UnmergedStatusCode,
+ DiffTreeType, FileStatus, GitSummary, StatusCode, TrackedStatus, TreeDiff, TreeDiffStatus,
+ UnmergedStatus, UnmergedStatusCode,
},
};
use gpui::{
@@ -44,6 +45,7 @@ use language::{
proto::{deserialize_version, serialize_version},
};
use parking_lot::Mutex;
+use pending_op::{PendingOp, PendingOps, Status as PendingOpStatus};
use postage::stream::Stream as _;
use rpc::{
AnyProtoClient, TypedEnvelope,
@@ -244,90 +246,11 @@ pub struct MergeDetails {
pub heads: Vec<Option<SharedString>>,
}
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum PendingOperationStatus {
- Staged,
- Unstaged,
- Reverted,
- Unchanged,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct PendingOperations {
- repo_path: RepoPath,
- // TODO: move this into StatusEntry
- staging: StageStatus,
- ops: Vec<PendingOperation>,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct PendingOperation {
- id: usize,
- finished: bool,
- status: PendingOperationStatus,
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub struct PendingOperationsSummary {
- finished: bool,
- status: PendingOperationStatus,
- count: usize,
-}
-
-impl Default for PendingOperationsSummary {
- fn default() -> Self {
- Self {
- finished: false,
- status: PendingOperationStatus::Unstaged,
- count: 0,
- }
- }
-}
-
-impl sum_tree::ContextLessSummary for PendingOperationsSummary {
- fn zero() -> Self {
- Default::default()
- }
-
- fn add_summary(&mut self, rhs: &Self) {
- self.finished = self.finished || rhs.finished;
- self.count += rhs.count;
- self.status = rhs.status;
- }
-}
-
-impl sum_tree::Item for PendingOperations {
- type Summary = PathSummary<PendingOperationsSummary>;
-
- fn summary(&self, _: <Self::Summary as sum_tree::Summary>::Context<'_>) -> Self::Summary {
- let mut item_summary = PendingOperationsSummary {
- count: self.ops.len(),
- ..Default::default()
- };
- if let Some(op) = self.ops.last() {
- item_summary.finished = op.finished;
- item_summary.status = op.status;
- }
- PathSummary {
- max_path: self.repo_path.0.clone(),
- item_summary,
- }
- }
-}
-
-impl sum_tree::KeyedItem for PendingOperations {
- type Key = PathKey;
-
- fn key(&self) -> Self::Key {
- PathKey(self.repo_path.0.clone())
- }
-}
-
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RepositorySnapshot {
pub id: RepositoryId,
pub statuses_by_path: SumTree<StatusEntry>,
- pub pending_ops_by_path: SumTree<PendingOperations>,
+ pub pending_ops_by_path: SumTree<PendingOps>,
pub work_directory_abs_path: Arc<Path>,
pub path_style: PathStyle,
pub branch: Option<Branch>,
@@ -3111,21 +3034,6 @@ impl RepositorySnapshot {
.cloned()
}
- pub fn pending_ops(&self) -> impl Iterator<Item = PendingOperations> + '_ {
- self.pending_ops_by_path.iter().cloned()
- }
-
- pub fn pending_ops_summary(&self) -> PendingOperationsSummary {
- self.pending_ops_by_path.summary().item_summary
- }
-
- pub fn pending_ops_for_path(&self, path: &RepoPath) -> Vec<PendingOperation> {
- self.pending_ops_by_path
- .get(&PathKey(path.0.clone()), ())
- .map(|ops| ops.ops.clone())
- .unwrap_or(Vec::new())
- }
-
pub fn abs_path_to_repo_path(&self, abs_path: &Path) -> Option<RepoPath> {
Self::abs_path_to_repo_path_inner(&self.work_directory_abs_path, abs_path, self.path_style)
}
@@ -3841,7 +3749,7 @@ impl Repository {
}
pub fn stage_entries(
- &self,
+ &mut self,
entries: Vec<RepoPath>,
cx: &mut Context<Self>,
) -> Task<anyhow::Result<()>> {
@@ -3861,6 +3769,32 @@ impl Repository {
_ => None,
};
+ let entries_cloned = entries.clone();
+
+ for entry in &entries_cloned {
+ let mut ops = Vec::new();
+ let mut id: u16 = 1;
+ if let Some(inner) = self
+ .snapshot
+ .pending_ops_by_path
+ .get(&PathKey(entry.0.clone()), ())
+ .map(|ops| &ops.ops)
+ {
+ ops.append(&mut inner.items(()));
+ id += inner.summary().max_id;
+ }
+ ops.push(PendingOp {
+ id,
+ status: PendingOpStatus::Staged,
+ finished: false,
+ });
+ let edit = sum_tree::Edit::Insert(PendingOps {
+ repo_path: entry.clone(),
+ ops: SumTree::from_iter(ops, ()),
+ });
+ self.snapshot.pending_ops_by_path.edit(vec![edit], ());
+ }
+
cx.spawn(async move |this, cx| {
for save_task in save_tasks {
save_task.await?;
@@ -3898,12 +3832,32 @@ impl Repository {
})?
.await??;
+ // this.update(cx, |this, _| {
+ // for entry in &entries_cloned {
+ // let key = PathKey(entry.0.clone());
+ // let Some(pending) = this.snapshot.pending_ops_by_path.get(&key) else { continue; };
+ // let Some(mut pending) = this.snapshot.pending_ops_by_path.remove(&key, ())
+ // else {
+ // continue;
+ // };
+ // for p in &mut pending.ops {
+ // if p.id == *op_id {
+ // p.finished = true;
+ // break;
+ // }
+ // }
+ // this.snapshot
+ // .pending_ops_by_path
+ // .insert_or_replace(pending, ());
+ // }
+ // })?;
+
Ok(())
})
}
pub fn unstage_entries(
- &self,
+ &mut self,
entries: Vec<RepoPath>,
cx: &mut Context<Self>,
) -> Task<anyhow::Result<()>> {
@@ -3964,7 +3918,7 @@ impl Repository {
})
}
- pub fn stage_all(&self, cx: &mut Context<Self>) -> Task<anyhow::Result<()>> {
+ pub fn stage_all(&mut self, cx: &mut Context<Self>) -> Task<anyhow::Result<()>> {
let to_stage = self
.cached_status()
.filter(|entry| !entry.status.staging().is_fully_staged())
@@ -3973,7 +3927,7 @@ impl Repository {
self.stage_entries(to_stage, cx)
}
- pub fn unstage_all(&self, cx: &mut Context<Self>) -> Task<anyhow::Result<()>> {
+ pub fn unstage_all(&mut self, cx: &mut Context<Self>) -> Task<anyhow::Result<()>> {
let to_unstage = self
.cached_status()
.filter(|entry| entry.status.staging().has_staged())
@@ -0,0 +1,99 @@
+use git::repository::RepoPath;
+use sum_tree::{ContextLessSummary, Dimension, Item, KeyedItem, NoSummary, SumTree};
+use worktree::{PathKey, PathSummary};
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum Status {
+ Staged,
+ Unstaged,
+ Reverted,
+ Unchanged,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct PendingOp {
+ pub id: u16,
+ pub status: Status,
+ pub finished: bool,
+}
+
+#[derive(Clone, Debug)]
+pub struct PendingOpSummary {
+ pub max_id: u16,
+ pub staged_count: u32,
+ pub unstaged_count: u32,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct PendingOps {
+ pub repo_path: RepoPath,
+ pub ops: SumTree<PendingOp>,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub struct PendingOpId(u16);
+
+impl Item for PendingOps {
+ type Summary = PathSummary<NoSummary>;
+
+ fn summary(&self, _cx: ()) -> Self::Summary {
+ PathSummary {
+ max_path: self.repo_path.0.clone(),
+ item_summary: NoSummary,
+ }
+ }
+}
+
+impl KeyedItem for PendingOps {
+ type Key = PathKey;
+
+ fn key(&self) -> Self::Key {
+ PathKey(self.repo_path.0.clone())
+ }
+}
+
+impl Item for PendingOp {
+ type Summary = PendingOpSummary;
+
+ fn summary(&self, _cx: ()) -> Self::Summary {
+ PendingOpSummary {
+ max_id: self.id,
+ staged_count: (self.status == Status::Staged) as u32,
+ unstaged_count: (self.status == Status::Unstaged) as u32,
+ }
+ }
+}
+
+impl ContextLessSummary for PendingOpSummary {
+ fn zero() -> Self {
+ Self {
+ max_id: 0,
+ staged_count: 0,
+ unstaged_count: 0,
+ }
+ }
+
+ fn add_summary(&mut self, summary: &Self) {
+ self.max_id = summary.max_id;
+ self.staged_count += summary.staged_count;
+ self.unstaged_count += summary.unstaged_count;
+ }
+}
+
+impl KeyedItem for PendingOp {
+ type Key = PendingOpId;
+
+ fn key(&self) -> Self::Key {
+ PendingOpId(self.id)
+ }
+}
+
+impl Dimension<'_, PendingOpSummary> for PendingOpId {
+ fn zero(_cx: ()) -> Self {
+ Self(0)
+ }
+
+ fn add_summary(&mut self, summary: &PendingOpSummary, _cx: ()) {
+ self.0 = summary.max_id;
+ }
+}