Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 112 additions & 88 deletions crates/git_ui/src/commit_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use git::{
use gpui::{
AnyElement, App, AppContext as _, AsyncWindowContext, ClipboardItem, Context, Entity,
EventEmitter, FocusHandle, Focusable, InteractiveElement, IntoElement, ParentElement,
PromptLevel, Render, ScrollHandle, StatefulInteractiveElement as _, Styled, Task, WeakEntity,
Window, actions,
PromptLevel, Render, ScrollHandle, StatefulInteractiveElement as _, Styled, Subscription,
Task, WeakEntity, Window, actions,
};
use language::{
Buffer, Capability, DiskState, File, LanguageRegistry, LineEnding, OffsetRangeExt as _,
Expand Down Expand Up @@ -47,6 +47,7 @@ use workspace::{

use crate::commit_tooltip::CommitAvatar;
use crate::git_panel::GitPanel;
use crate::solo_diff_view::SoloDiffView;

actions!(
git,
Expand Down Expand Up @@ -85,6 +86,7 @@ pub struct CommitView {
project: Entity<Project>,
workspace: WeakEntity<Workspace>,
remote: Option<GitRemote>,
_subscriptions: Vec<Subscription>,
_load_diff_task: Task<Result<()>>,
}

Expand Down Expand Up @@ -142,36 +144,35 @@ impl Addon for CommitDiffAddon {
_window: &mut Window,
cx: &mut App,
) -> ContextMenu {
let file_to_open = buffer.file().and_then(|file| {
let commit_view = self.commit_view.upgrade()?;
let commit_view = commit_view.read(cx);
let project_path = commit_view
.repository
.read(cx)
.repo_path_to_project_path(&RepoPath::from_rel_path(file.path()), cx)?;
let exists_at_head = commit_view
.workspace
.upgrade()?
.read(cx)
.project()
.read(cx)
.entry_for_path(&project_path, cx)
.is_some();
exists_at_head.then(|| file.clone())
});

menu.when_some(file_to_open, |menu, file| {
let commit_view = self.commit_view.clone();
menu.entry(
"Open File in Project",
Some(Box::new(OpenFileAtHead)),
move |window, cx| {
commit_view
.update(cx, |view, cx| view.open_file_at_head(&file, window, cx))
.log_err();
},
)
})
let Some(file) = buffer.file() else {
return menu;
};
if !file.can_open() {
return menu;
}
let Some(commit_view) = self.commit_view.upgrade() else {
return menu;
};
let repo_path = RepoPath::from_rel_path(file.path());
let sha = commit_view.read(cx).commit.sha.clone();
let repository = commit_view.read(cx).repository.clone();
let workspace = commit_view.read(cx).workspace.clone();

menu.entry(
"Open File Diff",
Some(Box::new(OpenFileAtHead)),
move |window, cx| {
SoloDiffView::open_or_focus_commit(
Arc::<str>::from(sha.as_ref()),
repo_path.clone(),
repository.clone(),
workspace.clone(),
window,
cx,
)
.detach_and_notify_err(workspace.clone(), window, cx);
},
)
}
}

Expand Down Expand Up @@ -261,6 +262,46 @@ impl CommitView {
.detach();
}

fn handle_editor_event(
&mut self,
_editor: &Entity<SplittableEditor>,
event: &EditorEvent,
window: &mut Window,
cx: &mut Context<Self>,
) {
if let EditorEvent::OpenExcerptsRequested {
selections_by_buffer,
..
} = event
{
for buffer_id in selections_by_buffer.keys() {
if let Some(buffer) = self.multibuffer.read(cx).buffer(*buffer_id)
&& let Some(file) = buffer.read(cx).file()
{
self.open_file_diff(RepoPath::from_rel_path(file.path()), window, cx);
}
}
}
}

fn open_file_diff(
&self,
repo_path: RepoPath,
window: &mut Window,
cx: &mut Context<Self>,
) {
let sha = Arc::<str>::from(self.commit.sha.as_ref());
SoloDiffView::open_or_focus_commit(
sha,
repo_path,
self.repository.clone(),
self.workspace.clone(),
window,
cx,
)
.detach_and_notify_err(self.workspace.clone(), window, cx);
}

fn new(
commit: CommitDetails,
commit_diff: CommitDiff,
Expand Down Expand Up @@ -303,10 +344,17 @@ impl CommitView {
editor.set_show_bookmarks(false, cx);
editor.set_show_breakpoints(false, cx);
editor.set_show_diff_review_button(true, cx);
editor.set_delegate_open_excerpts(true);
});

editor
});

let editor_subscription = cx.subscribe_in(
&editor,
window,
Self::handle_editor_event,
);
let commit_sha = Arc::<str>::from(commit.sha.as_ref());

let repository_clone = repository.clone();
Expand Down Expand Up @@ -501,6 +549,7 @@ impl CommitView {
project,
workspace,
remote,
_subscriptions: vec![editor_subscription],
_load_diff_task: load_diff_task,
}
}
Expand All @@ -525,33 +574,6 @@ impl CommitView {
self.multibuffer.read(cx).snapshot(cx).total_changed_lines()
}

