Add file history view (#42441)
Closes #16827 Release Notes: - Added: File history view accessible via right-click context menu on files in the editor or project panel. Shows commit history for the selected file with author, timestamp, and commit message. Clicking a commit opens a diff view filtered to show only changes for that specific file. <img width="1293" height="834" alt="Screenshot 2025-11-11 at 16 31 32" src="https://github.com/user-attachments/assets/3780d21b-a719-40b3-955c-d928c45a47cc" /> <img width="1283" height="836" alt="Screenshot 2025-11-11 at 16 31 24" src="https://github.com/user-attachments/assets/1dc4e56b-b225-4ffa-a2af-c5dcfb2efaa0" /> --------- Co-authored-by: cameron <cameron.studdstreet@gmail.com>
This commit is contained in:
@@ -14,7 +14,9 @@ use editor::{
|
||||
},
|
||||
};
|
||||
use file_icons::FileIcons;
|
||||
use git;
|
||||
use git::status::GitSummary;
|
||||
use git_ui;
|
||||
use git_ui::file_diff_view::FileDiffView;
|
||||
use gpui::{
|
||||
Action, AnyElement, App, AsyncWindowContext, Bounds, ClipboardItem, Context, CursorStyle,
|
||||
@@ -442,6 +444,72 @@ pub fn init(cx: &mut App) {
|
||||
panel.update(cx, |panel, cx| panel.delete(action, window, cx));
|
||||
}
|
||||
});
|
||||
|
||||
workspace.register_action(|workspace, _: &git::FileHistory, window, cx| {
|
||||
// First try to get from project panel if it's focused
|
||||
if let Some(panel) = workspace.panel::<ProjectPanel>(cx) {
|
||||
let maybe_project_path = panel.read(cx).state.selection.and_then(|selection| {
|
||||
let project = workspace.project().read(cx);
|
||||
let worktree = project.worktree_for_id(selection.worktree_id, cx)?;
|
||||
let entry = worktree.read(cx).entry_for_id(selection.entry_id)?;
|
||||
if entry.is_file() {
|
||||
Some(ProjectPath {
|
||||
worktree_id: selection.worktree_id,
|
||||
path: entry.path.clone(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(project_path) = maybe_project_path {
|
||||
let project = workspace.project();
|
||||
let git_store = project.read(cx).git_store();
|
||||
if let Some((repo, repo_path)) = git_store
|
||||
.read(cx)
|
||||
.repository_and_path_for_project_path(&project_path, cx)
|
||||
{
|
||||
git_ui::file_history_view::FileHistoryView::open(
|
||||
repo_path,
|
||||
git_store.downgrade(),
|
||||
repo.downgrade(),
|
||||
workspace.weak_handle(),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: try to get from active editor
|
||||
if let Some(active_item) = workspace.active_item(cx)
|
||||
&& let Some(editor) = active_item.downcast::<Editor>()
|
||||
&& let Some(buffer) = editor.read(cx).buffer().read(cx).as_singleton()
|
||||
&& let Some(file) = buffer.read(cx).file()
|
||||
{
|
||||
let worktree_id = file.worktree_id(cx);
|
||||
let project_path = ProjectPath {
|
||||
worktree_id,
|
||||
path: file.path().clone(),
|
||||
};
|
||||
let project = workspace.project();
|
||||
let git_store = project.read(cx).git_store();
|
||||
if let Some((repo, repo_path)) = git_store
|
||||
.read(cx)
|
||||
.repository_and_path_for_project_path(&project_path, cx)
|
||||
{
|
||||
git_ui::file_history_view::FileHistoryView::open(
|
||||
repo_path,
|
||||
git_store.downgrade(),
|
||||
repo.downgrade(),
|
||||
workspace.weak_handle(),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
@@ -1010,6 +1078,18 @@ impl ProjectPanel {
|
||||
|| (settings.hide_root && visible_worktrees_count == 1));
|
||||
let should_show_compare = !is_dir && self.file_abs_paths_to_diff(cx).is_some();
|
||||
|
||||
let has_git_repo = !is_dir && {
|
||||
let project_path = project::ProjectPath {
|
||||
worktree_id,
|
||||
path: entry.path.clone(),
|
||||
};
|
||||
project
|
||||
.git_store()
|
||||
.read(cx)
|
||||
.repository_and_path_for_project_path(&project_path, cx)
|
||||
.is_some()
|
||||
};
|
||||
|
||||
let context_menu = ContextMenu::build(window, cx, |menu, _, _| {
|
||||
menu.context(self.focus_handle.clone()).map(|menu| {
|
||||
if is_read_only {
|
||||
@@ -1060,6 +1140,10 @@ impl ProjectPanel {
|
||||
"Copy Relative Path",
|
||||
Box::new(zed_actions::workspace::CopyRelativePath),
|
||||
)
|
||||
.when(has_git_repo, |menu| {
|
||||
menu.separator()
|
||||
.action("File History", Box::new(git::FileHistory))
|
||||
})
|
||||
.when(!should_hide_rename, |menu| {
|
||||
menu.separator().action("Rename", Box::new(Rename))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user