Add a prototype with a multi buffer having all project git changes (#21543)
Part of https://github.com/zed-industries/zed/issues/20925 This prototype is behind a feature flag and being merged to avoid conflicts with further git-related resturctures. To be a proper, public feature, this needs at least: * showing deleted files * better performance * randomized tests * `TODO`s in the `project_diff.rs` file fixed The good thing is, >90% of the changes are in the `project_diff.rs` file only, have a basic test and already work on simple cases. Release Notes: - N/A --------- Co-authored-by: Thorsten Ball <thorsten@zed.dev> Co-authored-by: Cole Miller <cole@zed.dev>
This commit is contained in:
parent
f0fac41ca4
commit
8d18dfa4c1
13 changed files with 1269 additions and 27 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -3790,6 +3790,7 @@ dependencies = [
|
||||||
"db",
|
"db",
|
||||||
"emojis",
|
"emojis",
|
||||||
"env_logger 0.11.5",
|
"env_logger 0.11.5",
|
||||||
|
"feature_flags",
|
||||||
"file_icons",
|
"file_icons",
|
||||||
"fs",
|
"fs",
|
||||||
"futures 0.3.31",
|
"futures 0.3.31",
|
||||||
|
@ -3823,6 +3824,7 @@ dependencies = [
|
||||||
"snippet",
|
"snippet",
|
||||||
"sum_tree",
|
"sum_tree",
|
||||||
"task",
|
"task",
|
||||||
|
"tempfile",
|
||||||
"text",
|
"text",
|
||||||
"theme",
|
"theme",
|
||||||
"time",
|
"time",
|
||||||
|
|
|
@ -39,6 +39,7 @@ collections.workspace = true
|
||||||
convert_case.workspace = true
|
convert_case.workspace = true
|
||||||
db.workspace = true
|
db.workspace = true
|
||||||
emojis.workspace = true
|
emojis.workspace = true
|
||||||
|
feature_flags.workspace = true
|
||||||
file_icons.workspace = true
|
file_icons.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
fuzzy.workspace = true
|
fuzzy.workspace = true
|
||||||
|
@ -97,6 +98,7 @@ project = { workspace = true, features = ["test-support"] }
|
||||||
release_channel.workspace = true
|
release_channel.workspace = true
|
||||||
rand.workspace = true
|
rand.workspace = true
|
||||||
settings = { workspace = true, features = ["test-support"] }
|
settings = { workspace = true, features = ["test-support"] }
|
||||||
|
tempfile.workspace = true
|
||||||
text = { workspace = true, features = ["test-support"] }
|
text = { workspace = true, features = ["test-support"] }
|
||||||
theme = { workspace = true, features = ["test-support"] }
|
theme = { workspace = true, features = ["test-support"] }
|
||||||
tree-sitter-html.workspace = true
|
tree-sitter-html.workspace = true
|
||||||
|
|
|
@ -327,6 +327,7 @@ pub fn init(cx: &mut AppContext) {
|
||||||
.detach();
|
.detach();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
git::project_diff::init(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SearchWithinRange;
|
pub struct SearchWithinRange;
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
pub mod blame;
|
pub mod blame;
|
||||||
|
pub mod project_diff;
|
||||||
|
|
|
@ -154,7 +154,7 @@ impl GitBlame {
|
||||||
this.generate(cx);
|
this.generate(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
project::Event::WorktreeUpdatedGitRepositories => {
|
project::Event::WorktreeUpdatedGitRepositories(_) => {
|
||||||
log::debug!("Status of git repositories updated. Regenerating blame data...",);
|
log::debug!("Status of git repositories updated. Regenerating blame data...",);
|
||||||
this.generate(cx);
|
this.generate(cx);
|
||||||
}
|
}
|
||||||
|
|
1235
crates/editor/src/git/project_diff.rs
Normal file
1235
crates/editor/src/git/project_diff.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -648,7 +648,7 @@ impl FileFinderDelegate {
|
||||||
cx.subscribe(project, |file_finder, _, event, cx| {
|
cx.subscribe(project, |file_finder, _, event, cx| {
|
||||||
match event {
|
match event {
|
||||||
project::Event::WorktreeUpdatedEntries(_, _)
|
project::Event::WorktreeUpdatedEntries(_, _)
|
||||||
| project::Event::WorktreeAdded
|
| project::Event::WorktreeAdded(_)
|
||||||
| project::Event::WorktreeRemoved(_) => file_finder
|
| project::Event::WorktreeRemoved(_) => file_finder
|
||||||
.picker
|
.picker
|
||||||
.update(cx, |picker, cx| picker.refresh(cx)),
|
.update(cx, |picker, cx| picker.refresh(cx)),
|
||||||
|
|
|
@ -80,7 +80,6 @@ impl BufferDiff {
|
||||||
self.tree.is_empty()
|
self.tree.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
|
||||||
pub fn hunks_in_row_range<'a>(
|
pub fn hunks_in_row_range<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
range: Range<u32>,
|
range: Range<u32>,
|
||||||
|
|
|
@ -3998,7 +3998,6 @@ impl BufferSnapshot {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all the Git diff hunks intersecting the given row range.
|
/// Returns all the Git diff hunks intersecting the given row range.
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
|
||||||
pub fn git_diff_hunks_in_row_range(
|
pub fn git_diff_hunks_in_row_range(
|
||||||
&self,
|
&self,
|
||||||
range: Range<BufferRow>,
|
range: Range<BufferRow>,
|
||||||
|
|
|
@ -240,11 +240,11 @@ pub enum Event {
|
||||||
LanguageNotFound(Model<Buffer>),
|
LanguageNotFound(Model<Buffer>),
|
||||||
ActiveEntryChanged(Option<ProjectEntryId>),
|
ActiveEntryChanged(Option<ProjectEntryId>),
|
||||||
ActivateProjectPanel,
|
ActivateProjectPanel,
|
||||||
WorktreeAdded,
|
WorktreeAdded(WorktreeId),
|
||||||
WorktreeOrderChanged,
|
WorktreeOrderChanged,
|
||||||
WorktreeRemoved(WorktreeId),
|
WorktreeRemoved(WorktreeId),
|
||||||
WorktreeUpdatedEntries(WorktreeId, UpdatedEntriesSet),
|
WorktreeUpdatedEntries(WorktreeId, UpdatedEntriesSet),
|
||||||
WorktreeUpdatedGitRepositories,
|
WorktreeUpdatedGitRepositories(WorktreeId),
|
||||||
DiskBasedDiagnosticsStarted {
|
DiskBasedDiagnosticsStarted {
|
||||||
language_server_id: LanguageServerId,
|
language_server_id: LanguageServerId,
|
||||||
},
|
},
|
||||||
|
@ -259,7 +259,7 @@ pub enum Event {
|
||||||
DisconnectedFromHost,
|
DisconnectedFromHost,
|
||||||
DisconnectedFromSshRemote,
|
DisconnectedFromSshRemote,
|
||||||
Closed,
|
Closed,
|
||||||
DeletedEntry(ProjectEntryId),
|
DeletedEntry(WorktreeId, ProjectEntryId),
|
||||||
CollaboratorUpdated {
|
CollaboratorUpdated {
|
||||||
old_peer_id: proto::PeerId,
|
old_peer_id: proto::PeerId,
|
||||||
new_peer_id: proto::PeerId,
|
new_peer_id: proto::PeerId,
|
||||||
|
@ -1504,6 +1504,7 @@ impl Project {
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Option<Task<Result<()>>> {
|
) -> Option<Task<Result<()>>> {
|
||||||
let worktree = self.worktree_for_entry(entry_id, cx)?;
|
let worktree = self.worktree_for_entry(entry_id, cx)?;
|
||||||
|
cx.emit(Event::DeletedEntry(worktree.read(cx).id(), entry_id));
|
||||||
worktree.update(cx, |worktree, cx| {
|
worktree.update(cx, |worktree, cx| {
|
||||||
worktree.delete_entry(entry_id, trash, cx)
|
worktree.delete_entry(entry_id, trash, cx)
|
||||||
})
|
})
|
||||||
|
@ -2204,7 +2205,7 @@ impl Project {
|
||||||
match event {
|
match event {
|
||||||
WorktreeStoreEvent::WorktreeAdded(worktree) => {
|
WorktreeStoreEvent::WorktreeAdded(worktree) => {
|
||||||
self.on_worktree_added(worktree, cx);
|
self.on_worktree_added(worktree, cx);
|
||||||
cx.emit(Event::WorktreeAdded);
|
cx.emit(Event::WorktreeAdded(worktree.read(cx).id()));
|
||||||
}
|
}
|
||||||
WorktreeStoreEvent::WorktreeRemoved(_, id) => {
|
WorktreeStoreEvent::WorktreeRemoved(_, id) => {
|
||||||
cx.emit(Event::WorktreeRemoved(*id));
|
cx.emit(Event::WorktreeRemoved(*id));
|
||||||
|
@ -2225,23 +2226,25 @@ impl Project {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cx.observe(worktree, |_, _, cx| cx.notify()).detach();
|
cx.observe(worktree, |_, _, cx| cx.notify()).detach();
|
||||||
cx.subscribe(worktree, |project, worktree, event, cx| match event {
|
cx.subscribe(worktree, |project, worktree, event, cx| {
|
||||||
|
let worktree_id = worktree.update(cx, |worktree, _| worktree.id());
|
||||||
|
match event {
|
||||||
worktree::Event::UpdatedEntries(changes) => {
|
worktree::Event::UpdatedEntries(changes) => {
|
||||||
cx.emit(Event::WorktreeUpdatedEntries(
|
cx.emit(Event::WorktreeUpdatedEntries(
|
||||||
worktree.read(cx).id(),
|
worktree.read(cx).id(),
|
||||||
changes.clone(),
|
changes.clone(),
|
||||||
));
|
));
|
||||||
|
|
||||||
let worktree_id = worktree.update(cx, |worktree, _| worktree.id());
|
|
||||||
project
|
project
|
||||||
.client()
|
.client()
|
||||||
.telemetry()
|
.telemetry()
|
||||||
.report_discovered_project_events(worktree_id, changes);
|
.report_discovered_project_events(worktree_id, changes);
|
||||||
}
|
}
|
||||||
worktree::Event::UpdatedGitRepositories(_) => {
|
worktree::Event::UpdatedGitRepositories(_) => {
|
||||||
cx.emit(Event::WorktreeUpdatedGitRepositories);
|
cx.emit(Event::WorktreeUpdatedGitRepositories(worktree_id));
|
||||||
|
}
|
||||||
|
worktree::Event::DeletedEntry(id) => cx.emit(Event::DeletedEntry(worktree_id, *id)),
|
||||||
}
|
}
|
||||||
worktree::Event::DeletedEntry(id) => cx.emit(Event::DeletedEntry(*id)),
|
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
|
|
@ -304,7 +304,7 @@ impl ProjectPanel {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
project::Event::WorktreeUpdatedEntries(_, _)
|
project::Event::WorktreeUpdatedEntries(_, _)
|
||||||
| project::Event::WorktreeAdded
|
| project::Event::WorktreeAdded(_)
|
||||||
| project::Event::WorktreeOrderChanged => {
|
| project::Event::WorktreeOrderChanged => {
|
||||||
this.update_visible_entries(None, cx);
|
this.update_visible_entries(None, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
|
|
@ -125,7 +125,7 @@ impl ProjectIndex {
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
match event {
|
match event {
|
||||||
project::Event::WorktreeAdded | project::Event::WorktreeRemoved(_) => {
|
project::Event::WorktreeAdded(_) | project::Event::WorktreeRemoved(_) => {
|
||||||
self.update_worktree_indices(cx);
|
self.update_worktree_indices(cx);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -810,7 +810,7 @@ impl Workspace {
|
||||||
this.collaborator_left(*peer_id, cx);
|
this.collaborator_left(*peer_id, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
project::Event::WorktreeRemoved(_) | project::Event::WorktreeAdded => {
|
project::Event::WorktreeRemoved(_) | project::Event::WorktreeAdded(_) => {
|
||||||
this.update_window_title(cx);
|
this.update_window_title(cx);
|
||||||
this.serialize_workspace(cx);
|
this.serialize_workspace(cx);
|
||||||
}
|
}
|
||||||
|
@ -832,7 +832,7 @@ impl Workspace {
|
||||||
cx.remove_window();
|
cx.remove_window();
|
||||||
}
|
}
|
||||||
|
|
||||||
project::Event::DeletedEntry(entry_id) => {
|
project::Event::DeletedEntry(_, entry_id) => {
|
||||||
for pane in this.panes.iter() {
|
for pane in this.panes.iter() {
|
||||||
pane.update(cx, |pane, cx| {
|
pane.update(cx, |pane, cx| {
|
||||||
pane.handle_deleted_project_item(*entry_id, cx)
|
pane.handle_deleted_project_item(*entry_id, cx)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue