diff options
author | Kevin Sawicki | 2011-11-29 21:35:59 +0000 |
---|---|---|
committer | Stefan Lay | 2011-11-30 12:23:15 +0000 |
commit | 8a524f1f0802b045f8ad84b01df710002ed5fb76 (patch) | |
tree | 5d29c54f89f918c3d6ec771014d442d147e45a80 | |
parent | 75a1cf972c4a501ef0a991c1346ca95e66c9eb5a (diff) | |
download | egit-8a524f1f0802b045f8ad84b01df710002ed5fb76.tar.gz egit-8a524f1f0802b045f8ad84b01df710002ed5fb76.tar.xz egit-8a524f1f0802b045f8ad84b01df710002ed5fb76.zip |
Support 'Show Annotations' on history items
Blame can now be run from the file table in the history view
as well as the file section of the commit editor.
The blame operation will open the file in a read-only editor
and show annotations starting at the selected commit.
Bug: 362052
Change-Id: I8c88d704581f50e5c406724100d7e8ee31f72701
Signed-off-by: Kevin Sawicki <kevin@github.com>
7 files changed, 146 insertions, 22 deletions
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/commit/CommitEditorTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/commit/CommitEditorTest.java index b3d77446fe..7e0e25e149 100644 --- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/commit/CommitEditorTest.java +++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/commit/CommitEditorTest.java @@ -11,6 +11,7 @@ package org.eclipse.egit.ui.test.commit; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -18,14 +19,20 @@ import java.io.File; import java.util.concurrent.atomic.AtomicReference; import org.eclipse.egit.core.Activator; +import org.eclipse.egit.ui.JobFamilies; +import org.eclipse.egit.ui.UIText; import org.eclipse.egit.ui.common.LocalRepositoryTestCase; import org.eclipse.egit.ui.internal.commit.CommitEditor; import org.eclipse.egit.ui.internal.commit.RepositoryCommit; +import org.eclipse.egit.ui.test.ContextMenuHelper; +import org.eclipse.egit.ui.test.TestUtil; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEditor; import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotMultiPageEditor; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.PlatformUI; @@ -90,4 +97,32 @@ public class CommitEditorTest extends LocalRepositoryTestCase { botEditor.activatePage(name); botEditor.close(); } + + @Test + public void showAnnotations() throws Exception { + final AtomicReference<IEditorPart> editorRef = new AtomicReference<IEditorPart>(); + PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { + + public void run() { + RepositoryCommit repoCommit = new RepositoryCommit(repository, + commit); + editorRef.set(CommitEditor.openQuiet(repoCommit)); + } + }); + assertNotNull(editorRef.get()); + SWTBotEditor commitEditor = bot.activeEditor(); + SWTBotTable table = commitEditor.bot().table(0); + assertTrue(table.rowCount() > 0); + table.select(0); + ContextMenuHelper.clickContextMenu(table, + UIText.CommitFileDiffViewer_ShowAnnotationsMenuLabel); + TestUtil.joinJobs(JobFamilies.BLAME); + assertFalse(commitEditor.getReference().equals( + bot.activeEditor().getReference())); + + final String content = getTestFileContent(); + // Change working directory content to validate blame opens HEAD + setTestFileContent("updated content" + System.nanoTime()); + assertEquals(content, bot.activeEditor().toTextEditor().getText()); + } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/JobFamilies.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/JobFamilies.java index 2a0bd886dc..923dbfbbed 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/JobFamilies.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/JobFamilies.java @@ -117,10 +117,14 @@ public class JobFamilies { * Clone repository job */ public static final Object CLONE = new Object(); - + /** * Fetch data from git job */ public static final Object SYNCHRONIZE_READ_DATA = new Object(); + /** + * Show annotations git job + */ + public static final Object BLAME = new Object(); } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java index c90b426e5a..e5e221d14a 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java @@ -3347,6 +3347,9 @@ public class UIText extends NLS { public static String CommitFileDiffViewer_SelectOneCommitMessage; /** */ + public static String CommitFileDiffViewer_ShowAnnotationsMenuLabel; + + /** */ public static String CommitGraphTable_CommitId; /** */ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowBlameActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowBlameActionHandler.java index 1e0421f836..f72e96e93b 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowBlameActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowBlameActionHandler.java @@ -12,12 +12,16 @@ package org.eclipse.egit.ui.internal.actions; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; -import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IStorage; import org.eclipse.egit.core.internal.job.JobUtil; +import org.eclipse.egit.core.project.RepositoryMapping; +import org.eclipse.egit.ui.JobFamilies; import org.eclipse.egit.ui.UIText; import org.eclipse.egit.ui.internal.blame.BlameOperation; import org.eclipse.jgit.lib.Repository; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.handlers.HandlerUtil; /** @@ -28,13 +32,25 @@ public class ShowBlameActionHandler extends RepositoryActionHandler { /** @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent) */ public Object execute(final ExecutionEvent event) throws ExecutionException { IResource[] selected = getSelectedResources(); + if (selected.length != 1 || !(selected[0] instanceof IStorage)) + return null; + Repository repository = getRepository(); - if (repository != null && selected.length == 1 - && selected[0] instanceof IFile) - JobUtil.scheduleUserJob(new BlameOperation(repository, - (IFile) selected[0], HandlerUtil.getActiveShell(event), - HandlerUtil.getActiveSite(event).getPage()), - UIText.ShowBlameHandler_JobName, null); + if (repository == null) + return null; + + RepositoryMapping mapping = RepositoryMapping.getMapping(selected[0] + .getProject()); + if (mapping == null) + return null; + + String path = mapping.getRepoRelativePath(selected[0]); + IStorage storage = (IStorage) selected[0]; + Shell shell = HandlerUtil.getActiveShell(event); + IWorkbenchPage page = HandlerUtil.getActiveSite(event).getPage(); + JobUtil.scheduleUserJob(new BlameOperation(repository, storage, path, + null, shell, page), UIText.ShowBlameHandler_JobName, + JobFamilies.BLAME); return null; } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/blame/BlameOperation.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/blame/BlameOperation.java index 618e660b22..eae0fd5a6f 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/blame/BlameOperation.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/blame/BlameOperation.java @@ -14,17 +14,18 @@ import java.util.HashMap; import java.util.Map; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IStorage; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.egit.core.op.IEGitOperation; -import org.eclipse.egit.core.project.RepositoryMapping; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIPreferences; import org.eclipse.jface.text.revisions.RevisionInformation; import org.eclipse.jgit.api.BlameCommand; import org.eclipse.jgit.blame.BlameResult; import org.eclipse.jgit.diff.RawTextComparator; +import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.swt.widgets.Shell; @@ -40,7 +41,11 @@ public class BlameOperation implements IEGitOperation { private Repository repository; - private IFile file; + private IStorage storage; + + private String path; + + private AnyObjectId startCommit; private Shell shell; @@ -50,14 +55,18 @@ public class BlameOperation implements IEGitOperation { * Create annotate operation * * @param repository - * @param file + * @param storage + * @param path + * @param startCommit * @param shell * @param page */ - public BlameOperation(Repository repository, IFile file, Shell shell, - IWorkbenchPage page) { + public BlameOperation(Repository repository, IStorage storage, String path, + AnyObjectId startCommit, Shell shell, IWorkbenchPage page) { this.repository = repository; - this.file = file; + this.storage = storage; + this.path = path; + this.startCommit = startCommit; this.shell = shell; this.page = page; } @@ -67,14 +76,11 @@ public class BlameOperation implements IEGitOperation { info.setHoverControlCreator(new BlameInformationControlCreator(false)); info.setInformationPresenterControlCreator(new BlameInformationControlCreator( true)); - RepositoryMapping mapping = RepositoryMapping.getMapping(file - .getProject()); - if (mapping == null) - return; final BlameCommand command = new BlameCommand(repository) - .setFollowFileRenames(true).setFilePath( - mapping.getRepoRelativePath(file)); + .setFollowFileRenames(true).setFilePath(path); + if (startCommit != null) + command.setStartCommit(startCommit); if (Activator.getDefault().getPreferenceStore() .getBoolean(UIPreferences.BLAME_IGNORE_WHITESPACE)) command.setTextComparator(RawTextComparator.WS_IGNORE_ALL); @@ -122,8 +128,13 @@ public class BlameOperation implements IEGitOperation { shell.getDisplay().asyncExec(new Runnable() { public void run() { try { - AbstractDecoratedTextEditor editor = RevisionAnnotationController - .openEditor(page, file); + AbstractDecoratedTextEditor editor; + if (storage instanceof IFile) + editor = RevisionAnnotationController.openEditor(page, + (IFile) storage); + else + editor = RevisionAnnotationController.openEditor(page, + storage, storage); if (editor != null) editor.showRevisionInformation(info, "org.eclipse.egit.ui.internal.decorators.GitQuickDiffProvider"); //$NON-NLS-1$ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitFileDiffViewer.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitFileDiffViewer.java index a801e20a52..ee95fdc090 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitFileDiffViewer.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitFileDiffViewer.java @@ -16,13 +16,17 @@ import org.eclipse.compare.ITypedElement; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; +import org.eclipse.egit.core.internal.job.JobUtil; import org.eclipse.egit.ui.Activator; +import org.eclipse.egit.ui.JobFamilies; +import org.eclipse.egit.ui.UIIcons; import org.eclipse.egit.ui.UIPreferences; import org.eclipse.egit.ui.UIText; import org.eclipse.egit.ui.UIUtils; import org.eclipse.egit.ui.internal.CompareUtils; import org.eclipse.egit.ui.internal.EgitUiEditorUtils; import org.eclipse.egit.ui.internal.GitCompareFileRevisionEditorInput; +import org.eclipse.egit.ui.internal.blame.BlameOperation; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.MenuManager; @@ -86,6 +90,8 @@ public class CommitFileDiffViewer extends TableViewer { private IAction open; + private IAction blame; + private IAction openWorkingTreeVersion; private IAction compare; @@ -194,6 +200,21 @@ public class CommitFileDiffViewer extends TableViewer { } }; + blame = new Action( + UIText.CommitFileDiffViewer_ShowAnnotationsMenuLabel, + UIIcons.ANNOTATE) { + @SuppressWarnings("unchecked") + @Override + public void run() { + final ISelection s = getSelection(); + if (s.isEmpty() || !(s instanceof IStructuredSelection)) + return; + final IStructuredSelection iss = (IStructuredSelection) s; + for (Iterator<FileDiff> it = iss.iterator(); it.hasNext();) + showAnnotations(it.next()); + } + }; + openWorkingTreeVersion = new Action( UIText.CommitFileDiffViewer_OpenWorkingTreeVersionInEditorMenuLabel) { @SuppressWarnings("unchecked") @@ -237,6 +258,7 @@ public class CommitFileDiffViewer extends TableViewer { mgr.add(open); mgr.add(openWorkingTreeVersion); mgr.add(compare); + mgr.add(blame); mgr.add(new Separator()); mgr.add(selectAll = createStandardAction(ActionFactory.SELECT_ALL)); @@ -366,6 +388,38 @@ public class CommitFileDiffViewer extends TableViewer { } } + private void showAnnotations(FileDiff d) { + try { + IWorkbenchWindow window = PlatformUI.getWorkbench() + .getActiveWorkbenchWindow(); + IWorkbenchPage page = window.getActivePage(); + RevCommit commit = d.getChange().equals(ChangeType.DELETE) ? d + .getCommit().getParent(0) : d.getCommit(); + IFileRevision rev = CompareUtils.getFileRevision(d.getPath(), + commit, getRepository(), + d.getChange().equals(ChangeType.DELETE) ? d.getBlobs()[0] + : d.getBlobs()[d.getBlobs().length - 1]); + if (rev != null) { + BlameOperation op = new BlameOperation(getRepository(), + rev.getStorage(new NullProgressMonitor()), d.getPath(), + commit, window.getShell(), page); + JobUtil.scheduleUserJob(op, UIText.ShowBlameHandler_JobName, + JobFamilies.BLAME); + } else { + String message = NLS.bind( + UIText.CommitFileDiffViewer_notContainedInCommit, + d.getPath(), d.getCommit().getId().getName()); + Activator.showError(message, null); + } + } catch (IOException e) { + Activator.logError(UIText.GitHistoryPage_openFailed, e); + Activator.showError(UIText.GitHistoryPage_openFailed, null); + } catch (CoreException e) { + Activator.logError(UIText.GitHistoryPage_openFailed, e); + Activator.showError(UIText.GitHistoryPage_openFailed, null); + } + } + void showTwoWayFileDiff(final FileDiff d) { final GitCompareFileRevisionEditorInput in; diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties index 84ccf2b0f4..4844b83183 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties @@ -1174,6 +1174,7 @@ CommitFileDiffViewer_notContainedInCommit=File {0} is not contained in commit {1 CommitFileDiffViewer_OpenInEditorMenuLabel=Open in &Editor CommitFileDiffViewer_OpenWorkingTreeVersionInEditorMenuLabel=Open Working Tree Version CommitFileDiffViewer_SelectOneCommitMessage=Please select exactly one commit +CommitFileDiffViewer_ShowAnnotationsMenuLabel=Show Annotations CommitGraphTable_CommitId=Id CommitGraphTable_Committer=Committer CommitGraphTable_CompareWithEachOtherInTreeMenuLabel=Compare with Each Other in &Tree |