From b035fc586c571b893934548c696d2a6e6092505a Mon Sep 17 00:00:00 2001 From: Thomas Wolf Date: Thu, 14 Feb 2019 21:26:58 +0100 Subject: [PATCH] Avoid traversing git history for added files "Compare with HEAD" for a file did search the whole git history even for staged added files, which could be very expensive and on some repositories can take very long indeed. Avoid this by checking first whether the file exists at all in the HEAD commit, and only then try to find the last commit that touched it. Otherwise return an empty element. Bug: 544404 Change-Id: Idc9e9e3ba80faeb94b96391c32f58b5365164b8a Signed-off-by: Thomas Wolf --- .../org/eclipse/egit/ui/internal/CompareUtils.java | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) 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 index 5efc88140..b821617b3 100644 --- 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 @@ -918,8 +918,8 @@ public class CompareUtils { * the last commit that modified the file in order to have more useful * author information. *

- * Returns an empty typed element if there is not yet a head (initial import - * case). + * Returns an empty typed element if there is not yet a HEAD (initial import + * case) or the file does not exist in HEAD. *

* If there is an error getting the HEAD commit, it is handled and null * returned. @@ -932,13 +932,23 @@ public class CompareUtils { public static ITypedElement getHeadTypedElement(Repository repository, String repoRelativePath) { try { Ref head = repository.exactRef(Constants.HEAD); - if (head == null || head.getObjectId() == null) + if (head == null || head.getObjectId() == null) { // Initial import, not yet a HEAD commit return new EmptyTypedElement(""); //$NON-NLS-1$ - + } RevCommit latestFileCommit; try (RevWalk rw = new RevWalk(repository)) { RevCommit headCommit = rw.parseCommit(head.getObjectId()); + // Check if the path exists at all in HEAD + try (TreeWalk tw = TreeWalk.forPath(repository, + repoRelativePath, headCommit.getTree())) { + if (tw == null) { + return new GitCompareFileRevisionEditorInput.EmptyTypedElement( + NLS.bind(UIText.GitHistoryPage_FileNotInCommit, + getName(repoRelativePath), + Constants.HEAD)); + } + } rw.markStart(headCommit); rw.setTreeFilter(AndTreeFilter.create( PathFilterGroup.createFromStrings(repoRelativePath), @@ -946,8 +956,9 @@ public class CompareUtils { rw.setRewriteParents(false); latestFileCommit = rw.next(); // Fall back to HEAD - if (latestFileCommit == null) + if (latestFileCommit == null) { latestFileCommit = headCommit; + } } return CompareUtils.getFileRevisionTypedElement(repoRelativePath, latestFileCommit, repository); -- 2.11.4.GIT