From 8de3d09557363f33dee188d7026984d3539bb794 Mon Sep 17 00:00:00 2001 From: Thomas Wolf Date: Fri, 5 May 2017 15:34:05 +0200 Subject: [PATCH] Load the reflog view asynchronously Use a DeferredTreeContentManager to load the reflog: if it's long or the disk is slow or both, it may take some time. Bug: 515606 Change-Id: Ib824e753c030c7a2b37d9407c9a64553d4ebe8a1 Signed-off-by: Thomas Wolf --- .../src/org/eclipse/egit/ui/internal/UIText.java | 3 + .../egit/ui/internal/reflog/ReflogView.java | 51 ++++++++--- .../internal/reflog/ReflogViewContentProvider.java | 101 ++++++++++++++++----- .../org/eclipse/egit/ui/internal/uitext.properties | 1 + 4 files changed, 117 insertions(+), 39 deletions(-) diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java index 6624949f2..b77cda2c6 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java @@ -1568,6 +1568,9 @@ public class UIText extends NLS { public static String ReflogView_DateColumnHeader; /** */ + public static String ReflogView_ErrorOnLoad; + + /** */ public static String ReflogView_ErrorOnOpenCommit; /** */ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/reflog/ReflogView.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/reflog/ReflogView.java index 69d6fae36..33361836c 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/reflog/ReflogView.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/reflog/ReflogView.java @@ -94,6 +94,7 @@ import org.eclipse.ui.forms.events.HyperlinkEvent; import org.eclipse.ui.forms.widgets.Form; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ImageHyperlink; +import org.eclipse.ui.model.IWorkbenchAdapter; import org.eclipse.ui.part.IShowInTarget; import org.eclipse.ui.part.ShowInContext; import org.eclipse.ui.part.ViewPart; @@ -184,19 +185,28 @@ public class ReflogView extends ViewPart implements RefsChangedListener, IShowIn @Override public String getText(Object element) { - final ReflogEntry entry = (ReflogEntry) element; - return entry.getNewId().abbreviate(7).name(); + if (element instanceof ReflogEntry) { + final ReflogEntry entry = (ReflogEntry) element; + return entry.getNewId().abbreviate(7).name(); + } + return null; } @Override public String getToolTipText(Object element) { - final ReflogEntry entry = (ReflogEntry) element; - return entry.getNewId().name(); + if (element instanceof ReflogEntry) { + final ReflogEntry entry = (ReflogEntry) element; + return entry.getNewId().name(); + } + return null; } @Override public Image getImage(Object element) { - return branchImage; + if (element instanceof ReflogEntry) { + return branchImage; + } + return null; } }); @@ -207,9 +217,14 @@ public class ReflogView extends ViewPart implements RefsChangedListener, IShowIn @Override public String getText(Object element) { - final ReflogEntry entry = (ReflogEntry) element; - RevCommit c = getCommit(entry); - return c == null ? "" : c.getShortMessage(); //$NON-NLS-1$ + if (element instanceof ReflogEntry) { + final ReflogEntry entry = (ReflogEntry) element; + RevCommit c = getCommit(entry); + return c == null ? "" : c.getShortMessage(); //$NON-NLS-1$ + } else if (element instanceof IWorkbenchAdapter) { + return ((IWorkbenchAdapter) element).getLabel(element); + } + return null; } private RevCommit getCommit(final ReflogEntry entry) { @@ -229,10 +244,12 @@ public class ReflogView extends ViewPart implements RefsChangedListener, IShowIn @Override public String getText(Object element) { - final ReflogEntry entry = (ReflogEntry) element; - final PersonIdent who = entry.getWho(); - // TODO add option to use RelativeDateFormatter - return dateFormatter.formatDate(who); + if (element instanceof ReflogEntry) { + final ReflogEntry entry = (ReflogEntry) element; + final PersonIdent who = entry.getWho(); + return dateFormatter.formatDate(who); + } + return null; } @Override @@ -251,12 +268,18 @@ public class ReflogView extends ViewPart implements RefsChangedListener, IShowIn @Override public String getText(Object element) { - final ReflogEntry entry = (ReflogEntry) element; - return entry.getComment(); + if (element instanceof ReflogEntry) { + final ReflogEntry entry = (ReflogEntry) element; + return entry.getComment(); + } + return null; } @Override public Image getImage(Object element) { + if (!(element instanceof ReflogEntry)) { + return null; + } String comment = ((ReflogEntry) element).getComment(); if (comment.startsWith("commit:") || comment.startsWith("commit (initial):")) //$NON-NLS-1$ //$NON-NLS-2$ return (Image) resourceManager.get(UIIcons.COMMIT); diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/reflog/ReflogViewContentProvider.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/reflog/ReflogViewContentProvider.java index 501e74e2f..3dd3ffcbd 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/reflog/ReflogViewContentProvider.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/reflog/ReflogViewContentProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, Chris Aniszczyk and others. + * Copyright (c) 2011, 2017 Chris Aniszczyk and others. * 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 @@ -8,31 +8,49 @@ * Contributors: * Chris Aniszczyk - initial implementation * EclipseSource - Filtered Viewer + * Thomas Wolf - deferred loading *******************************************************************************/ package org.eclipse.egit.ui.internal.reflog; +import java.util.Collection; + import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.egit.ui.Activator; +import org.eclipse.egit.ui.internal.UIText; +import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jgit.api.Git; -import org.eclipse.jgit.api.ReflogCommand; +import org.eclipse.jgit.lib.ReflogEntry; import org.eclipse.jgit.lib.Repository; +import org.eclipse.ui.model.WorkbenchAdapter; +import org.eclipse.ui.progress.DeferredTreeContentManager; +import org.eclipse.ui.progress.IDeferredWorkbenchAdapter; +import org.eclipse.ui.progress.IElementCollector; /** - * A content provider for reflog entries given a repository + * A content provider for reflog entries given a repository and a ref. */ public class ReflogViewContentProvider implements ITreeContentProvider { + private DeferredTreeContentManager loader; + + private Object currentInput; + /** * Input class for this content provider */ - public static class ReflogInput { + public static class ReflogInput extends WorkbenchAdapter + implements IDeferredWorkbenchAdapter { private final Repository repository; private final String ref; + private Collection refLog; + /** * Create input with non-null repository and non-null ref * @@ -49,50 +67,83 @@ public class ReflogViewContentProvider implements ITreeContentProvider { /** * Get repository * - * @return repositoyr + * @return repository */ public Repository getRepository() { return repository; } - /** - * Get ref - * - * @return ref - */ - public String getRef() { - return ref; + @Override + public Object[] getChildren(Object o) { + if (refLog != null) { + return refLog.toArray(); + } + return super.getChildren(o); } - } - @Override - public Object[] getElements(Object inputElement) { - if (inputElement instanceof ReflogInput) { - ReflogInput input = (ReflogInput) inputElement; - try (Git git = new Git(input.repository)) { - ReflogCommand command = git.reflog(); - command.setRef(input.ref); - return command.call().toArray(); + @Override + public void fetchDeferredChildren(Object object, + IElementCollector collector, IProgressMonitor monitor) { + try (Git git = new Git(repository)) { + refLog = git.reflog().setRef(ref).call(); + collector.add(refLog.toArray(), monitor); } catch (Exception e) { Activator.logError("Error running reflog command", e); //$NON-NLS-1$ + collector.add(new ErrorElement(), monitor); } } - return new Object[0]; + + @Override + public boolean isContainer() { + return true; + } + + @Override + public ISchedulingRule getRule(Object object) { + return null; + } + } + + private static class ErrorElement extends WorkbenchAdapter { + + @Override + public String getLabel(Object object) { + return UIText.ReflogView_ErrorOnLoad; + } + } + + @Override + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - // TODO + if (oldInput != null && loader != null) { + loader.cancel(oldInput); + } + currentInput = newInput; + if (viewer instanceof AbstractTreeViewer && newInput != null) { + loader = new DeferredTreeContentManager( + (AbstractTreeViewer) viewer); + } } @Override public void dispose() { - // Do nothing + if (currentInput != null && loader != null) { + loader.cancel(currentInput); + } + currentInput = null; + loader = null; } @Override public Object[] getChildren(Object parentElement) { - return null; + if (parentElement instanceof ReflogInput && loader != null) { + return loader.getChildren(parentElement); + } + return new Object[0]; } @Override diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties index 4fd81c1f6..2069cd680 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties @@ -541,6 +541,7 @@ RefContentProposal_trackingBranch=tracking branch RefContentProposal_tree=tree RefContentProposal_unknownObject=locally unknown object ReflogView_DateColumnHeader=Date +ReflogView_ErrorOnLoad=Loading the reflog encountered an error; see the Error Log for more information ReflogView_ErrorOnOpenCommit=Error opening commit ReflogView_MessageColumnHeader=Reflog Message ReflogView_CommitColumnHeader=Commit -- 2.11.4.GIT