fn open_file_at_head(
&mut self,
file: &Arc<dyn language::File>,
window: &mut Window,
cx: &mut Context<Self>,
) {
let rel_path = file.path().clone();
let worktree_id = file.worktree_id(cx);
let repo_path = RepoPath::from_rel_path(&rel_path);
let project_path = self
.repository
.read(cx)
.repo_path_to_project_path(&repo_path, cx)
.unwrap_or(project::ProjectPath {
worktree_id,
path: rel_path,
});

self.workspace
.update(cx, |workspace, cx| {
workspace
.open_path_preview(project_path, None, false, false, true, window, cx)
.detach_and_log_err(cx);
})
.log_err();
}

fn open_file_at_head_action(
&mut self,
_: &OpenFileAtHead,
Expand All @@ -568,7 +590,8 @@ impl CommitView {
else {
return;
};
self.open_file_at_head(&file, window, cx);
let repo_path = RepoPath::from_rel_path(file.path());
self.open_file_diff(repo_path, window, cx);
}

fn render_header(&self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
Expand Down Expand Up @@ -1010,7 +1033,7 @@ pub(crate) async fn build_buffer(
Ok(buffer)
}

async fn build_buffer_diff(
pub(crate) async fn build_buffer_diff(
mut old_text: Option<String>,
buffer: &Entity<Buffer>,
language_registry: &Arc<LanguageRegistry>,
Expand Down Expand Up @@ -1204,35 +1227,34 @@ impl Item for CommitView {
let project = self.project.clone();
let diff_view_style = self.editor.read(cx).diff_view_style();
let multibuffer = self.multibuffer.clone();
Task::ready(Some(cx.new(|cx| {
let view = cx.new(|cx| {
let commit_view = cx.weak_entity();
let editor = cx.new({
let file_statuses = file_statuses.clone();
let project = project.clone();
let workspace_entity = workspace_entity.clone();
let multibuffer = multibuffer.clone();
move |cx| {
let editor = SplittableEditor::new(
diff_view_style,
multibuffer.clone(),
project.clone(),
workspace_entity.clone(),
window,
cx,
);
editor.set_diff_hunk_delegate(Some(Arc::new(RestoreOnlyDiffHunkDelegate)), cx);
editor.rhs_editor().update(cx, |editor, cx| {
editor.set_show_bookmarks(false, cx);
editor.set_show_breakpoints(false, cx);
editor.set_show_diff_review_button(true, cx);
editor.register_addon(CommitDiffAddon {
file_statuses,
commit_view,
});
let editor = cx.new(|cx| {
let editor = SplittableEditor::new(
diff_view_style,
multibuffer.clone(),
project.clone(),
workspace_entity.clone(),
window,
cx,
);
editor.set_diff_hunk_delegate(Some(Arc::new(RestoreOnlyDiffHunkDelegate)), cx);
editor.rhs_editor().update(cx, |editor, cx| {
editor.set_show_bookmarks(false, cx);
editor.set_show_breakpoints(false, cx);
editor.set_show_diff_review_button(true, cx);
editor.set_delegate_open_excerpts(true);
editor.register_addon(CommitDiffAddon {
file_statuses: file_statuses.clone(),
commit_view,
});
editor
}
});
editor
});

let editor_subscription =
cx.subscribe_in(&editor, window, Self::handle_editor_event);

let language_registry = project.read(cx).languages().clone();
let message = cx.new(|cx| {
Markdown::new(
Expand All @@ -1254,9 +1276,11 @@ impl Item for CommitView {
project: self.project.clone(),
workspace: self.workspace.clone(),
remote: self.remote.clone(),
_subscriptions: vec![editor_subscription],
_load_diff_task: Task::ready(Ok(())),
}
})))
});
Task::ready(Some(view))
}
}

Expand Down
Loading