From 070b2a2476973a1ed41dcff94fc41e5ad36bc528 Mon Sep 17 00:00:00 2001 From: Stefan Lay Date: Tue, 25 May 2010 12:41:30 +0200 Subject: [PATCH] Fix compare error by checking if blob is contained in commit Opening compare editor on a deleted file in the file list of the History View caused a message to be logged. The reason was that the blob was not found in the commit. This patch makes use of code that was already available for other compare actions. To allow for reuse, a new class CompareUtils is introduced. Bug: 312852 Signed-off-by: Stefan Lay --- .../org/eclipse/egit/ui/internal/CompareUtils.java | 117 ++++++++ .../ui/internal/actions/CompareWithHeadAction.java | 17 +- .../ui/internal/history/CommitFileDiffViewer.java | 302 ++++++++++----------- .../egit/ui/internal/history/GitHistoryPage.java | 47 +--- 4 files changed, 278 insertions(+), 205 deletions(-) create mode 100644 org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java new file mode 100644 index 00000000..0590439d --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/CompareUtils.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2010, SAP AG + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Stefan Lay (SAP AG) - initial implementation + *******************************************************************************/ +package org.eclipse.egit.ui.internal; + +import java.io.IOException; + +import org.eclipse.compare.CompareEditorInput; +import org.eclipse.compare.ITypedElement; +import org.eclipse.egit.core.internal.storage.GitFileRevision; +import org.eclipse.egit.ui.Activator; +import org.eclipse.egit.ui.UIText; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.osgi.util.NLS; +import org.eclipse.team.core.history.IFileRevision; +import org.eclipse.team.internal.ui.history.FileRevisionTypedElement; + +/** + * A collection of helper methods useful for comparing content + */ +public class CompareUtils { + + /** + * + * @param gitPath + * path within the commit's tree of the file. + * @param commit + * the commit the blob was identified to be within. + * @param db + * the repository this commit was loaded out of. + * @return an instance of {@link ITypedElement} which can be used in + * {@link CompareEditorInput} + */ + public static ITypedElement getFileRevisionTypedElement( + final String gitPath, final RevCommit commit, final Repository db) { + return getFileRevisionTypedElement(gitPath, commit, db, null); + } + + /** + * @param gitPath + * path within the commit's tree of the file. + * @param commit + * the commit the blob was identified to be within. + * @param db + * the repository this commit was loaded out of, and that this + * file's blob should also be reachable through. + * @param blobId + * unique name of the content. + * @return an instance of {@link ITypedElement} which can be used in + * {@link CompareEditorInput} + */ + public static ITypedElement getFileRevisionTypedElement( + final String gitPath, final RevCommit commit, final Repository db, + ObjectId blobId) { + ITypedElement right = new GitCompareFileRevisionEditorInput.EmptyTypedElement( + NLS + .bind(UIText.GitHistoryPage_FileNotInCommit, getName(gitPath), + commit)); + + try { + IFileRevision nextFile = getFileRevision(gitPath, commit, db, blobId); + if (nextFile != null) + right = new FileRevisionTypedElement(nextFile); + } catch (IOException e) { + Activator.error(NLS.bind(UIText.GitHistoryPage_errorLookingUpPath, + gitPath, commit.getId()), e); + } + return right; + } + + private static String getName(String gitPath) { + final int last = gitPath.lastIndexOf('/'); + return last >= 0 ? gitPath.substring(last + 1) : gitPath; + } + + /** + * + * @param gitPath + * path within the commit's tree of the file. + * @param commit + * the commit the blob was identified to be within. + * @param db + * the repository this commit was loaded out of, and that this + * file's blob should also be reachable through. + * @param blobId + * unique name of the content. + * @return an instance of {@link IFileRevision} or null if the file is not + * contained in {@code commit} + * @throws IOException + */ + public static IFileRevision getFileRevision(final String gitPath, + final RevCommit commit, final Repository db, ObjectId blobId) + throws IOException { + + TreeWalk w = TreeWalk.forPath(db, gitPath, commit.getTree()); + // check if file is contained in commit + if (w != null) { + final IFileRevision fileRevision = GitFileRevision.inCommit(db, + commit, gitPath, blobId); + return fileRevision; + } + return null; + } + + +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithHeadAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithHeadAction.java index 6a7c7f42..f2c95330 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithHeadAction.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithHeadAction.java @@ -15,9 +15,8 @@ import org.eclipse.compare.CompareUI; import org.eclipse.compare.ITypedElement; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; -import org.eclipse.egit.core.internal.storage.GitFileRevision; import org.eclipse.egit.core.project.RepositoryMapping; -import org.eclipse.egit.ui.UIText; +import org.eclipse.egit.ui.internal.CompareUtils; import org.eclipse.egit.ui.internal.GitCompareFileRevisionEditorInput; import org.eclipse.jface.action.IAction; import org.eclipse.jgit.lib.Constants; @@ -25,10 +24,6 @@ import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; -import org.eclipse.jgit.treewalk.TreeWalk; -import org.eclipse.osgi.util.NLS; -import org.eclipse.team.core.history.IFileRevision; -import org.eclipse.team.internal.ui.history.FileRevisionTypedElement; import org.eclipse.team.ui.synchronize.SaveableCompareEditorInput; /** @@ -53,14 +48,8 @@ public class CompareWithHeadAction extends RepositoryAction { RevWalk rw = new RevWalk(repository); RevCommit commit = rw.parseCommit(head.getObjectId()); - next = new GitCompareFileRevisionEditorInput.EmptyTypedElement(NLS.bind(UIText.GitHistoryPage_FileNotInCommit, - resource.getName(), commit)); - TreeWalk w = TreeWalk.forPath(repository, gitPath, commit.getTree()); - // check if file is contained in commit - if (w != null) { - final IFileRevision nextFile = GitFileRevision.inCommit(repository, commit, gitPath, null); - next = new FileRevisionTypedElement(nextFile); - } + next = CompareUtils.getFileRevisionTypedElement(gitPath, commit, + repository); } catch (IOException e) { // this exception is handled by TeamAction.run throw new InvocationTargetException(e); 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 ad9475d0..d566b81e 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 @@ -1,154 +1,148 @@ -/******************************************************************************* - * Copyright (C) 2008, Shawn O. Pearce - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.egit.ui.internal.history; - -import java.util.Iterator; - -import org.eclipse.compare.CompareUI; -import org.eclipse.compare.ITypedElement; -import org.eclipse.egit.core.internal.storage.GitFileRevision; -import org.eclipse.egit.ui.UIText; -import org.eclipse.egit.ui.internal.GitCompareFileRevisionEditorInput; -import org.eclipse.jface.viewers.ColumnWeightData; -import org.eclipse.jface.viewers.IOpenListener; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.OpenEvent; -import org.eclipse.jface.viewers.StructuredSelection; -import org.eclipse.jface.viewers.TableLayout; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.swt.SWT; -import org.eclipse.swt.dnd.Clipboard; -import org.eclipse.swt.dnd.DND; -import org.eclipse.swt.dnd.TextTransfer; -import org.eclipse.swt.dnd.Transfer; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.team.core.history.IFileRevision; -import org.eclipse.team.internal.ui.history.FileRevisionTypedElement; -import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.revwalk.RevCommit; -import org.eclipse.jgit.treewalk.TreeWalk; - -class CommitFileDiffViewer extends TableViewer { - private TreeWalk walker; - - private Clipboard clipboard; - - CommitFileDiffViewer(final Composite parent) { - super(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER - | SWT.FULL_SELECTION); - - final Table rawTable = getTable(); - rawTable.setHeaderVisible(true); - rawTable.setLinesVisible(true); - - final TableLayout layout = new TableLayout(); - rawTable.setLayout(layout); - createColumns(rawTable, layout); - - setLabelProvider(new FileDiffLabelProvider()); - setContentProvider(new FileDiffContentProvider()); - addOpenListener(new IOpenListener() { - public void open(final OpenEvent event) { - final ISelection s = event.getSelection(); - if (s.isEmpty() || !(s instanceof IStructuredSelection)) - return; - final IStructuredSelection iss = (IStructuredSelection) s; - final FileDiff d = (FileDiff) iss.getFirstElement(); - if (walker != null && d.blobs.length == 2) - showTwoWayFileDiff(d); - } - }); - - clipboard = new Clipboard(rawTable.getDisplay()); - rawTable.addDisposeListener(new DisposeListener() { - public void widgetDisposed(final DisposeEvent e) { - clipboard.dispose(); - } - }); - } - - void showTwoWayFileDiff(final FileDiff d) { - final GitCompareFileRevisionEditorInput in; - - final Repository db = walker.getRepository(); - final String p = d.path; - final RevCommit c = d.commit; - final IFileRevision baseFile; - final IFileRevision nextFile; - final ITypedElement base; - final ITypedElement next; - - baseFile = GitFileRevision.inCommit(db, c.getParent(0), p, d.blobs[0]); - nextFile = GitFileRevision.inCommit(db, c, p, d.blobs[1]); - - base = new FileRevisionTypedElement(baseFile); - next = new FileRevisionTypedElement(nextFile); - in = new GitCompareFileRevisionEditorInput(base, next, null); - CompareUI.openCompareEditor(in); - } - - TreeWalk getTreeWalk() { - return walker; - } - - void setTreeWalk(final TreeWalk walk) { - walker = walk; - } - - void doSelectAll() { - final IStructuredContentProvider cp; - final Object in = getInput(); - if (in == null) - return; - - cp = ((IStructuredContentProvider) getContentProvider()); - final Object[] el = cp.getElements(in); - if (el == null || el.length == 0) - return; - setSelection(new StructuredSelection(el)); - } - - void doCopy() { - final ISelection s = getSelection(); - if (s.isEmpty() || !(s instanceof IStructuredSelection)) - return; - final IStructuredSelection iss = (IStructuredSelection) s; - final Iterator itr = iss.iterator(); - final StringBuilder r = new StringBuilder(); - while (itr.hasNext()) { - final FileDiff d = itr.next(); - if (r.length() > 0) - r.append("\n"); //$NON-NLS-1$ - r.append(d.path); - } - - clipboard.setContents(new Object[] { r.toString() }, - new Transfer[] { TextTransfer.getInstance() }, DND.CLIPBOARD); - } - - private void createColumns(final Table rawTable, final TableLayout layout) { - final TableColumn mode = new TableColumn(rawTable, SWT.NONE); - mode.setResizable(true); - mode.setText(""); //$NON-NLS-1$ - mode.setWidth(5); - layout.addColumnData(new ColumnWeightData(1, true)); - - final TableColumn path = new TableColumn(rawTable, SWT.NONE); - path.setResizable(true); - path.setText(UIText.HistoryPage_pathnameColumn); - path.setWidth(250); - layout.addColumnData(new ColumnWeightData(20, true)); - } -} +/******************************************************************************* + * Copyright (C) 2008, Shawn O. Pearce + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.egit.ui.internal.history; + +import java.util.Iterator; + +import org.eclipse.compare.CompareUI; +import org.eclipse.compare.ITypedElement; +import org.eclipse.egit.ui.UIText; +import org.eclipse.egit.ui.internal.CompareUtils; +import org.eclipse.egit.ui.internal.GitCompareFileRevisionEditorInput; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.IOpenListener; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.OpenEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableLayout; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.DND; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.dnd.Transfer; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; + +class CommitFileDiffViewer extends TableViewer { + private TreeWalk walker; + + private Clipboard clipboard; + + CommitFileDiffViewer(final Composite parent) { + super(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER + | SWT.FULL_SELECTION); + + final Table rawTable = getTable(); + rawTable.setHeaderVisible(true); + rawTable.setLinesVisible(true); + + final TableLayout layout = new TableLayout(); + rawTable.setLayout(layout); + createColumns(rawTable, layout); + + setLabelProvider(new FileDiffLabelProvider()); + setContentProvider(new FileDiffContentProvider()); + addOpenListener(new IOpenListener() { + public void open(final OpenEvent event) { + final ISelection s = event.getSelection(); + if (s.isEmpty() || !(s instanceof IStructuredSelection)) + return; + final IStructuredSelection iss = (IStructuredSelection) s; + final FileDiff d = (FileDiff) iss.getFirstElement(); + if (walker != null && d.blobs.length == 2) + showTwoWayFileDiff(d); + } + }); + + clipboard = new Clipboard(rawTable.getDisplay()); + rawTable.addDisposeListener(new DisposeListener() { + public void widgetDisposed(final DisposeEvent e) { + clipboard.dispose(); + } + }); + } + + void showTwoWayFileDiff(final FileDiff d) { + final GitCompareFileRevisionEditorInput in; + + final Repository db = walker.getRepository(); + final String p = d.path; + final RevCommit c = d.commit; + final ITypedElement base; + final ITypedElement next; + + base = CompareUtils.getFileRevisionTypedElement(p, c.getParent(0), db, d.blobs[0]); + next = CompareUtils.getFileRevisionTypedElement(p, c, db, d.blobs[1]); + + in = new GitCompareFileRevisionEditorInput(base, next, null); + CompareUI.openCompareEditor(in); + } + + TreeWalk getTreeWalk() { + return walker; + } + + void setTreeWalk(final TreeWalk walk) { + walker = walk; + } + + void doSelectAll() { + final IStructuredContentProvider cp; + final Object in = getInput(); + if (in == null) + return; + + cp = ((IStructuredContentProvider) getContentProvider()); + final Object[] el = cp.getElements(in); + if (el == null || el.length == 0) + return; + setSelection(new StructuredSelection(el)); + } + + void doCopy() { + final ISelection s = getSelection(); + if (s.isEmpty() || !(s instanceof IStructuredSelection)) + return; + final IStructuredSelection iss = (IStructuredSelection) s; + final Iterator itr = iss.iterator(); + final StringBuilder r = new StringBuilder(); + while (itr.hasNext()) { + final FileDiff d = itr.next(); + if (r.length() > 0) + r.append("\n"); //$NON-NLS-1$ + r.append(d.path); + } + + clipboard.setContents(new Object[] { r.toString() }, + new Transfer[] { TextTransfer.getInstance() }, DND.CLIPBOARD); + } + + private void createColumns(final Table rawTable, final TableLayout layout) { + final TableColumn mode = new TableColumn(rawTable, SWT.NONE); + mode.setResizable(true); + mode.setText(""); //$NON-NLS-1$ + mode.setWidth(5); + layout.addColumnData(new ColumnWeightData(1, true)); + + final TableColumn path = new TableColumn(rawTable, SWT.NONE); + path.setResizable(true); + path.setText(UIText.HistoryPage_pathnameColumn); + path.setWidth(250); + layout.addColumnData(new ColumnWeightData(20, true)); + } +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java index a4be3b5b..59f570db 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java @@ -30,12 +30,12 @@ import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.egit.core.ResourceList; -import org.eclipse.egit.core.internal.storage.GitFileRevision; import org.eclipse.egit.core.project.RepositoryMapping; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIIcons; import org.eclipse.egit.ui.UIPreferences; import org.eclipse.egit.ui.UIText; +import org.eclipse.egit.ui.internal.CompareUtils; import org.eclipse.egit.ui.internal.GitCompareFileRevisionEditorInput; import org.eclipse.egit.ui.internal.trace.GitTraceLocation; import org.eclipse.jface.action.Action; @@ -91,7 +91,6 @@ import org.eclipse.team.core.history.IFileRevision; import org.eclipse.team.internal.ui.IPreferenceIds; import org.eclipse.team.internal.ui.TeamUIPlugin; import org.eclipse.team.internal.ui.Utils; -import org.eclipse.team.internal.ui.history.FileRevisionTypedElement; import org.eclipse.team.ui.history.HistoryPage; import org.eclipse.team.ui.synchronize.SaveableCompareEditorInput; import org.eclipse.ui.IActionBars; @@ -400,7 +399,8 @@ public class GitHistoryPage extends HistoryPage implements RepositoryListener { final String gitPath = mapping.getRepoRelativePath(resource); IStructuredSelection selection = (IStructuredSelection) event.getSelection(); SWTCommit commit = (SWTCommit) selection.getFirstElement(); - ITypedElement right = getFileRevisionTypedElement(resource, gitPath, commit); + ITypedElement right = CompareUtils + .getFileRevisionTypedElement(gitPath, commit, db); final GitCompareFileRevisionEditorInput in = new GitCompareFileRevisionEditorInput( SaveableCompareEditorInput.createFileElement(resource), right, @@ -438,36 +438,6 @@ public class GitHistoryPage extends HistoryPage implements RepositoryListener { Repository.addAnyRepositoryChangedListener(this); } - private ITypedElement getFileRevisionTypedElement(final IFile resource, - final String gitPath, SWTCommit commit) { - ITypedElement right = new GitCompareFileRevisionEditorInput.EmptyTypedElement( - NLS.bind(UIText.GitHistoryPage_FileNotInCommit, resource - .getName(), commit)); - - try { - IFileRevision nextFile = getFileRevision(resource, gitPath, commit); - if (nextFile != null) - right = new FileRevisionTypedElement(nextFile); - } catch (IOException e) { - Activator.error(NLS.bind(UIText.GitHistoryPage_errorLookingUpPath, - gitPath, commit.getId()), e); - } - return right; - } - - private IFileRevision getFileRevision(final IFile resource, - final String gitPath, SWTCommit commit) throws IOException { - - TreeWalk w = TreeWalk.forPath(db, gitPath, commit.getTree()); - // check if file is contained in commit - if (w != null) { - final IFileRevision fileRevision = GitFileRevision.inCommit(db, - commit, gitPath, null); - return fileRevision; - } - return null; - } - private void openInCompare(CompareEditorInput input) { IWorkbenchPage workBenchPage = getSite().getPage(); IEditorPart editor = findReusableCompareEditor(input, workBenchPage); @@ -1227,7 +1197,8 @@ public class GitHistoryPage extends HistoryPage implements RepositoryListener { IFile file = (IFile) getInput(); final RepositoryMapping mapping = RepositoryMapping.getMapping(file.getProject()); final String gitPath = mapping.getRepoRelativePath(file); - ITypedElement right = getFileRevisionTypedElement(file, gitPath, commit); + ITypedElement right = CompareUtils + .getFileRevisionTypedElement(gitPath, commit, db); final GitCompareFileRevisionEditorInput in = new GitCompareFileRevisionEditorInput( SaveableCompareEditorInput.createFileElement(file), right, @@ -1270,8 +1241,10 @@ public class GitHistoryPage extends HistoryPage implements RepositoryListener { final String gitPath = map .getRepoRelativePath(resource); - final ITypedElement base = getFileRevisionTypedElement(resource, gitPath, commit1); - final ITypedElement next = getFileRevisionTypedElement(resource, gitPath, commit2); + final ITypedElement base = CompareUtils + .getFileRevisionTypedElement(gitPath, commit1, db); + final ITypedElement next = CompareUtils + .getFileRevisionTypedElement(gitPath, commit2, db); CompareEditorInput in = new GitCompareFileRevisionEditorInput(base, next, null); openInCompare(in); } @@ -1314,7 +1287,7 @@ public class GitHistoryPage extends HistoryPage implements RepositoryListener { SWTCommit commit = (SWTCommit) it.next(); IFileRevision rev = null; try { - rev = getFileRevision(resource, gitPath, commit); + rev = CompareUtils.getFileRevision(gitPath, commit, db, null); } catch (IOException e) { Activator.logError(NLS.bind( UIText.GitHistoryPage_errorLookingUpPath, gitPath, -- 2.11.4.GIT