@@ -45,7 +45,7 @@ use language::{
proto::{deserialize_version, serialize_version},
};
use parking_lot::Mutex;
-use pending_op::{PendingOp, PendingOps, Status as PendingOpStatus};
+use pending_op::{PendingOp, PendingOpId, PendingOpStatus};
use postage::stream::Stream as _;
use rpc::{
AnyProtoClient, TypedEnvelope,
@@ -250,7 +250,7 @@ pub struct MergeDetails {
pub struct RepositorySnapshot {
pub id: RepositoryId,
pub statuses_by_path: SumTree<StatusEntry>,
- pub pending_ops_by_path: SumTree<PendingOps>,
+ pub pending_ops: SumTree<PendingOp>,
pub work_directory_abs_path: Arc<Path>,
pub path_style: PathStyle,
pub branch: Option<Branch>,
@@ -2906,7 +2906,7 @@ impl RepositorySnapshot {
Self {
id,
statuses_by_path: Default::default(),
- pending_ops_by_path: Default::default(),
+ pending_ops: Default::default(),
work_directory_abs_path,
branch: None,
head_commit: None,
@@ -3034,11 +3034,16 @@ impl RepositorySnapshot {
.cloned()
}
- pub fn pending_ops_for_path(&self, path: &RepoPath) -> Option<SumTree<PendingOp>> {
- self.pending_ops_by_path
- .get(&PathKey(path.0.clone()), ())
- .map(|ops| &ops.ops)
- .cloned()
+ pub fn pending_op_by_id(&self, id: PendingOpId) -> Option<PendingOp> {
+ self.pending_ops.get(&id, ()).cloned()
+ }
+
+ pub fn pending_ops_for_path(&self, path: &RepoPath) -> Vec<PendingOp> {
+ self.pending_ops
+ .filter::<_, PathKey>((), |sum| sum.max_path == path.0)
+ .into_iter()
+ .map(Clone::clone)
+ .collect()
}
pub fn abs_path_to_repo_path(&self, abs_path: &Path) -> Option<RepoPath> {
@@ -3776,10 +3781,20 @@ impl Repository {
_ => None,
};
- let entries_cloned = entries.clone();
+ let mut ids = Vec::with_capacity(entries.len());
- for entry in &entries_cloned {
- self.push_pending_op_for_path(entry, PendingOpStatus::Staged);
+ for entry in &entries {
+ let id = self.snapshot.pending_ops.summary().item_summary.max_id + 1;
+ self.snapshot.pending_ops.push(
+ PendingOp {
+ repo_path: entry.clone(),
+ id,
+ status: PendingOpStatus::Staged,
+ finished: false,
+ },
+ (),
+ );
+ ids.push(id);
}
cx.spawn(async move |this, cx| {
@@ -3819,25 +3834,16 @@ 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, ());
- // }
- // })?;
+ this.update(cx, |this, _| {
+ for id in ids {
+ if let Some(mut op) = this.snapshot.pending_op_by_id(id) {
+ op.finished = true;
+ this.snapshot
+ .pending_ops
+ .edit(vec![sum_tree::Edit::Insert(op)], ());
+ }
+ }
+ })?;
Ok(())
})
@@ -3864,8 +3870,20 @@ impl Repository {
_ => None,
};
+ let mut ids = Vec::with_capacity(entries.len());
+
for entry in &entries {
- self.push_pending_op_for_path(entry, PendingOpStatus::Unstaged);
+ let id = self.snapshot.pending_ops.summary().item_summary.max_id + 1;
+ self.snapshot.pending_ops.push(
+ PendingOp {
+ repo_path: entry.clone(),
+ id,
+ status: PendingOpStatus::Unstaged,
+ finished: false,
+ },
+ (),
+ );
+ ids.push(id);
}
cx.spawn(async move |this, cx| {
@@ -3905,6 +3923,17 @@ impl Repository {
})?
.await??;
+ this.update(cx, |this, _| {
+ for id in ids {
+ if let Some(mut op) = this.snapshot.pending_op_by_id(id) {
+ op.finished = true;
+ this.snapshot
+ .pending_ops
+ .edit(vec![sum_tree::Edit::Insert(op)], ());
+ }
+ }
+ })?;
+
Ok(())
})
}
@@ -5123,29 +5152,6 @@ impl Repository {
pub fn barrier(&mut self) -> oneshot::Receiver<()> {
self.send_job(None, |_, _| async {})
}
-
- fn push_pending_op_for_path(&mut self, path: &RepoPath, status: PendingOpStatus) {
- let mut ops = Vec::new();
- let existing_ops = self.snapshot.pending_ops_for_path(path);
- let id = existing_ops
- .as_ref()
- .map(|ops| ops.summary().max_id)
- .unwrap_or(0)
- + 1;
- if let Some(existing_ops) = existing_ops {
- ops.append(&mut existing_ops.items(()));
- }
- ops.push(PendingOp {
- id,
- status,
- finished: false,
- });
- let edit = sum_tree::Edit::Insert(PendingOps {
- repo_path: path.clone(),
- ops: SumTree::from_iter(ops, ()),
- });
- self.snapshot.pending_ops_by_path.edit(vec![edit], ());
- }
}
fn get_permalink_in_rust_registry_src(
@@ -5395,7 +5401,7 @@ async fn compute_snapshot(
MergeDetails::load(&backend, &statuses_by_path, &prev_snapshot).await?;
log::debug!("new merge details (changed={merge_heads_changed:?}): {merge_details:?}");
- let pending_ops_by_path = prev_snapshot.pending_ops_by_path.clone();
+ let pending_ops = prev_snapshot.pending_ops.clone();
if merge_heads_changed {
events.push(RepositoryEvent::MergeHeadsChanged);
@@ -5422,7 +5428,7 @@ async fn compute_snapshot(
let snapshot = RepositorySnapshot {
id,
statuses_by_path,
- pending_ops_by_path,
+ pending_ops,
work_directory_abs_path,
path_style: prev_snapshot.path_style,
scan_id: prev_snapshot.scan_id + 1,
@@ -1,9 +1,10 @@
use git::repository::RepoPath;
-use sum_tree::{ContextLessSummary, Dimension, Item, KeyedItem, NoSummary, SumTree};
-use worktree::{PathKey, PathSummary};
+use std::ops::Add;
+use sum_tree::{ContextLessSummary, Dimension, Item, KeyedItem};
+use worktree::PathSummary;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
-pub enum Status {
+pub enum PendingOpStatus {
Staged,
Unstaged,
Reverted,
@@ -12,54 +13,33 @@ pub enum Status {
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PendingOp {
- pub id: u16,
- pub status: Status,
+ pub repo_path: RepoPath,
+ pub id: PendingOpId,
+ pub status: PendingOpStatus,
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>,
+ pub max_id: PendingOpId,
+ pub staged_count: usize,
+ pub unstaged_count: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct PendingOpId(u16);
+pub struct PendingOpId(pub usize);
-impl Item for PendingOps {
- type Summary = PathSummary<NoSummary>;
+impl Item for PendingOp {
+ type Summary = PathSummary<PendingOpSummary>;
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,
+ item_summary: PendingOpSummary {
+ max_id: self.id,
+ staged_count: (self.status == PendingOpStatus::Staged) as usize,
+ unstaged_count: (self.status == PendingOpStatus::Unstaged) as usize,
+ },
}
}
}
@@ -67,7 +47,7 @@ impl Item for PendingOp {
impl ContextLessSummary for PendingOpSummary {
fn zero() -> Self {
Self {
- max_id: 0,
+ max_id: PendingOpId(0),
staged_count: 0,
unstaged_count: 0,
}
@@ -84,16 +64,24 @@ impl KeyedItem for PendingOp {
type Key = PendingOpId;
fn key(&self) -> Self::Key {
- PendingOpId(self.id)
+ self.id
}
}
-impl Dimension<'_, PendingOpSummary> for PendingOpId {
+impl Dimension<'_, PathSummary<PendingOpSummary>> for PendingOpId {
fn zero(_cx: ()) -> Self {
Self(0)
}
- fn add_summary(&mut self, summary: &PendingOpSummary, _cx: ()) {
- self.0 = summary.max_id;
+ fn add_summary(&mut self, summary: &PathSummary<PendingOpSummary>, _cx: ()) {
+ *self = summary.item_summary.max_id;
+ }
+}
+
+impl Add<usize> for PendingOpId {
+ type Output = PendingOpId;
+
+ fn add(self, rhs: usize) -> Self::Output {
+ Self(self.0 + rhs)
}
}