Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Neumann2019-09-18 05:14:54 -0400
committerThomas Wolf2019-11-11 17:28:59 -0500
commit16f145f4a8b8a76331e8d2c94fce4bdf01e777a5 (patch)
treeb79846c0d0095f68cee6648bba5d475f68dc12eb
parent558a1bc2de76751caef2aec724fc6f5aeade51f6 (diff)
downloadegit-16f145f4a8b8a76331e8d2c94fce4bdf01e777a5.tar.gz
egit-16f145f4a8b8a76331e8d2c94fce4bdf01e777a5.tar.xz
egit-16f145f4a8b8a76331e8d2c94fce4bdf01e777a5.zip
GitHistoryView: Add ability to select refs to show
This commit adds: * Helper class to manage ref filter preferences (repo specific) * Changes to MenuBar * New Dialog to configure Ref filters * Fixes for existing tests, which were broken by this change * New tests for the new features CQ: 21056 Bug: 381520 Change-Id: I5e2eb4daa843e91ca120da45c09482e5ba82a6af Signed-off-by: Tim Neumann <Tim.Neumann@advantest.com>
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/RepositoryUtil.java37
-rw-r--r--org.eclipse.egit.ui.test/META-INF/MANIFEST.MF2
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java25
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/GitHistoryRefFilterConfigurationDialogTest.java755
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/HistoryViewTest.java390
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/RefFilterHelperTest.java697
-rw-r--r--org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/RefFilterUtil.java74
-rw-r--r--org.eclipse.egit.ui/META-INF/MANIFEST.MF3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java9
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java6
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java49
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ReplaceWithCommitActionHandler.java7
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitSelectionDialog.java44
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java310
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryRefFilterConfigurationDialog.java490
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryWalk.java24
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/RefFilterHelper.java727
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/SWTWalk.java5
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties21
19 files changed, 3552 insertions, 123 deletions
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/RepositoryUtil.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/RepositoryUtil.java
index e3172fb0f..f7744209f 100644
--- a/org.eclipse.egit.core/src/org/eclipse/egit/core/RepositoryUtil.java
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/RepositoryUtil.java
@@ -409,6 +409,43 @@ public class RepositoryUtil {
}
/**
+ * Get the repository specific preference key for the given preference key
+ * and repository.
+ *
+ * @param repositoryId
+ * The id of the repository to get the key for
+ * @param preferenceKey
+ * The preference key to get the repository specific one for
+ * @return The repository specific key
+ */
+ public String getRepositorySpecificPreferenceKey(String repositoryId,
+ String preferenceKey) {
+ return preferenceKey + "_" + repositoryId; //$NON-NLS-1$
+ }
+
+ /**
+ * Get the repository specific preference key for the given preference key
+ * and repository.
+ *
+ * @param repository
+ * The repository to get the key for
+ * @param preferenceKey
+ * The preference key to get the repository specific one for
+ * @return The repository specific key
+ */
+ public String getRepositorySpecificPreferenceKey(
+ @NonNull Repository repository, String preferenceKey) {
+ String pathString = getRelativizedRepositoryPath(repository);
+
+ if (pathString == null) {
+ return getRepositorySpecificPreferenceKey(repository.toString(),
+ preferenceKey);
+ }
+
+ return getRepositorySpecificPreferenceKey(pathString, preferenceKey);
+ }
+
+ /**
* @return the underlying preferences
*/
public IEclipsePreferences getPreferences() {
diff --git a/org.eclipse.egit.ui.test/META-INF/MANIFEST.MF b/org.eclipse.egit.ui.test/META-INF/MANIFEST.MF
index 2a7b8522a..d81fc7c66 100644
--- a/org.eclipse.egit.ui.test/META-INF/MANIFEST.MF
+++ b/org.eclipse.egit.ui.test/META-INF/MANIFEST.MF
@@ -52,4 +52,6 @@ Import-Package: net.bytebuddy;version="[1.7.9,2.0.0)",
org.mockito;version="[2.13.0,3.0.0)",
org.mockito.junit;version="[2.13.0,3.0.0)",
org.mockito.stubbing;version="[2.13.0,3.0.0)",
+ org.mockito.hamcrest;version="[2.13.0,3.0.0)",
+ org.mockito.invocation;version="[2.13.0,3.0.0)",
org.osgi.framework;version="[1.4.0,2.0.0)"
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java
index e3a6abfe6..acdafde08 100644
--- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/common/LocalRepositoryTestCase.java
@@ -142,6 +142,8 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase {
protected static final String REPO2 = "RemoteRepository";
+ protected static final String REMOTE_REPO_SIMPLE = "SimpleRemoteRepository";
+
protected static final String CHILDREPO = "ChildRepository";
/** A general project containing FOLDER containing FILE1 and FILE2 */
@@ -485,6 +487,29 @@ public abstract class LocalRepositoryTestCase extends EGitTestCase {
return mapping;
}
+ protected File createSimpleRemoteRepository(File repositoryDir)
+ throws Exception {
+ Repository myRepository = lookupRepository(repositoryDir);
+ File gitDir = new File(testDirectory, REMOTE_REPO_SIMPLE);
+ Repository myRemoteRepository = FileRepositoryBuilder.create(gitDir);
+ myRemoteRepository.create(true);
+ // double-check that this is bare
+ assertTrue(myRemoteRepository.isBare());
+
+ // now we configure the remote
+ myRepository.getConfig().setString("remote", "origin", "url",
+ "file:///" + myRemoteRepository.getDirectory().getPath());
+ myRepository.getConfig().setString("remote", "origin", "fetch",
+ "+refs/heads/*:refs/remotes/origin/*");
+ myRepository.getConfig().save();
+
+ // and push
+ PushOperationUI pa = new PushOperationUI(myRepository, "origin", false);
+ pa.execute(null);
+
+ return myRemoteRepository.getDirectory();
+ }
+
protected File createRemoteRepository(File repositoryDir)
throws Exception {
Repository myRepository = lookupRepository(repositoryDir);
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/GitHistoryRefFilterConfigurationDialogTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/GitHistoryRefFilterConfigurationDialogTest.java
new file mode 100644
index 000000000..954013d12
--- /dev/null
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/GitHistoryRefFilterConfigurationDialogTest.java
@@ -0,0 +1,755 @@
+/*******************************************************************************
+ * Copyright (C) 2019, Tim Neumann <Tim.Neumann@advantest.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.egit.ui.test.history;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anySet;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.eclipse.egit.core.RepositoryUtil;
+import org.eclipse.egit.ui.Activator;
+import org.eclipse.egit.ui.common.LocalRepositoryTestCase;
+import org.eclipse.egit.ui.internal.UIText;
+import org.eclipse.egit.ui.internal.history.GitHistoryRefFilterConfigurationDialog;
+import org.eclipse.egit.ui.internal.history.RefFilterHelper;
+import org.eclipse.egit.ui.internal.history.RefFilterHelper.RefFilter;
+import org.eclipse.egit.ui.view.repositories.GitRepositoriesViewTestUtils;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotButton;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTableItem;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
+import org.eclipse.ui.PlatformUI;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+@RunWith(SWTBotJunit4ClassRunner.class)
+public class GitHistoryRefFilterConfigurationDialogTest
+ extends LocalRepositoryTestCase {
+ private Display display;
+
+ private Repository repo;
+
+ private SWTBotShell dialogBot;
+
+ private GitHistoryRefFilterConfigurationDialog dialog;
+
+ private RefFilterHelper refFilterHelper;
+
+ private GitRepositoriesViewTestUtils myRepoViewUtil;
+
+ private RefFilter newRefFilter(String filterString, boolean preConfigured,
+ boolean selected) {
+ return RefFilterUtil.newRefFilter(refFilterHelper, filterString,
+ preConfigured, selected);
+ }
+
+ @Before
+ public void setupTests() throws Exception {
+ display = PlatformUI.getWorkbench().getDisplay();
+
+ myRepoViewUtil = new GitRepositoriesViewTestUtils();
+ File repoFile = createProjectAndCommitToRepository();
+
+ RepositoryUtil repositoryUtil = Activator.getDefault()
+ .getRepositoryUtil();
+ repositoryUtil.addConfiguredRepository(repoFile);
+
+ repo = myRepoViewUtil.lookupRepository(repoFile);
+
+ refFilterHelper = mock(RefFilterHelper.class);
+
+ List<RefFilter> testFilters = new ArrayList<>();
+ testFilters.add(newRefFilter("HEAD", true, false));
+ testFilters.add(newRefFilter("refs/**/[CURRENT-BRANCH]", true, false));
+ testFilters.add(newRefFilter("refs/heads/**", true, true));
+ testFilters.add(newRefFilter("refs/remotes/**", true, false));
+ testFilters.add(newRefFilter("refs/tags/**", true, false));
+ testFilters.add(newRefFilter("Mock", false, false));
+ testFilters.add(newRefFilter("test", false, false));
+ testFilters.add(newRefFilter("filter", false, true));
+
+ when(refFilterHelper.getRefFilters())
+ .thenReturn(new HashSet<>(testFilters));
+
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Set<RefFilter> filters = invocation.getArgument(0);
+ for (RefFilter filter : filters) {
+ filter.setSelected(filter.equals(testFilters.get(0)));
+ }
+ return null;
+ }
+ }).when(refFilterHelper).selectOnlyHEAD(anySet());
+
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Set<RefFilter> filters = invocation.getArgument(0);
+ for (RefFilter filter : filters) {
+ filter.setSelected(filter.equals(testFilters.get(1)));
+ }
+ return null;
+ }
+ }).when(refFilterHelper).selectOnlyCurrentBranch(anySet());
+
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Set<RefFilter> filters = invocation.getArgument(0);
+ for (RefFilter filter : filters) {
+ filter.setSelected(filter.equals(testFilters.get(0))
+ || filter.equals(testFilters.get(2))
+ || filter.equals(testFilters.get(3))
+ || filter.equals(testFilters.get(4)));
+ }
+ return null;
+ }
+ }).when(refFilterHelper).selectExactlyAllBranchesAndTags(anySet());
+
+ List<RefFilter> defaults = new ArrayList<>();
+ defaults.add(newRefFilter("HEAD", true, true));
+ defaults.add(newRefFilter("refs/**/[CURRENT-BRANCH]", true, false));
+ defaults.add(newRefFilter("refs/heads/**", true, false));
+ defaults.add(newRefFilter("refs/remotes/**", true, false));
+ defaults.add(newRefFilter("refs/tags/**", true, false));
+
+ when(refFilterHelper.getDefaults())
+ .thenReturn(new HashSet<>(defaults));
+
+ display.asyncExec(() -> {
+ dialog = new GitHistoryRefFilterConfigurationDialog(
+ display.getActiveShell(), repo, refFilterHelper);
+ dialog.open();
+ });
+ dialogBot = bot
+ .shell(UIText.GitHistoryPage_filterRefDialog_dialogTitle);
+ }
+
+ @After
+ public void teardown() {
+ myRepoViewUtil.dispose();
+ display.asyncExec(dialog::close);
+ }
+
+ private static class RefFilterInfo {
+ private final String filterString;
+
+ private final boolean preConfigured;
+
+ private final boolean checked;
+
+ public RefFilterInfo(String filterString, boolean preConfigured,
+ boolean checked) {
+ this.filterString = filterString;
+ this.preConfigured = preConfigured;
+ this.checked = checked;
+ }
+
+ public String getFilterString() {
+ return filterString;
+ }
+
+ public boolean isPreConfigured() {
+ return preConfigured;
+ }
+
+ public boolean isChecked() {
+ return checked;
+ }
+ }
+
+ private List<Matcher<? super RefFilter>> getRefFilterMatchersFromInfos(
+ List<RefFilterInfo> infos) {
+ return infos.stream().map(info -> newRefFilterMatcher(info))
+ .collect(Collectors.toList());
+ }
+
+ private Matcher<RefFilter> newRefFilterMatcher(RefFilterInfo info) {
+ return RefFilterUtil.newRefFilterMatcher(info.getFilterString(),
+ info.isPreConfigured(), info.isChecked());
+ }
+
+ private List<Matcher<? super SWTBotTableItem>> getTableRowMatchersFromInfos(
+ List<RefFilterInfo> infos) {
+ return infos.stream().map(info -> newTableRowMatcher(info))
+ .collect(Collectors.toList());
+ }
+
+ private Matcher<SWTBotTableItem> newTableRowMatcher(RefFilterInfo info) {
+ return newTableRowMatcher(info.getFilterString(),
+ info.isPreConfigured(), info.isChecked());
+ }
+
+ private Matcher<SWTBotTableItem> newTableRowMatcher(String text,
+ boolean preConfigured, boolean checked) {
+ return new TypeSafeMatcher<SWTBotTableItem>() {
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("A table row with ");
+ description.appendValue(text);
+ description.appendText(" which is ");
+ if (!checked) {
+ description.appendText("_not_ ");
+ }
+ description.appendText("checked");
+
+ }
+
+ private boolean matchText(String itemText) {
+ if (preConfigured) {
+ return Objects.equals(itemText,
+ text + " - (preconfigured)");
+ } else {
+ return Objects.equals(itemText, text);
+ }
+ }
+
+ @Override
+ protected boolean matchesSafely(SWTBotTableItem item) {
+ return matchText(item.getText()) && item.isChecked() == checked;
+ }
+ };
+ }
+
+ private List<SWTBotTableItem> listOfRows(SWTBotTable table) {
+ int rows = table.rowCount();
+ List<SWTBotTableItem> result = new ArrayList<>(rows);
+ for (int i = 0; i < rows; i++) {
+ result.add(table.getTableItem(i));
+ }
+ return result;
+ }
+
+ private void click(String button) {
+ SWTBotButton btn = dialogBot.bot().button(button);
+ btn.click();
+ }
+
+ private void clickOk() {
+ click(IDialogConstants.OK_LABEL);
+ }
+
+ private void clickCancel() {
+ click(IDialogConstants.CANCEL_LABEL);
+ }
+
+ @SuppressWarnings("unchecked")
+ private ArgumentCaptor<Set<RefFilter>> newRefFilterSetArgCaptor() {
+ return ArgumentCaptor.forClass(Set.class);
+ }
+
+ private void verifyTableContents(List<RefFilterInfo> expected) {
+ SWTBotTable table = dialogBot.bot().table();
+
+ assertThat("Expeceted different rows", listOfRows(table),
+ contains(getTableRowMatchersFromInfos(expected)));
+ }
+
+ private void verifyResult(List<RefFilterInfo> expected) {
+ ArgumentCaptor<Set<RefFilter>> argument = newRefFilterSetArgCaptor();
+ verify(refFilterHelper, times(1)).setRefFilters(argument.capture());
+
+ assertThat("Expected different set to be saved", argument.getValue(),
+ containsInAnyOrder(getRefFilterMatchersFromInfos(expected)));
+ }
+
+ private void verifyTableContentsClickOkAndVerifyResult(
+ List<RefFilterInfo> expected) {
+ verifyTableContents(expected);
+ clickOk();
+ verifyResult(expected);
+ }
+
+ @Test
+ public void testInitialTableContent() throws Exception {
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, false));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, true));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+ expected.add(new RefFilterInfo("filter", false, true));
+ expected.add(new RefFilterInfo("Mock", false, false));
+ expected.add(new RefFilterInfo("test", false, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ @Test
+ public void testCheckOne() throws Exception {
+ SWTBotTable table = dialogBot.bot().table();
+
+ table.getTableItem(0).check();
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, true));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, true));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+ expected.add(new RefFilterInfo("filter", false, true));
+ expected.add(new RefFilterInfo("Mock", false, false));
+ expected.add(new RefFilterInfo("test", false, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ @Test
+ public void testCheckTwo() throws Exception {
+ SWTBotTable table = dialogBot.bot().table();
+
+ table.getTableItem(3).check();
+ table.getTableItem(6).check();
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, false));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, true));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, true));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+ expected.add(new RefFilterInfo("filter", false, true));
+ expected.add(new RefFilterInfo("Mock", false, true));
+ expected.add(new RefFilterInfo("test", false, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ @Test
+ public void testUncheckOne() throws Exception {
+ SWTBotTable table = dialogBot.bot().table();
+
+ table.getTableItem(2).uncheck();
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, false));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, false));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+ expected.add(new RefFilterInfo("filter", false, true));
+ expected.add(new RefFilterInfo("Mock", false, false));
+ expected.add(new RefFilterInfo("test", false, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ @Test
+ public void testUncheckTwo() throws Exception {
+ SWTBotTable table = dialogBot.bot().table();
+
+ table.getTableItem(2).uncheck();
+ table.getTableItem(5).uncheck();
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, false));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, false));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+ expected.add(new RefFilterInfo("filter", false, false));
+ expected.add(new RefFilterInfo("Mock", false, false));
+ expected.add(new RefFilterInfo("test", false, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ @Test
+ public void testUncheckAndCheck() throws Exception {
+ SWTBotTable table = dialogBot.bot().table();
+
+ table.getTableItem(2).uncheck();
+ table.getTableItem(7).check();
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, false));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, false));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+ expected.add(new RefFilterInfo("filter", false, true));
+ expected.add(new RefFilterInfo("Mock", false, false));
+ expected.add(new RefFilterInfo("test", false, true));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ private Event createEvent(Control control) {
+ Event event = new Event();
+ event.keyCode = SWT.NONE;
+ event.stateMask = SWT.NONE;
+ event.doit = true;
+ event.widget = control;
+ event.button = 1;
+ return event;
+ }
+
+ private void keyEvent(Control control, int keyCode) {
+ Event event = createEvent(control);
+ event.button = 0;
+ event.type = SWT.KeyDown;
+ event.keyCode = keyCode;
+ event.character = (char) keyCode;
+
+ Display.getDefault().post(event);
+
+ event.type = SWT.KeyUp;
+
+ Display.getDefault().post(event);
+ }
+
+ private void typeTextAndEnter(String text) {
+ Control c = dialog.getShell();
+ for (int i = 0; i < text.length(); i++) {
+ keyEvent(c, text.charAt(i));
+ }
+ keyEvent(c, 13);
+ }
+
+ @Test
+ public void testAdd() throws Exception {
+ click(UIText.GitHistoryPage_filterRefDialog_button_add);
+
+ typeTextAndEnter("added");
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, false));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, true));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+ expected.add(new RefFilterInfo("added", false, false));
+ expected.add(new RefFilterInfo("filter", false, true));
+ expected.add(new RefFilterInfo("Mock", false, false));
+ expected.add(new RefFilterInfo("test", false, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ private SWTBotTreeItem findMaster(SWTBotTreeItem[] items) {
+ for (SWTBotTreeItem item : items) {
+ if (item.getText().startsWith("master")) {
+ return item;
+ }
+ }
+
+ SWTBotTreeItem found = null;
+
+ for (SWTBotTreeItem item : items) {
+ found = findMaster(item.getItems());
+ if (found != null) {
+ return found;
+ }
+ }
+
+ return null;
+ }
+
+ @Test
+ public void testAddRef() throws Exception {
+ click(UIText.GitHistoryPage_filterRefDialog_button_addRef);
+ SWTBotShell refSelectDialogBot = bot.shell(
+ UIText.GitHistoryPage_filterRefDialog_selectRefDialog_dialogTitle);
+
+ SWTBotTree treeBot = refSelectDialogBot.bot().tree();
+ SWTBotTreeItem[] items = treeBot.getAllItems();
+
+ SWTBotTreeItem masterItem = findMaster(items);
+
+ if (masterItem == null) {
+ fail("No master branch in select ref dialog.");
+ } else {
+ masterItem.select();
+ }
+
+ refSelectDialogBot.bot().button(IDialogConstants.OK_LABEL).click();
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, false));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, true));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+ expected.add(new RefFilterInfo("filter", false, true));
+ expected.add(new RefFilterInfo("Mock", false, false));
+ expected.add(new RefFilterInfo("refs/heads/master", false, false));
+ expected.add(new RefFilterInfo("test", false, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ @Test
+ public void testRemove() throws Exception {
+ SWTBotTable table = dialogBot.bot().table();
+ table.getTableItem(5).select();
+ click(UIText.GitHistoryPage_filterRefDialog_button_remove);
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, false));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, true));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+ expected.add(new RefFilterInfo("Mock", false, false));
+ expected.add(new RefFilterInfo("test", false, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ @Test
+ public void testEdit() throws Exception {
+ SWTBotTable table = dialogBot.bot().table();
+ table.getTableItem(5).select();
+ click(UIText.GitHistoryPage_filterRefDialog_button_edit);
+
+ typeTextAndEnter("edited");
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, false));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, true));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+ expected.add(new RefFilterInfo("edited", false, true));
+ expected.add(new RefFilterInfo("Mock", false, false));
+ expected.add(new RefFilterInfo("test", false, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ @Test
+ public void testDoubleClick() throws Exception {
+ SWTBotTable table = dialogBot.bot().table();
+ SWTBotTableItem item = table.getTableItem(5);
+ item.doubleClick();
+
+ typeTextAndEnter("edited");
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, false));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, true));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+ expected.add(new RefFilterInfo("edited", false, true));
+ expected.add(new RefFilterInfo("Mock", false, false));
+ expected.add(new RefFilterInfo("test", false, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ @Test
+ public void testButtonHead() throws Exception {
+
+ click(UIText.GitHistoryPage_filterRefDialog_button_headOnly);
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, true));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, false));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+ expected.add(new RefFilterInfo("filter", false, false));
+ expected.add(new RefFilterInfo("Mock", false, false));
+ expected.add(new RefFilterInfo("test", false, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ @Test
+ public void testButtonCurrentBranch() throws Exception {
+ click(UIText.GitHistoryPage_filterRefDialog_button_currentBranchOnly);
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, false));
+ expected.add(new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, true));
+ expected.add(new RefFilterInfo("refs/heads/**", true, false));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+ expected.add(new RefFilterInfo("filter", false, false));
+ expected.add(new RefFilterInfo("Mock", false, false));
+ expected.add(new RefFilterInfo("test", false, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ @Test
+ public void testButtonAllBranches() throws Exception {
+ click(UIText.GitHistoryPage_filterRefDialog_button_allBranchesAndTags);
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, true));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, true));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, true));
+ expected.add(new RefFilterInfo("refs/tags/**", true, true));
+ expected.add(new RefFilterInfo("filter", false, false));
+ expected.add(new RefFilterInfo("Mock", false, false));
+ expected.add(new RefFilterInfo("test", false, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ }
+
+ @Test
+ public void testButtonRestoreDefaults() throws Exception {
+ click(JFaceResources.getString("defaults"));
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, true));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, false));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+
+ verifyTableContents(expected);
+ verify(refFilterHelper, Mockito.never())
+ .resetLastSelectionStateToDefault();
+ }
+
+ @Test
+ public void testButtonRestoreDefaultsAndOk() throws Exception {
+ click(JFaceResources.getString("defaults"));
+
+ List<RefFilterInfo> expected = new ArrayList<>();
+ expected.add(new RefFilterInfo("HEAD", true, true));
+ expected.add(
+ new RefFilterInfo("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(new RefFilterInfo("refs/heads/**", true, false));
+ expected.add(new RefFilterInfo("refs/remotes/**", true, false));
+ expected.add(new RefFilterInfo("refs/tags/**", true, false));
+
+ verifyTableContentsClickOkAndVerifyResult(expected);
+ verify(refFilterHelper).resetLastSelectionStateToDefault();
+ }
+
+ @Test
+ public void testButtonRestoreDefaultsAndCancel() throws Exception {
+ click(JFaceResources.getString("defaults"));
+ click(IDialogConstants.CANCEL_LABEL);
+
+ verify(refFilterHelper, Mockito.never())
+ .setRefFilters(ArgumentMatchers.any());
+ verify(refFilterHelper, Mockito.never())
+ .resetLastSelectionStateToDefault();
+ }
+
+ @Test
+ public void testCancel() throws Exception {
+ clickCancel();
+ verify(refFilterHelper, Mockito.never())
+ .setRefFilters(ArgumentMatchers.any());
+ }
+
+ @Test
+ public void testCancelAfterCheck() throws Exception {
+ SWTBotTable table = dialogBot.bot().table();
+
+ table.getTableItem(0).check();
+
+ clickCancel();
+ verify(refFilterHelper, Mockito.never())
+ .setRefFilters(ArgumentMatchers.any());
+ }
+
+ @Test
+ public void testCancelAfterUncheck() throws Exception {
+ SWTBotTable table = dialogBot.bot().table();
+
+ table.getTableItem(2).uncheck();
+
+ clickCancel();
+ verify(refFilterHelper, Mockito.never())
+ .setRefFilters(ArgumentMatchers.any());
+ }
+
+ @Test
+ public void testCancelAfterAdd() throws Exception {
+ click(UIText.GitHistoryPage_filterRefDialog_button_add);
+
+ typeTextAndEnter("added");
+
+ clickCancel();
+ verify(refFilterHelper, Mockito.never())
+ .setRefFilters(ArgumentMatchers.any());
+ }
+
+ @Test
+ public void testCancelAfterEdit() throws Exception {
+ SWTBotTable table = dialogBot.bot().table();
+ table.getTableItem(5).select();
+ click(UIText.GitHistoryPage_filterRefDialog_button_edit);
+
+ typeTextAndEnter("edited");
+
+ clickCancel();
+ verify(refFilterHelper, Mockito.never())
+ .setRefFilters(ArgumentMatchers.any());
+ }
+
+ @Test
+ public void testCancelAfterButtonHead() throws Exception {
+ click(UIText.GitHistoryPage_filterRefDialog_button_headOnly);
+
+ clickCancel();
+ verify(refFilterHelper, Mockito.never())
+ .setRefFilters(ArgumentMatchers.any());
+ }
+}
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/HistoryViewTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/HistoryViewTest.java
index 58db11f58..158862725 100644
--- a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/HistoryViewTest.java
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/HistoryViewTest.java
@@ -13,6 +13,11 @@
package org.eclipse.egit.ui.test.history;
import static org.eclipse.swtbot.swt.finder.matchers.WidgetMatcherFactory.withRegex;
+import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
+import static org.hamcrest.Matchers.emptyArray;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -22,6 +27,9 @@ import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
@@ -34,14 +42,24 @@ import org.eclipse.egit.gitflow.op.InitOperation;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.JobFamilies;
import org.eclipse.egit.ui.internal.UIText;
+import org.eclipse.egit.ui.internal.history.RefFilterHelper;
+import org.eclipse.egit.ui.internal.history.RefFilterHelper.RefFilter;
import org.eclipse.egit.ui.internal.repository.RepositoriesView;
import org.eclipse.egit.ui.test.ContextMenuHelper;
import org.eclipse.egit.ui.test.TestUtil;
import org.eclipse.egit.ui.view.repositories.GitRepositoriesViewTestBase;
import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jgit.api.CheckoutCommand;
+import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
+import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.PushCommand;
+import org.eclipse.jgit.api.ResetCommand;
+import org.eclipse.jgit.api.ResetCommand.ResetType;
+import org.eclipse.jgit.api.TagCommand;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -52,17 +70,21 @@ import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner;
+import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTableItem;
-import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarToggleButton;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarDropDownButton;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree;
import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
import org.eclipse.team.ui.history.IHistoryView;
import org.eclipse.ui.PlatformUI;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@@ -80,6 +102,8 @@ public class HistoryViewTest extends GitRepositoriesViewTestBase {
private File repoFile;
+ private RefFilterHelper refFilterHelper;
+
@Before
public void setupTests() throws Exception {
repoFile = createProjectAndCommitToRepository();
@@ -89,14 +113,117 @@ public class HistoryViewTest extends GitRepositoriesViewTestBase {
folder2.create(false, true, null);
IFile addedFile = folder2.getFile(ADDEDFILE);
addedFile.create(
- new ByteArrayInputStream("More content".getBytes(prj
- .getDefaultCharset())), false, null);
+ new ByteArrayInputStream(
+ "More content".getBytes(prj.getDefaultCharset())),
+ false, null);
addAndCommit(addedFile, ADDEDMESSAGE);
+
// TODO count the commits
commitCount = 3;
+
+ setupAdditionalCommits();
+
RepositoryUtil repositoryUtil = Activator.getDefault()
.getRepositoryUtil();
repositoryUtil.addConfiguredRepository(repoFile);
+
+ Repository repo = myRepoViewUtil.lookupRepository(repoFile);
+
+ refFilterHelper = new RefFilterHelper(repo);
+ refFilterHelper.setRefFilters(refFilterHelper.getDefaults());
+ refFilterHelper.resetLastSelectionStateToDefault();
+ }
+
+ private void checkout(Git git, String ref, boolean create)
+ throws Exception {
+ CheckoutCommand checkout = git.checkout();
+ checkout.setName(ref);
+ checkout.setCreateBranch(create);
+ checkout.setUpstreamMode(SetupUpstreamMode.SET_UPSTREAM);
+ checkout.call();
+ }
+
+ private void commitNewFile(String fileName, String commitMsg)
+ throws Exception {
+ IProject prj = ResourcesPlugin.getWorkspace().getRoot()
+ .getProject(PROJ1);
+ IFile toCreate = prj.getFile(fileName);
+ toCreate.create(
+ new ByteArrayInputStream(
+ "Content".getBytes(prj.getDefaultCharset())),
+ false, null);
+ addAndCommit(toCreate, commitMsg);
+ }
+
+ private static void tag(Git git, String name) throws Exception {
+ TagCommand tag = git.tag();
+ tag.setName(name);
+ PersonIdent committer = new PersonIdent(TestUtil.TESTCOMMITTER_NAME,
+ TestUtil.TESTCOMMITTER_EMAIL);
+ tag.setTagger(committer);
+ Repository repo = git.getRepository();
+ RevCommit headCommit = repo.parseCommit(
+ repo.exactRef(Constants.HEAD).getLeaf().getObjectId());
+ tag.setObjectId(headCommit);
+ tag.call();
+ }
+
+ private void resetHard(Git git, String to) throws Exception {
+ ResetCommand reset = git.reset();
+ reset.setRef(to);
+ reset.setMode(ResetType.HARD);
+ reset.call();
+ }
+
+ private void push(Git git) throws Exception {
+ PushCommand push = git.push();
+ push.setPushAll();
+ push.call();
+ }
+
+ private void fetch(Git git) throws Exception {
+ FetchCommand fetch = git.fetch();
+ fetch.call();
+ }
+
+ private void setupAdditionalCommits() throws Exception {
+ Repository repo = myRepoViewUtil.lookupRepository(repoFile);
+
+ try (Git git = Git.wrap(repo)) {
+ createSimpleRemoteRepository(repoFile);
+
+ checkout(git, "master", false);
+ checkout(git, "testR", true);
+ commitNewFile("testR.txt", "testR");
+ push(git);
+ resetHard(git, "HEAD~");
+
+ checkout(git, "master", false);
+ checkout(git, "testD", true);
+ commitNewFile("testDa.txt", "testDa");
+ push(git);
+ fetch(git);
+ resetHard(git, "HEAD~");
+ commitNewFile("testDb.txt", "testDb");
+
+ checkout(git, "master", false);
+ checkout(git, "test1", true);
+ commitNewFile("test1.txt", "test1");
+
+ commitNewFile("test1t.txt", "test1t");
+ tag(git, "TEST1t");
+ resetHard(git, "HEAD~");
+
+ checkout(git, "master", false);
+ checkout(git, "test2", true);
+ commitNewFile("test2.txt", "test2");
+
+ checkout(git, "master", false);
+ checkout(git, "test12", true);
+ commitNewFile("test12.txt", "test12");
+
+ checkout(git, "master", false);
+ }
}
@Test
@@ -314,7 +441,6 @@ public class HistoryViewTest extends GitRepositoriesViewTestBase {
@Test
public void testSelectBranch() throws Exception {
- toggleShowAllBranchesButton(false);
SWTBotTable commitTable = getHistoryViewTable(PROJ1);
assertEquals("Unexpected number of commits", commitCount,
commitTable.rowCount());
@@ -421,23 +547,226 @@ public class HistoryViewTest extends GitRepositoriesViewTestBase {
assertEquals(commit[0].getId().name(), repo.getBranch());
}
+ private String[] getCommitMsgsFromUi(final SWTBotTable table) {
+ int length = table.rowCount();
+ String[] result = new String[length];
+
+ for (int i = 0; i < length; i++) {
+ RevCommit commit = getCommitInLine(table, i)[0];
+ String msg = commit.getFullMessage();
+ // Want newest commit last.
+ result[length - (1 + i)] = msg;
+ }
+
+ return result;
+ }
+
+ private SWTBotMenu getFilterMenuItem(
+ SWTBotToolbarDropDownButton selectedRefs, String refFilter) {
+ return selectedRefs.menuItem(new TypeSafeMatcher<MenuItem>() {
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(
+ "MenuItem for RefFilter \"" + refFilter + "\"");
+ }
+
+ @Override
+ protected boolean matchesSafely(MenuItem item) {
+ return item.getText().startsWith(refFilter);
+ }
+
+ });
+ }
+
+ private void uncheckRefFilter(SWTBotToolbarDropDownButton selectedRefs,
+ String refFilter) {
+ SWTBotMenu filter = getFilterMenuItem(selectedRefs, refFilter);
+ assertTrue("Expected " + refFilter + " to be checked",
+ filter.isChecked());
+ filter.click();
+ }
+
+ private void checkRefFilter(SWTBotToolbarDropDownButton selectedRefs,
+ String refFilter) {
+ SWTBotMenu filter = getFilterMenuItem(selectedRefs, refFilter);
+ assertTrue("Expected " + refFilter + " to be unchecked",
+ !filter.isChecked());
+ filter.click();
+ }
+
+ private void assertNoCommit(SWTBotTable table) {
+ bot.waitUntil(new DefaultCondition() {
+
+ @Override
+ public boolean test() throws Exception {
+ return table.rowCount() == 0;
+ }
+
+ @Override
+ public String getFailureMessage() {
+ return "CommitGraphTable did not become empty";
+ }
+
+ });
+ Assert.assertThat("Expected no commit", getCommitMsgsFromUi(table),
+ emptyArray());
+ }
+
+ private void assertCommitsAfterBase(SWTBotTable table, String... commitMsgs)
+ throws Exception {
+ TestUtil.waitForJobs(50, 5000);
+ // There are three expected fixed commits, plus then the ones given in
+ // the parameter.
+ int expectedNumberOfCommits = commitMsgs.length + 3;
+ bot.waitUntil(new DefaultCondition() {
+
+ @Override
+ public boolean test() throws Exception {
+ return table.rowCount() == expectedNumberOfCommits;
+ }
+
+ @Override
+ public String getFailureMessage() {
+ return "CommitGraphTable did not get expected number of rows: "
+ + expectedNumberOfCommits;
+ }
+
+ });
+ List<Matcher<? super String>> matchers = new ArrayList<>();
+ matchers.add(equalTo("Initial commit"));
+ matchers.add(startsWith("Touched at"));
+ matchers.add(equalTo("A new file in a new folder"));
+
+ for (String msg : commitMsgs) {
+ matchers.add(equalTo(msg));
+ }
+
+ Assert.assertThat("Expected different commits",
+ getCommitMsgsFromUi(table),
+ is(arrayContainingInAnyOrder(matchers)));
+ }
+
@Test
- public void testShowAllBranches() throws Exception {
- try {
- toggleShowAllBranchesButton(true);
- final SWTBotTable table = getHistoryViewTable(PROJ1);
- int commits = getHistoryViewTable(PROJ1).rowCount();
- checkoutLine(table, 1);
-
- toggleShowAllBranchesButton(false);
- assertEquals("Wrong number of commits", commits - 1,
- getHistoryViewTable(PROJ1).rowCount());
- toggleShowAllBranchesButton(true);
- assertEquals("Wrong number of commits", commits,
- getHistoryViewTable(PROJ1).rowCount());
- } finally {
- toggleShowAllBranchesButton(false);
+ public void testSelectShownRefs() throws Exception {
+ Set<RefFilter> filters = refFilterHelper.getRefFilters();
+ filters.add(refFilterHelper.new RefFilter("refs/heads/test1"));
+ filters.add(refFilterHelper.new RefFilter("refs/heads/test?"));
+ filters.add(refFilterHelper.new RefFilter("refs/heads/test*"));
+ refFilterHelper.setRefFilters(filters);
+
+ Repository repo = myRepoViewUtil.lookupRepository(repoFile);
+
+ SWTBotTable table = getHistoryViewTable(PROJ1);
+ SWTBotView view = bot.viewById(IHistoryView.VIEW_ID);
+ SWTBotToolbarDropDownButton selectedRefs = (SWTBotToolbarDropDownButton) view
+ .toolbarButton(UIText.GitHistoryPage_showingHistoryOfHead);
+
+ try(Git git = Git.wrap(repo)) {
+ checkout(git, "testD", false);
}
+ assertCommitsAfterBase(table, "testDb");
+
+ uncheckRefFilter(selectedRefs, "HEAD");
+ assertNoCommit(table);
+
+ checkRefFilter(selectedRefs, "refs/**/[CURRENT-BRANCH]");
+ assertCommitsAfterBase(table, "testDa", "testDb");
+
+ uncheckRefFilter(selectedRefs, "refs/**/[CURRENT-BRANCH]");
+ assertNoCommit(table);
+
+ checkRefFilter(selectedRefs, "refs/heads/**");
+ assertCommitsAfterBase(table, "test1", "test2", "test12", "testDb");
+
+ uncheckRefFilter(selectedRefs, "refs/heads/**");
+ assertNoCommit(table);
+
+ checkRefFilter(selectedRefs, "refs/remotes/**");
+ assertCommitsAfterBase(table, "testDa", "testR");
+
+ uncheckRefFilter(selectedRefs, "refs/remotes/**");
+ assertNoCommit(table);
+
+ checkRefFilter(selectedRefs, "refs/tags/**");
+ assertCommitsAfterBase(table, "test1", "test1t");
+
+ uncheckRefFilter(selectedRefs, "refs/tags/**");
+ assertNoCommit(table);
+
+ checkRefFilter(selectedRefs, "refs/heads/test1");
+ assertCommitsAfterBase(table, "test1");
+
+ uncheckRefFilter(selectedRefs, "refs/heads/test1");
+ assertNoCommit(table);
+
+ checkRefFilter(selectedRefs, "refs/heads/test?");
+ assertCommitsAfterBase(table, "test1", "test2", "testDb");
+
+ uncheckRefFilter(selectedRefs, "refs/heads/test?");
+ assertNoCommit(table);
+
+ checkRefFilter(selectedRefs, "refs/heads/test*");
+ assertCommitsAfterBase(table, "test1", "test2", "test12", "testDb");
+
+ uncheckRefFilter(selectedRefs, "refs/heads/test*");
+ assertNoCommit(table);
+ }
+
+ @Test
+ public void testToggleShownRefs() throws Exception {
+ SWTBotTable table = getHistoryViewTable(PROJ1);
+ SWTBotView view = bot.viewById(IHistoryView.VIEW_ID);
+ SWTBotToolbarDropDownButton selectedRefs = (SWTBotToolbarDropDownButton) view
+ .toolbarButton(UIText.GitHistoryPage_showingHistoryOfHead);
+
+ checkRefFilter(selectedRefs, "refs/heads/**");
+ checkRefFilter(selectedRefs, "refs/remotes/**");
+ checkRefFilter(selectedRefs, "refs/tags/**");
+
+ assertCommitsAfterBase(table, "test1", "test2", "test12", "testDa",
+ "testDb", "test1t", "testR");
+
+ selectedRefs.click();
+ assertCommitsAfterBase(table);
+
+ uncheckRefFilter(selectedRefs, "HEAD");
+ assertNoCommit(table);
+
+ checkRefFilter(selectedRefs, "HEAD");
+ assertCommitsAfterBase(table);
+
+ selectedRefs.click();
+ assertCommitsAfterBase(table, "test1", "test2", "test12", "testDa",
+ "testDb", "test1t", "testR");
+
+ uncheckRefFilter(selectedRefs, "refs/heads/**");
+ uncheckRefFilter(selectedRefs, "refs/remotes/**");
+ uncheckRefFilter(selectedRefs, "refs/tags/**");
+ }
+
+ @Test
+ public void testOpenRefFilterDialogFromDropdown() throws Exception {
+ getHistoryViewTable(PROJ1); // Make sure the history view is visible
+ SWTBotView view = bot.viewById(IHistoryView.VIEW_ID);
+ SWTBotToolbarDropDownButton selectedRefs = (SWTBotToolbarDropDownButton) view
+ .toolbarButton(UIText.GitHistoryPage_showingHistoryOfHead);
+
+ selectedRefs.menuItem(UIText.GitHistoryPage_configureFilters).click();
+ // This will cause an exception if the dialog is not found
+ bot.shell(UIText.GitHistoryPage_filterRefDialog_dialogTitle).bot()
+ .button(IDialogConstants.OK_LABEL).click();
+ }
+
+ @Test
+ public void testOpenRefFilterDialogFromMenu() throws Exception {
+ getHistoryViewTable(PROJ1); // Make sure the history view is visible
+ SWTBotView view = bot.viewById(IHistoryView.VIEW_ID);
+
+ view.viewMenu(UIText.GitHistoryPage_configureFilters).click();
+ // This will cause an exception if the dialog is not found
+ bot.shell(UIText.GitHistoryPage_filterRefDialog_dialogTitle).bot()
+ .button(IDialogConstants.OK_LABEL).click();
}
@Test
@@ -523,13 +852,11 @@ public class HistoryViewTest extends GitRepositoriesViewTestBase {
TestUtil.joinJobs(JobFamilies.REBASE);
}
- private RevCommit[] checkoutLine(final SWTBotTable table, int line)
- throws InterruptedException {
+ private RevCommit[] getCommitInLine(SWTBotTable table, int line) {
table.getTableItem(line).select();
final RevCommit[] commit = new RevCommit[1];
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
-
@Override
public void run() {
TableItem tableItem = table.widget.getSelection()[0];
@@ -538,6 +865,14 @@ public class HistoryViewTest extends GitRepositoriesViewTestBase {
}
});
+ return commit;
+ }
+
+ private RevCommit[] checkoutLine(final SWTBotTable table, int line)
+ throws InterruptedException {
+ table.getTableItem(line).select();
+ final RevCommit[] commit = getCommitInLine(table, line);
+
ContextMenuHelper.clickContextMenuSync(table,
UIText.GitHistoryPage_CheckoutMenuLabel);
TestUtil.joinJobs(JobFamilies.CHECKOUT);
@@ -554,17 +889,6 @@ public class HistoryViewTest extends GitRepositoriesViewTestBase {
item.setText(item.getText()); // TODO: is there a better solution?
}
- private void toggleShowAllBranchesButton(boolean checked) throws Exception{
- getHistoryViewTable(PROJ1);
- SWTBotView view = bot
- .viewById(IHistoryView.VIEW_ID);
- SWTBotToolbarToggleButton showAllBranches = (SWTBotToolbarToggleButton) view
- .toolbarButton(UIText.GitHistoryPage_showAllBranches);
- boolean isChecked = showAllBranches.isChecked();
- if(isChecked && !checked || !isChecked && checked)
- showAllBranches.click();
- }
-
private static SWTBotTableItem getTableItemWithId(SWTBotTable table,
ObjectId wantedId) {
for (int i = 0; i < table.rowCount(); i++) {
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/RefFilterHelperTest.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/RefFilterHelperTest.java
new file mode 100644
index 000000000..fb99454f3
--- /dev/null
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/RefFilterHelperTest.java
@@ -0,0 +1,697 @@
+/*******************************************************************************
+ * Copyright (C) 2019, Tim Neumann <Tim.Neumann@advantest.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.egit.ui.test.history;
+
+import static org.eclipse.egit.ui.test.history.RefFilterUtil.newRefFilterMatcher;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.hamcrest.MockitoHamcrest.argThat;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.egit.core.RepositoryUtil;
+import org.eclipse.egit.ui.Activator;
+import org.eclipse.egit.ui.UIPreferences;
+import org.eclipse.egit.ui.common.LocalRepositoryTestCase;
+import org.eclipse.egit.ui.internal.history.RefFilterHelper;
+import org.eclipse.egit.ui.internal.history.RefFilterHelper.RefFilter;
+import org.eclipse.egit.ui.test.TestUtil;
+import org.eclipse.egit.ui.view.repositories.GitRepositoriesViewTestUtils;
+import org.eclipse.jface.preference.IPersistentPreferenceStore;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.TagCommand;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class RefFilterHelperTest extends LocalRepositoryTestCase {
+
+ private Repository repo;
+
+ private RefFilterHelper refFilterHelper;
+
+ private IPersistentPreferenceStore prefStore;
+
+ private GitRepositoriesViewTestUtils myRepoViewUtil;
+
+ @SuppressWarnings("boxing")
+ @Before
+ public void setupTests() throws Exception {
+ myRepoViewUtil = new GitRepositoriesViewTestUtils();
+ File repoFile = createProjectAndCommitToRepository();
+ createSimpleRemoteRepository(repoFile);
+
+ RepositoryUtil repositoryUtil = Activator.getDefault()
+ .getRepositoryUtil();
+ repositoryUtil.addConfiguredRepository(repoFile);
+
+ repo = myRepoViewUtil.lookupRepository(repoFile);
+
+ try (Git git = Git.wrap(repo)) {
+ TagCommand tag = git.tag();
+ tag.setName("TestTag");
+ PersonIdent committer = new PersonIdent(TestUtil.TESTCOMMITTER_NAME,
+ TestUtil.TESTCOMMITTER_EMAIL);
+ tag.setTagger(committer);
+ RevCommit headCommit = repo.parseCommit(
+ repo.exactRef(Constants.HEAD).getLeaf().getObjectId());
+ tag.setObjectId(headCommit);
+ tag.call();
+ }
+ prefStore = mock(IPersistentPreferenceStore.class);
+
+ when(prefStore.needsSaving()).thenReturn(true);
+ when(prefStore.getDefaultString(anyString())).thenReturn("");
+
+ refFilterHelper = new RefFilterHelper(repo, prefStore);
+ }
+
+ @After
+ public void teardown() {
+ myRepoViewUtil.dispose();
+ }
+
+ private String getRepoSpecificPrefKeyForConfiguredFilters() {
+ return Activator.getDefault().getRepositoryUtil()
+ .getRepositorySpecificPreferenceKey(this.repo,
+ UIPreferences.RESOURCEHISTORY_REF_FILTERS);
+ }
+
+ @Test
+ public void testConstructor() throws Exception {
+ verify(prefStore)
+ .getDefaultString(UIPreferences.RESOURCEHISTORY_REF_FILTERS);
+ verify(prefStore, times(2)).getDefaultString(
+ UIPreferences.RESOURCEHISTORY_SELECTED_REF_FILTERS);
+ verify(prefStore).getDefaultString(
+ UIPreferences.RESOURCEHISTORY_LAST_SELECTED_REF_FILTERS);
+ verify(prefStore).setDefault(
+ eq(getRepoSpecificPrefKeyForConfiguredFilters()), eq(""));
+ verify(prefStore).setDefault(
+ eq(getRepoSpecificPrefKeyForSelectedFilters()), eq(""));
+ verify(prefStore).setDefault(
+ eq(getRepoSpecificPrefKeyForLastSelectedFilters()), eq(""));
+ }
+
+ @Test
+ public void testGetConfiguredFilters() throws Exception {
+ when(prefStore
+ .getString(eq(getRepoSpecificPrefKeyForConfiguredFilters())))
+ .thenReturn("Mock:test:filter");
+ List<String> result = refFilterHelper.getConfiguredFilters();
+ assertThat("Expected different list of configured filters", result,
+ containsInAnyOrder("Mock", "test", "filter"));
+ }
+
+ @Test
+ public void testSetConfiguredFiltersNoSave() throws Exception {
+ List<String> filters = Arrays.asList("Mock", "test", "filter");
+
+ refFilterHelper.setConfiguredFilters(filters, false);
+ verify(prefStore).setValue(
+ eq(getRepoSpecificPrefKeyForConfiguredFilters()),
+ argThat(refFilterConfigStringOf(
+ containsInAnyOrder("Mock", "test", "filter"))));
+ verify(prefStore, never()).save();
+ }
+
+ @Test
+ public void testSetConfiguredFiltersWithSave() throws Exception {
+ List<String> filters = Arrays.asList("Mock", "test", "filter");
+
+ refFilterHelper.setConfiguredFilters(filters, true);
+ verify(prefStore).setValue(
+ eq(getRepoSpecificPrefKeyForConfiguredFilters()),
+ argThat(refFilterConfigStringOf(
+ containsInAnyOrder("Mock", "test", "filter"))));
+ verify(prefStore).save();
+ }
+
+ private String getRepoSpecificPrefKeyForSelectedFilters() {
+ return Activator.getDefault().getRepositoryUtil()
+ .getRepositorySpecificPreferenceKey(this.repo,
+ UIPreferences.RESOURCEHISTORY_SELECTED_REF_FILTERS);
+ }
+
+ @Test
+ public void testGetSelectedFilters() throws Exception {
+ when(prefStore
+ .getString(eq(getRepoSpecificPrefKeyForSelectedFilters())))
+ .thenReturn("Mock:test:filter");
+ List<String> result = refFilterHelper.getSelectedFilters();
+ assertThat("Expected different list of selected filters", result,
+ containsInAnyOrder("Mock", "test", "filter"));
+ }
+
+ @Test
+ public void testSetSelectedFiltersNoSave() throws Exception {
+ List<String> filters = Arrays.asList("Mock", "test", "filter");
+
+ refFilterHelper.setSelectedFilters(filters, false);
+ verify(prefStore).setValue(
+ eq(getRepoSpecificPrefKeyForSelectedFilters()),
+ argThat(refFilterConfigStringOf(
+ containsInAnyOrder("Mock", "test", "filter"))));
+ verify(prefStore, never()).save();
+ }
+
+ @Test
+ public void testSetSelectedFiltersWithSave() throws Exception {
+ List<String> filters = Arrays.asList("Mock", "test", "filter");
+
+ refFilterHelper.setSelectedFilters(filters, true);
+ verify(prefStore).setValue(
+ eq(getRepoSpecificPrefKeyForSelectedFilters()),
+ argThat(refFilterConfigStringOf(
+ containsInAnyOrder("Mock", "test", "filter"))));
+ verify(prefStore).save();
+ }
+
+ private String getRepoSpecificPrefKeyForLastSelectedFilters() {
+ return Activator.getDefault().getRepositoryUtil()
+ .getRepositorySpecificPreferenceKey(this.repo,
+ UIPreferences.RESOURCEHISTORY_LAST_SELECTED_REF_FILTERS);
+ }
+
+ @Test
+ public void testGetLastSelectedFilters() throws Exception {
+ when(prefStore
+ .getString(eq(getRepoSpecificPrefKeyForLastSelectedFilters())))
+ .thenReturn("Mock:test:filter");
+ List<String> result = refFilterHelper.getLastSelectedFilters();
+ assertThat("Expected different list of last selected filters", result,
+ containsInAnyOrder("Mock", "test", "filter"));
+ }
+
+ @Test
+ public void testSetLastSelectedFiltersNoSave() throws Exception {
+ List<String> filters = Arrays.asList("Mock", "test", "filter");
+
+ refFilterHelper.setLastSelectedFilters(filters, false);
+ verify(prefStore).setValue(
+ eq(getRepoSpecificPrefKeyForLastSelectedFilters()),
+ argThat(refFilterConfigStringOf(
+ containsInAnyOrder("Mock", "test", "filter"))));
+ verify(prefStore, never()).save();
+ }
+
+ @Test
+ public void testSetLastSelectedFiltersWithSave() throws Exception {
+ List<String> filters = Arrays.asList("Mock", "test", "filter");
+
+ refFilterHelper.setLastSelectedFilters(filters, true);
+ verify(prefStore).setValue(
+ eq(getRepoSpecificPrefKeyForLastSelectedFilters()),
+ argThat(refFilterConfigStringOf(
+ containsInAnyOrder("Mock", "test", "filter"))));
+ verify(prefStore).save();
+ }
+
+ private RefFilter newRefFilter(String filterString, boolean preConfigured,
+ boolean selected) {
+ return RefFilterUtil.newRefFilter(refFilterHelper, filterString,
+ preConfigured, selected);
+ }
+
+ @Test
+ public void testGetFilters() throws Exception {
+ when(prefStore
+ .getString(eq(getRepoSpecificPrefKeyForConfiguredFilters())))
+ .thenReturn("Mock:test:filter");
+ when(prefStore
+ .getString(eq(getRepoSpecificPrefKeyForSelectedFilters())))
+ .thenReturn("HEAD:test");
+ Set<RefFilter> result = refFilterHelper.getRefFilters();
+
+ List<Matcher<? super RefFilter>> expected = new ArrayList<>();
+ expected.add(newRefFilterMatcher("HEAD", true, true));
+ expected.add(
+ newRefFilterMatcher("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(newRefFilterMatcher("refs/heads/**", true, false));
+ expected.add(newRefFilterMatcher("refs/remotes/**", true, false));
+ expected.add(newRefFilterMatcher("refs/tags/**", true, false));
+ expected.add(newRefFilterMatcher("Mock", false, false));
+ expected.add(newRefFilterMatcher("test", false, true));
+ expected.add(newRefFilterMatcher("filter", false, false));
+
+ assertThat("Expected different filters", result,
+ containsInAnyOrder(expected));
+ }
+
+ @Test
+ public void testRestoreLastSelectionState() throws Exception {
+ when(prefStore
+ .getString(eq(getRepoSpecificPrefKeyForLastSelectedFilters())))
+ .thenReturn("HEAD:test");
+ Set<RefFilter> testSet = new HashSet<>();
+ testSet.add(newRefFilter("HEAD", true, false));
+ testSet.add(newRefFilter("refs/**/[CURRENT-BRANCH]", true,
+ false));
+ testSet.add(newRefFilter("refs/heads/**", true, true));
+ testSet.add(newRefFilter("refs/remotes/**", true, false));
+ testSet.add(newRefFilter("refs/tags/**", true, false));
+ testSet.add(newRefFilter("Mock", false, false));
+ testSet.add(newRefFilter("test", false, false));
+ testSet.add(newRefFilter("filter", false, true));
+
+ List<Matcher<? super RefFilter>> expected = new ArrayList<>();
+ expected.add(newRefFilterMatcher("HEAD", true, true));
+ expected.add(
+ newRefFilterMatcher("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(newRefFilterMatcher("refs/heads/**", true, false));
+ expected.add(newRefFilterMatcher("refs/remotes/**", true, false));
+ expected.add(newRefFilterMatcher("refs/tags/**", true, false));
+ expected.add(newRefFilterMatcher("Mock", false, false));
+ expected.add(newRefFilterMatcher("test", false, true));
+ expected.add(newRefFilterMatcher("filter", false, false));
+
+ refFilterHelper.restoreLastSelectionState(testSet);
+ assertThat("Expected different filters", testSet,
+ containsInAnyOrder(expected));
+ }
+
+ @Test
+ public void testSetFilters() throws Exception {
+ Set<RefFilter> testSet = new HashSet<>();
+ testSet.add(newRefFilter("HEAD", true, false));
+ testSet.add(newRefFilter("refs/**/[CURRENT-BRANCH]", true,
+ false));
+ testSet.add(newRefFilter("refs/heads/**", true, true));
+ testSet.add(newRefFilter("refs/remotes/**", true, false));
+ testSet.add(newRefFilter("refs/tags/**", true, false));
+ testSet.add(newRefFilter("Mock", false, false));
+ testSet.add(newRefFilter("test", false, false));
+ testSet.add(newRefFilter("filter", false, true));
+
+ refFilterHelper.setRefFilters(testSet);
+
+ verify(prefStore).setValue(
+ eq(getRepoSpecificPrefKeyForConfiguredFilters()),
+ argThat(refFilterConfigStringOf(
+ containsInAnyOrder("Mock", "test", "filter"))));
+
+ verify(prefStore).setValue(
+ eq(getRepoSpecificPrefKeyForSelectedFilters()),
+ argThat(refFilterConfigStringOf(
+ containsInAnyOrder("refs/heads/**", "filter"))));
+
+ verify(prefStore).save();
+ }
+
+ @Test
+ public void testSaveSelectionStateAsLastSelectionState() throws Exception {
+ Set<RefFilter> testSet = new HashSet<>();
+ testSet.add(newRefFilter("HEAD", true, false));
+ testSet.add(newRefFilter("refs/**/[CURRENT-BRANCH]", true,
+ false));
+ testSet.add(newRefFilter("refs/heads/**", true, true));
+ testSet.add(newRefFilter("refs/remotes/**", true, false));
+ testSet.add(newRefFilter("refs/tags/**", true, false));
+ testSet.add(newRefFilter("Mock", false, false));
+ testSet.add(newRefFilter("test", false, false));
+ testSet.add(newRefFilter("filter", false, true));
+
+ refFilterHelper.saveSelectionStateAsLastSelectionState(testSet);
+
+ verify(prefStore).setValue(
+ eq(getRepoSpecificPrefKeyForLastSelectedFilters()),
+ argThat(refFilterConfigStringOf(
+ containsInAnyOrder("refs/heads/**", "filter"))));
+
+ verify(prefStore).save();
+ }
+
+ @Test
+ public void testResetLastSelectionStateToDefault() throws Exception {
+ refFilterHelper.resetLastSelectionStateToDefault();
+
+ verify(prefStore).setToDefault(
+ eq(getRepoSpecificPrefKeyForLastSelectedFilters()));
+
+ verify(prefStore).save();
+ }
+
+ private Matcher<Ref> ref(Matcher<String> refName) {
+ return new TypeSafeMatcher<Ref>() {
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("A ref with the name ");
+ refName.describeTo(description);
+ }
+
+ @Override
+ protected boolean matchesSafely(Ref item) {
+ return refName.matches(item.getName());
+ }
+ };
+ }
+
+ private void checkMatchingRefsForSelectedRefFilters(
+ String selectedRefConfig, List<Matcher<? super Ref>> expected)
+ throws Exception {
+ when(prefStore
+ .getString(eq(getRepoSpecificPrefKeyForSelectedFilters())))
+ .thenReturn(selectedRefConfig);
+ when(prefStore
+ .getString(eq(getRepoSpecificPrefKeyForConfiguredFilters())))
+ .thenReturn("");
+ Set<Ref> result = refFilterHelper
+ .getMatchingRefsForSelectedRefFilters();
+
+ assertThat("Expected different refs for config: " + selectedRefConfig,
+ result, containsInAnyOrder(expected));
+ }
+
+ @Test
+ public void testGetMatchingRefsForSelectedRefFilters()
+ throws Exception {
+ checkMatchingRefsForSelectedRefFilters("HEAD",
+ Arrays.asList(ref(equalTo("HEAD"))));
+ checkMatchingRefsForSelectedRefFilters("refs/**/[CURRENT-BRANCH]",
+ Arrays.asList(ref(equalTo("refs/heads/master")),
+ ref(equalTo("refs/remotes/origin/master"))));
+ checkMatchingRefsForSelectedRefFilters("refs/heads/**",
+ Arrays.asList(ref(equalTo("refs/heads/master")),
+ ref(equalTo("refs/heads/stable"))));
+ checkMatchingRefsForSelectedRefFilters("refs/remotes/**",
+ Arrays.asList(ref(equalTo("refs/remotes/origin/master"))));
+ checkMatchingRefsForSelectedRefFilters("refs/tags/**",
+ Arrays.asList(ref(equalTo("refs/tags/TestTag"))));
+ }
+
+ @Test
+ public void testSelectOnlyHEAD() throws Exception {
+ Set<RefFilter> testSet = new HashSet<>();
+ testSet.add(newRefFilter("HEAD", true, false));
+ testSet.add(newRefFilter("refs/**/[CURRENT-BRANCH]", true,
+ false));
+ testSet.add(newRefFilter("refs/heads/**", true, true));
+ testSet.add(newRefFilter("refs/remotes/**", true, false));
+ testSet.add(newRefFilter("refs/tags/**", true, false));
+ testSet.add(newRefFilter("Mock", false, false));
+ testSet.add(newRefFilter("test", false, false));
+ testSet.add(newRefFilter("filter", false, true));
+
+ List<Matcher<? super RefFilter>> expected = new ArrayList<>();
+ expected.add(newRefFilterMatcher("HEAD", true, true));
+ expected.add(
+ newRefFilterMatcher("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(newRefFilterMatcher("refs/heads/**", true, false));
+ expected.add(newRefFilterMatcher("refs/remotes/**", true, false));
+ expected.add(newRefFilterMatcher("refs/tags/**", true, false));
+ expected.add(newRefFilterMatcher("Mock", false, false));
+ expected.add(newRefFilterMatcher("test", false, false));
+ expected.add(newRefFilterMatcher("filter", false, false));
+
+ refFilterHelper.selectOnlyHEAD(testSet);
+ assertThat("Expected different filters", testSet,
+ containsInAnyOrder(expected));
+ }
+
+ @Test
+ public void testIsOnlyHEADSelected() throws Exception {
+ Set<RefFilter> testSet1 = new HashSet<>();
+ testSet1.add(newRefFilter("HEAD", true, false));
+ testSet1.add(newRefFilter("refs/**/[CURRENT-BRANCH]",
+ true, false));
+ testSet1.add(newRefFilter("refs/heads/**", true, true));
+ testSet1.add(
+ newRefFilter("refs/remotes/**", true, false));
+ testSet1.add(newRefFilter("refs/tags/**", true, false));
+ testSet1.add(newRefFilter("Mock", false, false));
+ testSet1.add(newRefFilter("test", false, false));
+ testSet1.add(newRefFilter("filter", false, true));
+
+ assertFalse("Not only head selected",
+ refFilterHelper.isOnlyHEADSelected(testSet1));
+
+ Set<RefFilter> testSet2 = new HashSet<>();
+ testSet2.add(newRefFilter("HEAD", true, true));
+ testSet2.add(newRefFilter("refs/**/[CURRENT-BRANCH]",
+ true, false));
+ testSet2.add(newRefFilter("refs/heads/**", true, true));
+ testSet2.add(
+ newRefFilter("refs/remotes/**", true, false));
+ testSet2.add(newRefFilter("refs/tags/**", true, false));
+ testSet2.add(newRefFilter("Mock", false, false));
+ testSet2.add(newRefFilter("test", false, false));
+ testSet2.add(newRefFilter("filter", false, true));
+
+ assertFalse("Not only head selected",
+ refFilterHelper.isOnlyHEADSelected(testSet2));
+
+ Set<RefFilter> testSet3 = new HashSet<>();
+ testSet3.add(newRefFilter("HEAD", true, true));
+ testSet3.add(newRefFilter("refs/**/[CURRENT-BRANCH]",
+ true, false));
+ testSet3.add(newRefFilter("refs/heads/**", true, false));
+ testSet3.add(
+ newRefFilter("refs/remotes/**", true, false));
+ testSet3.add(newRefFilter("refs/tags/**", true, false));
+ testSet3.add(newRefFilter("Mock", false, false));
+ testSet3.add(newRefFilter("test", false, false));
+ testSet3.add(newRefFilter("filter", false, false));
+
+ assertTrue("Only head selected!",
+ refFilterHelper.isOnlyHEADSelected(testSet3));
+
+ }
+
+ @Test
+ public void testSelectOnlyCurrentBranch() throws Exception {
+ Set<RefFilter> testSet = new HashSet<>();
+ testSet.add(newRefFilter("HEAD", true, false));
+ testSet.add(newRefFilter("refs/**/[CURRENT-BRANCH]", true,
+ false));
+ testSet.add(newRefFilter("refs/heads/**", true, true));
+ testSet.add(newRefFilter("refs/remotes/**", true, false));
+ testSet.add(newRefFilter("refs/tags/**", true, false));
+ testSet.add(newRefFilter("Mock", false, false));
+ testSet.add(newRefFilter("test", false, false));
+ testSet.add(newRefFilter("filter", false, true));
+
+ List<Matcher<? super RefFilter>> expected = new ArrayList<>();
+ expected.add(newRefFilterMatcher("HEAD", true, false));
+ expected.add(
+ newRefFilterMatcher("refs/**/[CURRENT-BRANCH]", true, true));
+ expected.add(newRefFilterMatcher("refs/heads/**", true, false));
+ expected.add(newRefFilterMatcher("refs/remotes/**", true, false));
+ expected.add(newRefFilterMatcher("refs/tags/**", true, false));
+ expected.add(newRefFilterMatcher("Mock", false, false));
+ expected.add(newRefFilterMatcher("test", false, false));
+ expected.add(newRefFilterMatcher("filter", false, false));
+
+ refFilterHelper.selectOnlyCurrentBranch(testSet);
+ assertThat("Expected different filters", testSet,
+ containsInAnyOrder(expected));
+ }
+
+ @Test
+ public void testIsOnlyCurrentBranchSelected() throws Exception {
+ Set<RefFilter> testSet1 = new HashSet<>();
+ testSet1.add(newRefFilter("HEAD", true, false));
+ testSet1.add(newRefFilter("refs/**/[CURRENT-BRANCH]",
+ true, false));
+ testSet1.add(newRefFilter("refs/heads/**", true, true));
+ testSet1.add(
+ newRefFilter("refs/remotes/**", true, false));
+ testSet1.add(newRefFilter("refs/tags/**", true, false));
+ testSet1.add(newRefFilter("Mock", false, false));
+ testSet1.add(newRefFilter("test", false, false));
+ testSet1.add(newRefFilter("filter", false, true));
+
+ assertFalse("Not only current branch selected",
+ refFilterHelper.isOnlyCurrentBranchSelected(testSet1));
+
+ Set<RefFilter> testSet2 = new HashSet<>();
+ testSet2.add(newRefFilter("HEAD", true, false));
+ testSet2.add(newRefFilter("refs/**/[CURRENT-BRANCH]",
+ true, true));
+ testSet2.add(newRefFilter("refs/heads/**", true, true));
+ testSet2.add(
+ newRefFilter("refs/remotes/**", true, false));
+ testSet2.add(newRefFilter("refs/tags/**", true, false));
+ testSet2.add(newRefFilter("Mock", false, false));
+ testSet2.add(newRefFilter("test", false, false));
+ testSet2.add(newRefFilter("filter", false, true));
+
+ assertFalse("Not only current branch selected",
+ refFilterHelper.isOnlyCurrentBranchSelected(testSet2));
+
+ Set<RefFilter> testSet3 = new HashSet<>();
+ testSet3.add(newRefFilter("HEAD", true, false));
+ testSet3.add(newRefFilter("refs/**/[CURRENT-BRANCH]",
+ true, true));
+ testSet3.add(newRefFilter("refs/heads/**", true, false));
+ testSet3.add(
+ newRefFilter("refs/remotes/**", true, false));
+ testSet3.add(newRefFilter("refs/tags/**", true, false));
+ testSet3.add(newRefFilter("Mock", false, false));
+ testSet3.add(newRefFilter("test", false, false));
+ testSet3.add(newRefFilter("filter", false, false));
+
+ assertTrue("Only current branch selected!",
+ refFilterHelper.isOnlyCurrentBranchSelected(testSet3));
+
+ }
+
+ @Test
+ public void testSelectExactlyAllBranchesAndTags() throws Exception {
+ Set<RefFilter> testSet = new HashSet<>();
+ testSet.add(newRefFilter("HEAD", true, false));
+ testSet.add(newRefFilter("refs/**/[CURRENT-BRANCH]", true,
+ false));
+ testSet.add(newRefFilter("refs/heads/**", true, true));
+ testSet.add(newRefFilter("refs/remotes/**", true, false));
+ testSet.add(newRefFilter("refs/tags/**", true, false));
+ testSet.add(newRefFilter("Mock", false, false));
+ testSet.add(newRefFilter("test", false, false));
+ testSet.add(newRefFilter("filter", false, true));
+
+ List<Matcher<? super RefFilter>> expected = new ArrayList<>();
+ expected.add(newRefFilterMatcher("HEAD", true, true));
+ expected.add(
+ newRefFilterMatcher("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(newRefFilterMatcher("refs/heads/**", true, true));
+ expected.add(newRefFilterMatcher("refs/remotes/**", true, true));
+ expected.add(newRefFilterMatcher("refs/tags/**", true, true));
+ expected.add(newRefFilterMatcher("Mock", false, false));
+ expected.add(newRefFilterMatcher("test", false, false));
+ expected.add(newRefFilterMatcher("filter", false, false));
+
+ refFilterHelper.selectExactlyAllBranchesAndTags(testSet);
+ assertThat("Expected different filters", testSet,
+ containsInAnyOrder(expected));
+ }
+
+ @Test
+ public void testIsExactlyAllBranchesAndTagsSelected() throws Exception {
+ Set<RefFilter> testSet1 = new HashSet<>();
+ testSet1.add(newRefFilter("HEAD", true, false));
+ testSet1.add(newRefFilter("refs/**/[CURRENT-BRANCH]",
+ true, false));
+ testSet1.add(newRefFilter("refs/heads/**", true, true));
+ testSet1.add(
+ newRefFilter("refs/remotes/**", true, false));
+ testSet1.add(newRefFilter("refs/tags/**", true, false));
+ testSet1.add(newRefFilter("Mock", false, false));
+ testSet1.add(newRefFilter("test", false, false));
+ testSet1.add(newRefFilter("filter", false, true));
+
+ assertFalse("Not only current branch selected",
+ refFilterHelper.isExactlyAllBranchesAndTagsSelected(testSet1));
+
+ Set<RefFilter> testSet2 = new HashSet<>();
+ testSet2.add(newRefFilter("HEAD", true, true));
+ testSet2.add(newRefFilter("refs/**/[CURRENT-BRANCH]",
+ true, false));
+ testSet2.add(newRefFilter("refs/heads/**", true, true));
+ testSet2.add(newRefFilter("refs/remotes/**", true, true));
+ testSet2.add(newRefFilter("refs/tags/**", true, true));
+ testSet2.add(newRefFilter("Mock", false, false));
+ testSet2.add(newRefFilter("test", false, false));
+ testSet2.add(newRefFilter("filter", false, true));
+
+ assertFalse("Not only current branch selected",
+ refFilterHelper.isExactlyAllBranchesAndTagsSelected(testSet2));
+
+ Set<RefFilter> testSet3 = new HashSet<>();
+ testSet3.add(newRefFilter("HEAD", true, true));
+ testSet3.add(newRefFilter("refs/**/[CURRENT-BRANCH]",
+ true, false));
+ testSet3.add(newRefFilter("refs/heads/**", true, true));
+ testSet3.add(newRefFilter("refs/remotes/**", true, true));
+ testSet3.add(newRefFilter("refs/tags/**", true, true));
+ testSet3.add(newRefFilter("Mock", false, false));
+ testSet3.add(newRefFilter("test", false, false));
+ testSet3.add(newRefFilter("filter", false, false));
+
+ assertTrue("Only current branch selected!",
+ refFilterHelper.isExactlyAllBranchesAndTagsSelected(testSet3));
+
+ }
+
+ @Test
+ public void testGetDefaults() throws Exception {
+ when(prefStore.getDefaultString(
+ eq(UIPreferences.RESOURCEHISTORY_REF_FILTERS)))
+ .thenReturn("Mock:test:filter");
+ when(prefStore.getDefaultString(
+ eq(UIPreferences.RESOURCEHISTORY_SELECTED_REF_FILTERS)))
+ .thenReturn("HEAD:test");
+ Set<RefFilter> result = refFilterHelper.getDefaults();
+
+ List<Matcher<? super RefFilter>> expected = new ArrayList<>();
+ expected.add(newRefFilterMatcher("HEAD", true, true));
+ expected.add(
+ newRefFilterMatcher("refs/**/[CURRENT-BRANCH]", true, false));
+ expected.add(newRefFilterMatcher("refs/heads/**", true, false));
+ expected.add(newRefFilterMatcher("refs/remotes/**", true, false));
+ expected.add(newRefFilterMatcher("refs/tags/**", true, false));
+ expected.add(newRefFilterMatcher("Mock", false, false));
+ expected.add(newRefFilterMatcher("test", false, true));
+ expected.add(newRefFilterMatcher("filter", false, false));
+
+ assertThat("Expected different filters", result,
+ containsInAnyOrder(expected));
+ }
+
+ private Matcher<String> refFilterConfigStringOf(
+ Matcher<Iterable<? extends String>> items) {
+ return new RefFilterConfigStringMatcher(items);
+ }
+
+ private static class RefFilterConfigStringMatcher
+ extends TypeSafeMatcher<String> {
+
+ private final Matcher<Iterable<? extends String>> itemsMatcher;
+
+ public RefFilterConfigStringMatcher(
+ Matcher<Iterable<? extends String>> itemsMatcher) {
+ this.itemsMatcher = itemsMatcher;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("A ref filter config string containing ");
+ itemsMatcher.describeTo(description);
+ }
+
+ @Override
+ protected boolean matchesSafely(String item) {
+ return itemsMatcher.matches(Arrays.asList(item.split(":")));
+ }
+
+ }
+}
diff --git a/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/RefFilterUtil.java b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/RefFilterUtil.java
new file mode 100644
index 000000000..9e6c76b38
--- /dev/null
+++ b/org.eclipse.egit.ui.test/src/org/eclipse/egit/ui/test/history/RefFilterUtil.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (C) 2019, Tim Neumann <Tim.Neumann@advantest.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.egit.ui.test.history;
+
+import static org.mockito.Mockito.when;
+
+import java.util.Objects;
+
+import org.eclipse.egit.ui.internal.history.RefFilterHelper;
+import org.eclipse.egit.ui.internal.history.RefFilterHelper.RefFilter;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.mockito.Mockito;
+
+public class RefFilterUtil {
+ private RefFilterUtil() {
+ // Forbid instantiation
+ }
+
+ public static Matcher<RefFilter> newRefFilterMatcher(String filterString,
+ boolean preConfigured,
+ boolean selected) {
+ return new TypeSafeMatcher<RefFilterHelper.RefFilter>() {
+ @Override
+ public void describeTo(Description description) {
+ description.appendText("a ref filter with ");
+ description.appendValue(filterString);
+ description.appendText(" which is ");
+ if (!preConfigured) {
+ description.appendText("_not_ ");
+ }
+ description.appendText("preconfigured and ");
+ if (!selected) {
+ description.appendText("_not_ ");
+ }
+ description.appendText("selected");
+ }
+
+ @Override
+ protected boolean matchesSafely(RefFilter item) {
+ if (item.isPreconfigured() != preConfigured) {
+ return false;
+ }
+
+ if (item.isSelected() != selected) {
+ return false;
+ }
+
+ return Objects.equals(filterString, item.getFilterString());
+ }
+ };
+ }
+
+ @SuppressWarnings("boxing")
+ public static RefFilter newRefFilter(RefFilterHelper helper,
+ String filterString, boolean preConfigured,
+ boolean selected) {
+ RefFilter mock = Mockito.mock(RefFilter.class);
+ when(mock.getFilterString()).thenReturn(filterString);
+ when(mock.isPreconfigured()).thenReturn(preConfigured);
+ when(mock.isSelected()).thenReturn(selected);
+ return helper.new RefFilter(mock);
+ }
+
+}
diff --git a/org.eclipse.egit.ui/META-INF/MANIFEST.MF b/org.eclipse.egit.ui/META-INF/MANIFEST.MF
index 0deaa40bb..e263e4ce6 100644
--- a/org.eclipse.egit.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.egit.ui/META-INF/MANIFEST.MF
@@ -31,7 +31,8 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.12.0,4.0.0)",
org.eclipse.ui.views;bundle-version="[3.8.100,4.0.0)",
org.eclipse.osgi.services;bundle-version="[3.5.100,4.0.0)",
org.eclipse.e4.core.contexts;bundle-version="[1.5.1,2.0.0)",
- org.eclipse.e4.ui.workbench;bundle-version="[1.4.0,2.0.0)"
+ org.eclipse.e4.ui.workbench;bundle-version="[1.4.0,2.0.0)",
+ org.apache.ant;bundle-version="[1.10.5,2.0.0)"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Service-Component: OSGI-INF/org.eclipse.egit.ui.internal.clone.GitCloneDropAdapter.xml
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java
index 79208d709..fa891ffb9 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java
@@ -59,7 +59,14 @@ public class PluginPreferenceInitializer extends AbstractPreferenceInitializer {
store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_REV_DETAIL, true);
store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_REV_COMMENT, true);
store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_TOOLTIPS, false);
- store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_ALL_BRANCHES, false);
+ store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_ALL_BRANCHES,
+ false);
+ store.setDefault(UIPreferences.RESOURCEHISTORY_SELECTED_REF_FILTERS,
+ "HEAD"); //$NON-NLS-1$
+ store.setDefault(
+ UIPreferences.RESOURCEHISTORY_LAST_SELECTED_REF_FILTERS,
+ "refs/tags/**:HEAD:refs/heads/**:refs/remotes/**"); //$NON-NLS-1$
+ store.setDefault(UIPreferences.RESOURCEHISTORY_REF_FILTERS, ""); //$NON-NLS-1$
store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_FIRST_PARENT_ONLY_DEFAULT,
false);
store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_ADDITIONAL_REFS,
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java
index 867c8f4f3..ebf186c11 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java
@@ -50,6 +50,12 @@ public class UIPreferences {
/** */
public final static String RESOURCEHISTORY_SHOW_ALL_BRANCHES = "resourcehistory_show_all_branches"; //$NON-NLS-1$
/** */
+ public final static String RESOURCEHISTORY_REF_FILTERS = "resourcehistory_ref_filters"; //$NON-NLS-1$
+ /** */
+ public final static String RESOURCEHISTORY_SELECTED_REF_FILTERS = "resourcehistory_selected_ref_filters"; //$NON-NLS-1$
+ /** */
+ public final static String RESOURCEHISTORY_LAST_SELECTED_REF_FILTERS = "resourcehistory_last_selected_ref_filters"; //$NON-NLS-1$
+ /** */
public final static String RESOURCEHISTORY_SHOW_FIRST_PARENT_ONLY_DEFAULT = "resourcehistory_show_first_parent_only"; //$NON-NLS-1$
/** */
public final static String RESOURCEHISTORY_SHOW_ADDITIONAL_REFS = "resourcehistory_show_additionalrefs"; //$NON-NLS-1$
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 9cb50dd5c..0dd5e603a 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
@@ -472,7 +472,10 @@ public class UIText extends NLS {
public static String GitHistoryPage_compareMode;
/** */
- public static String GitHistoryPage_showAllBranches;
+ public static String GitHistoryPage_showingHistoryOfHead;
+
+ /** */
+ public static String GitHistoryPage_showingHistoryOfConfiguredFilters;
/** */
public static String GitHistoryPage_showFirstParentOnly;
@@ -625,7 +628,7 @@ public class UIText extends NLS {
public static String GitHistoryPage_ShowAdditionalRefsMenuLabel;
/** */
- public static String GitHistoryPage_ShowAllBranchesMenuLabel;
+ public static String GitHistoryPage_SelectShownRefsMenuLabel;
/** */
public static String GitHistoryPage_ShowFirstParentOnlyMenuLabel;
@@ -667,6 +670,48 @@ public class UIText extends NLS {
public static String GitHistoryPage_toggleEmailAddresses;
/** */
+ public static String GitHistoryPage_configureFilters;
+
+ /** */
+ public static String GitHistoryPage_filterRefDialog_dialogTitle;
+
+ /** */
+ public static String GitHistoryPage_filterRefDialog_filtersCompositLabel;
+
+ /** */
+ public static String GitHistoryPage_filterRefDialog_patternExplanation;
+
+ /** */
+ public static String GitHistoryPage_filterRefDialog_button_add;
+
+ /** */
+ public static String GitHistoryPage_filterRefDialog_button_remove;
+
+ /** */
+ public static String GitHistoryPage_filterRefDialog_button_edit;
+
+ /** */
+ public static String GitHistoryPage_filterRefDialog_button_addRef;
+
+ /** */
+ public static String GitHistoryPage_filterRefDialog_button_headOnly;
+
+ /** */
+ public static String GitHistoryPage_filterRefDialog_button_currentBranchOnly;
+
+ /** */
+ public static String GitHistoryPage_filterRefDialog_button_allBranchesAndTags;
+
+ /** */
+ public static String GitHistoryPage_filterRefDialog_preconfiguredText;
+
+ /** */
+ public static String GitHistoryPage_filterRefDialog_selectRefDialog_dialogTitle;
+
+ /** */
+ public static String GitHistoryPage_filterRefDialog_selectRefDialog_dialogMessage;
+
+ /** */
public static String GitLightweightDecorator_name;
/** */
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ReplaceWithCommitActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ReplaceWithCommitActionHandler.java
index 617cd1f68..35ddd6d24 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ReplaceWithCommitActionHandler.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ReplaceWithCommitActionHandler.java
@@ -20,6 +20,7 @@ import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.egit.ui.internal.history.CommitSelectionDialog;
import org.eclipse.jface.window.Window;
+import org.eclipse.jgit.lib.Repository;
/**
* Replace with commit action handler
@@ -28,9 +29,13 @@ public class ReplaceWithCommitActionHandler extends DiscardChangesActionHandler
@Override
protected String gatherRevision(ExecutionEvent event) throws ExecutionException {
+ final Repository repo = getRepository(true, event);
+ if (repo == null) {
+ return null;
+ }
IResource[] resources = gatherResourceToOperateOn(event);
CommitSelectionDialog dlg = new CommitSelectionDialog(getShell(event),
- getRepository(true, event), resources);
+ repo, resources);
if (dlg.open() == Window.OK)
return dlg.getCommitId().name();
else
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitSelectionDialog.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitSelectionDialog.java
index b74e689ba..e57d4005f 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitSelectionDialog.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitSelectionDialog.java
@@ -15,12 +15,11 @@ import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.egit.core.project.RepositoryMapping;
-import org.eclipse.egit.ui.Activator;
-import org.eclipse.egit.ui.UIPreferences;
import org.eclipse.egit.ui.UIUtils;
import org.eclipse.egit.ui.internal.GitLabels;
import org.eclipse.egit.ui.internal.UIText;
@@ -37,10 +36,10 @@ import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.diff.DiffConfig;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
@@ -65,6 +64,7 @@ import org.eclipse.ui.PlatformUI;
public class CommitSelectionDialog extends TitleAreaDialog {
private static final int BATCH_SIZE = 256;
+ @NonNull
private final Repository repository;
private final IResource[] filterResources;
@@ -81,7 +81,8 @@ public class CommitSelectionDialog extends TitleAreaDialog {
* @param parentShell
* @param repository
*/
- public CommitSelectionDialog(Shell parentShell, Repository repository) {
+ public CommitSelectionDialog(Shell parentShell,
+ @NonNull Repository repository) {
this(parentShell, repository, null);
}
@@ -91,10 +92,15 @@ public class CommitSelectionDialog extends TitleAreaDialog {
*
* @param parentShell
* @param repository
+ * the repository; must not be null
* @param filterResources
* the resources to use to filter commits, null for no filter
+ *
+ * @throws IllegalArgumentException
+ * if the given repository is null
*/
- public CommitSelectionDialog(Shell parentShell, Repository repository,
+ public CommitSelectionDialog(Shell parentShell,
+ @NonNull Repository repository,
IResource[] filterResources) {
super(parentShell);
setShellStyle(getShellStyle() | SWT.SHELL_TRIM);
@@ -170,19 +176,12 @@ public class CommitSelectionDialog extends TitleAreaDialog {
.newFlag("highlight"); //$NON-NLS-1$
allCommits.source(currentWalk);
- if (Activator.getDefault().getPreferenceStore()
- .getBoolean(
- UIPreferences.RESOURCEHISTORY_SHOW_ALL_BRANCHES)) {
- markStartAllRefs(currentWalk,
- Constants.R_HEADS);
- markStartAllRefs(currentWalk,
- Constants.R_REMOTES);
- } else {
- currentWalk
- .markStart(currentWalk.parseCommit(
- repository.resolve(
- Constants.HEAD)));
- }
+ RefFilterHelper helper = new RefFilterHelper(
+ repository);
+
+ markStartAllRefs(currentWalk, helper
+ .getMatchingRefsForSelectedRefFilters());
+
for (;;) {
final int oldsz = allCommits.size();
allCommits.fillTo(oldsz + BATCH_SIZE - 1);
@@ -231,13 +230,12 @@ public class CommitSelectionDialog extends TitleAreaDialog {
.toArray(new SWTCommit[0]), null, true);
}
- private void markStartAllRefs(RevWalk currentWalk, String prefix)
+ private void markStartAllRefs(RevWalk currentWalk, Set<Ref> refs)
throws IOException, MissingObjectException,
IncorrectObjectTypeException {
- for (Ref ref : repository.getRefDatabase().getRefsByPrefix(prefix)) {
- if (ref.isSymbolic())
- continue;
- currentWalk.markStart(currentWalk.parseCommit(ref.getObjectId()));
+ for (Ref ref : refs) {
+ currentWalk.markStart(
+ currentWalk.parseCommit(ref.getLeaf().getObjectId()));
}
}
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 24b11205a..91c27e732 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
@@ -10,6 +10,7 @@
* Copyright (C) 2015, IBM Corporation (Dani Megert <daniel_megert@ch.ibm.com>)
* Copyright (C) 2015-2019 Thomas Wolf <thomas.wolf@paranor.ch>
* Copyright (C) 2015-2017, Stefan Dirix <sdirix@eclipsesource.com>
+ * Copyright (C) 2019, Tim Neumann <Tim.Neumann@advantest.com>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -27,6 +28,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
@@ -36,6 +38,7 @@ import java.util.Set;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.Adapters;
+import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
@@ -65,6 +68,7 @@ import org.eclipse.egit.ui.internal.components.DropDownMenuAction;
import org.eclipse.egit.ui.internal.components.RepositoryMenuUtil.RepositoryToolbarAction;
import org.eclipse.egit.ui.internal.fetch.FetchHeadChangedEvent;
import org.eclipse.egit.ui.internal.history.FindToolbar.StatusListener;
+import org.eclipse.egit.ui.internal.history.RefFilterHelper.RefFilter;
import org.eclipse.egit.ui.internal.repository.tree.AdditionalRefNode;
import org.eclipse.egit.ui.internal.repository.tree.FileNode;
import org.eclipse.egit.ui.internal.repository.tree.FolderNode;
@@ -108,6 +112,7 @@ import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.window.Window;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.diff.DiffConfig;
import org.eclipse.jgit.diff.DiffEntry;
@@ -423,7 +428,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
IWorkbenchAction compareModeAction;
- IWorkbenchAction showAllBranchesAction;
+ IWorkbenchAction selectShownRefsAction;
IWorkbenchAction showFirstParentOnlyAction;
@@ -445,6 +450,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
RepositoryToolbarAction switchRepositoryAction;
+ IWorkbenchAction configureFiltersAction;
+
private GitHistoryPage historyPage;
GitHistoryPageActions(GitHistoryPage historyPage) {
@@ -465,7 +472,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
createFilterActions();
createCompareModeAction();
createReuseCompareEditorAction();
- createShowAllBranchesAction();
+ createSelectShownRefsAction();
createShowFirstParentOnlyAction();
createShowAdditionalRefsAction();
createShowCommentAction();
@@ -478,6 +485,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
createWrapCommentAction();
createFillCommentAction();
createFollowRenamesAction();
+ createConfigureFiltersAction();
wrapCommentAction.setEnabled(showCommentAction.isChecked());
fillCommentAction.setEnabled(showCommentAction.isChecked());
@@ -614,20 +622,171 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
actionsToDispose.add(reuseCompareEditorAction);
}
- private void createShowAllBranchesAction() {
- showAllBranchesAction = new BooleanPrefAction(
- UIPreferences.RESOURCEHISTORY_SHOW_ALL_BRANCHES,
- UIText.GitHistoryPage_ShowAllBranchesMenuLabel) {
+ private class SelectShownRefsAction extends DropDownMenuAction
+ implements IPropertyChangeListener {
+
+ private boolean headMode;
+
+ private RefFilterHelper helper;
+
+ public SelectShownRefsAction() {
+ super(UIText.GitHistoryPage_SelectShownRefsMenuLabel);
+ historyPage.addPropertyChangeListener(this);
+
+ Repository currentRepo = historyPage.getCurrentRepo();
+
+ if (currentRepo != null) {
+ helper = new RefFilterHelper(currentRepo);
+ }
+
+ setHeadModeFromHelperState();
+ updateUiForMode();
+ }
+
+ private void setHeadModeFromHelperState() {
+ if (helper == null) {
+ return;
+ }
+ Set<RefFilter> filters = helper.getRefFilters();
+
+ headMode = helper.isOnlyHEADSelected(filters);
+ }
+
+ private void updateUiForMode() {
+ if (headMode) {
+ this.setImageDescriptor(UIIcons.BRANCH);
+ this.setToolTipText(
+ UIText.GitHistoryPage_showingHistoryOfHead);
+ } else {
+ this.setImageDescriptor(UIIcons.BRANCHES);
+ this.setToolTipText(
+ UIText.GitHistoryPage_showingHistoryOfConfiguredFilters);
+ }
+ }
+
+ @Override
+ public void dispose() {
+ historyPage.removePropertyChangeListener(this);
+ super.dispose();
+ }
+
+ @Override
+ protected Collection<IAction> getActions() {
+ if (historyPage.getCurrentRepo() == null) {
+ return new ArrayList<>();
+ }
+ List<IAction> actions = new ArrayList<>();
+ actions.add(configureFiltersAction);
+ Set<RefFilter> filters = helper.getRefFilters();
+ List<RefFilter> sortedFilters = new ArrayList<>(
+ filters);
+ sortedFilters.sort(new Comparator<RefFilter>() {
+
+ private int category(RefFilter filter) {
+ if (filter.isPreconfigured()) {
+ return 100;
+ }
+ return 1000;
+ }
+
+ @Override
+ public int compare(RefFilter o1, RefFilter o2) {
+ int cat1 = category(o1);
+ int cat2 = category(o2);
+
+ if (cat1 != cat2) {
+ return cat1 - cat2;
+ }
+
+ String name1 = o1.getFilterString();
+ String name2 = o2.getFilterString();
+
+ return name1.compareTo(name2);
+ }
+ });
+
+ for (RefFilter filter : sortedFilters) {
+ Action action = new ShownRefAction(filter, () -> {
+ helper.setRefFilters(filters);
+ setHeadModeFromHelperState();
+ updateUiForMode();
+ historyPage.refresh();
+ });
+ actions.add(action);
+ }
+ return actions;
+ }
+
+ @Override
+ public void run() {
+ if (historyPage.getCurrentRepo() == null)
+ return;
+ Set<RefFilter> filters = helper.getRefFilters();
+
+ if (helper.isOnlyHEADSelected(filters)) {
+ helper.restoreLastSelectionState(filters);
+ headMode = false;
+ } else {
+ helper.saveSelectionStateAsLastSelectionState(filters);
+ helper.selectOnlyHEAD(filters);
+ headMode = true;
+ }
+ updateUiForMode();
+ helper.setRefFilters(filters);
+ historyPage.refresh(historyPage.selectedCommit());
+ }
+
+ private class ShownRefAction extends Action {
+
+ private RefFilter filter;
+
+ private Runnable postChangeAction;
+
+ public ShownRefAction(RefFilter filter,
+ Runnable postChangeAction) {
+ super(filter.getFilterString(), IAction.AS_CHECK_BOX);
+ if (filter.isPreconfigured()) {
+ this.setText(filter.getFilterString()
+ + UIText.GitHistoryPage_filterRefDialog_preconfiguredText);
+ }
+ this.filter = filter;
+ this.postChangeAction = postChangeAction;
+ }
@Override
- void apply(boolean value) {
- historyPage.refresh(historyPage.selectedCommit());
+ public boolean isChecked() {
+ return filter.isSelected();
}
- };
- showAllBranchesAction.setImageDescriptor(UIIcons.BRANCH);
- showAllBranchesAction
- .setToolTipText(UIText.GitHistoryPage_showAllBranches);
- actionsToDispose.add(showAllBranchesAction);
+
+ @Override
+ public void run() {
+ if (historyPage.getCurrentRepo() == null)
+ return;
+ filter.setSelected(!filter.isSelected());
+ postChangeAction.run();
+ }
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent event) {
+ if (P_REPOSITORY.equals(event.getProperty())) {
+ Repository currentRepo = historyPage.getCurrentRepo();
+ if (currentRepo == null) {
+ this.setEnabled(false);
+ helper = null;
+ } else {
+ this.setEnabled(true);
+ helper = new RefFilterHelper(currentRepo);
+ setHeadModeFromHelperState();
+ updateUiForMode();
+ }
+ }
+ }
+ }
+
+ private void createSelectShownRefsAction() {
+ selectShownRefsAction = new SelectShownRefsAction();
+ actionsToDispose.add(selectShownRefsAction);
}
private class ShowFirstParentOnlyPrefAction extends Action
@@ -647,7 +806,9 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
final String prefKey = UIPreferences.RESOURCEHISTORY_SHOW_FIRST_PARENT_ONLY_DEFAULT;
Repository repo = historyPage.getCurrentRepo();
if (repo != null) {
- String repoSpecificKey = getRepoSpecificKey(repo, prefKey);
+ String repoSpecificKey = Activator.getDefault()
+ .getRepositoryUtil()
+ .getRepositorySpecificPreferenceKey(repo, prefKey);
boolean newBoolean = isChecked();
if (newBoolean == historyPage.store.getBoolean(prefKey)) {
historyPage.store.setToDefault(repoSpecificKey);
@@ -701,7 +862,9 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
return;
}
- String repoSpecificKey = getRepoSpecificKey(repo, prefKey);
+ String repoSpecificKey = Activator.getDefault()
+ .getRepositoryUtil()
+ .getRepositorySpecificPreferenceKey(repo, prefKey);
if (prefKey.equals(event.getProperty())) {
// global first parent preference changed, if this repo does
@@ -875,6 +1038,65 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
fillCommentAction.apply(fillCommentAction.isChecked());
actionsToDispose.add(fillCommentAction);
}
+
+ private class ConfigureFilterAction extends Action
+ implements IWorkbenchAction, IPropertyChangeListener {
+
+ private GitHistoryRefFilterConfigurationDialog dialog;
+
+ private RefFilterHelper helper;
+
+ ConfigureFilterAction() {
+ super(UIText.GitHistoryPage_configureFilters);
+ historyPage.addPropertyChangeListener(this);
+ Repository currentRepo = historyPage.getCurrentRepo();
+ if (currentRepo != null) {
+ helper = new RefFilterHelper(currentRepo);
+ }
+ }
+
+ @Override
+ public void run() {
+ if (historyPage.getCurrentRepo() == null) {
+ return;
+ }
+
+ dialog = new GitHistoryRefFilterConfigurationDialog(
+ historyPage.getSite().getWorkbenchWindow().getShell(),
+ historyPage.getCurrentRepo(), helper);
+ if (dialog.open() == Window.OK) {
+ historyPage.refresh(historyPage.selectedCommit());
+ }
+ }
+
+ @Override
+ public void dispose() {
+ historyPage.removePropertyChangeListener(this);
+ if (dialog != null) {
+ dialog.close();
+ }
+ }
+
+ @Override
+ public void propertyChange(PropertyChangeEvent event) {
+ if (P_REPOSITORY.equals(event.getProperty())) {
+ Repository currentRepo = historyPage.getCurrentRepo();
+ if (currentRepo == null) {
+ this.setEnabled(false);
+ helper = null;
+ } else {
+ this.setEnabled(true);
+ helper = new RefFilterHelper(currentRepo);
+ }
+ }
+
+ }
+ }
+
+ private void createConfigureFiltersAction() {
+ configureFiltersAction = new ConfigureFilterAction();
+ actionsToDispose.add(configureFiltersAction);
+ }
}
/**
@@ -1025,7 +1247,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
/** ObjectId of the ref or commit of the last input, if any. */
private ObjectId selectedObj;
- private boolean currentShowAllBranches;
+ private String currentRefFilters;
private boolean currentShowFirstParentOnly;
@@ -1061,8 +1283,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
if (!RepositoryUtil.PREFS_DIRECTORIES_REL.equals(event.getKey())) {
return;
}
- if (currentRepo == null || !Activator.getDefault().getRepositoryUtil()
- .contains(currentRepo)) {
+ if (getCurrentRepo() == null || !Activator.getDefault()
+ .getRepositoryUtil().contains(getCurrentRepo())) {
Control control = historyControl;
if (!control.isDisposed()) {
control.getDisplay().asyncExec(() -> {
@@ -1674,7 +1896,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
mgr.add(actions.switchRepositoryAction);
mgr.add(actions.filterAction);
mgr.add(actions.compareModeAction);
- mgr.add(actions.showAllBranchesAction);
+ mgr.add(actions.selectShownRefsAction);
mgr.add(actions.showFirstParentOnlyAction);
}
@@ -1721,7 +1943,6 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
IMenuManager showSubMenuMgr = new MenuManager(
UIText.GitHistoryPage_ShowSubMenuLabel);
viewMenuMgr.add(showSubMenuMgr);
- showSubMenuMgr.add(actions.showAllBranchesAction);
showSubMenuMgr.add(actions.showFirstParentOnlyAction);
showSubMenuMgr.add(actions.showAdditionalRefsAction);
showSubMenuMgr.add(actions.showNotesAction);
@@ -1744,6 +1965,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
viewMenuMgr.add(actions.filterAction);
+ viewMenuMgr.add(actions.configureFiltersAction);
+
viewMenuMgr.add(new Separator());
viewMenuMgr.add(actions.compareModeAction);
viewMenuMgr.add(actions.reuseCompareEditorAction);
@@ -2488,6 +2711,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
return;
}
+ Assert.isNotNull(db);
+
AnyObjectId headId = resolveHead(db, true);
if (headId == null) {
currentHeadId = null;
@@ -2573,10 +2798,17 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
* @return {@code true} if any setting changed, {@code false} otherwise
*/
private boolean updateSettings() {
- boolean allBranchesChanged = currentShowAllBranches != store
- .getBoolean(UIPreferences.RESOURCEHISTORY_SHOW_ALL_BRANCHES);
- currentShowAllBranches = store
- .getBoolean(UIPreferences.RESOURCEHISTORY_SHOW_ALL_BRANCHES);
+ String newRefFilters = ""; //$NON-NLS-1$
+ Repository repo = getCurrentRepo();
+ if (repo != null) {
+ newRefFilters = store.getString(Activator.getDefault()
+ .getRepositoryUtil()
+ .getRepositorySpecificPreferenceKey(repo,
+ UIPreferences.RESOURCEHISTORY_SELECTED_REF_FILTERS));
+ }
+ boolean refFiltersChanged = !Objects.equals(currentRefFilters,
+ newRefFilters);
+ currentRefFilters = newRefFilters;
boolean isShowFirstParentOnly = isShowFirstParentOnly();
boolean firstParentOnlyChanged = currentShowFirstParentOnly != isShowFirstParentOnly;
@@ -2594,7 +2826,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
boolean followRenamesChanged = currentFollowRenames != getFollowRenames();
currentFollowRenames = getFollowRenames();
- return allBranchesChanged || firstParentOnlyChanged
+ return refFiltersChanged || firstParentOnlyChanged
|| additionalRefsChange || showNotesChanged
|| followRenamesChanged;
}
@@ -2711,23 +2943,6 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
return !o.equals(n);
}
- private static String getRepoSpecificKey(String repositoryId,
- String key) {
- return key + "_" + repositoryId; //$NON-NLS-1$
- }
-
- private static String getRepoSpecificKey(@NonNull Repository repo,
- String key) {
- String pathString = Activator.getDefault().getRepositoryUtil()
- .getRelativizedRepositoryPath(repo);
-
- if (pathString == null) {
- return getRepoSpecificKey(repo.toString(), key);
- }
-
- return getRepoSpecificKey(pathString, key);
- }
-
/**
* Unset the repository specific preference of the given key for the
* repository represented by the given repository path.
@@ -2743,7 +2958,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
*/
private void unsetRepoSpecificPreference(String repositoryPath,
String key) {
- String prefString = getRepoSpecificKey(repositoryPath, key);
+ String prefString = Activator.getDefault().getRepositoryUtil()
+ .getRepositorySpecificPreferenceKey(repositoryPath, key);
store.setToDefault(prefString);
}
@@ -2763,7 +2979,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
Repository repo = getCurrentRepo();
if (repo != null) {
- String repoSpecificKey = getRepoSpecificKey(repo, prefKey);
+ String repoSpecificKey = Activator.getDefault().getRepositoryUtil()
+ .getRepositorySpecificPreferenceKey(repo, prefKey);
if (store.contains(repoSpecificKey)) {
firstParent = store.getBoolean(repoSpecificKey);
}
@@ -2771,11 +2988,12 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener,
return firstParent;
}
- private @NonNull SWTWalk createNewWalk(Repository db, AnyObjectId headId,
+ private @NonNull SWTWalk createNewWalk(@NonNull Repository db,
+ AnyObjectId headId,
AnyObjectId fetchHeadId) {
currentHeadId = headId;
currentFetchHeadId = fetchHeadId;
- SWTWalk walk = new GitHistoryWalk(db, headId, selectedObj);
+ SWTWalk walk = new GitHistoryWalk(db, selectedObj);
if (isShowFirstParentOnly()) {
walk.setFirstParent(true);
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryRefFilterConfigurationDialog.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryRefFilterConfigurationDialog.java
new file mode 100644
index 000000000..11e09f61c
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryRefFilterConfigurationDialog.java
@@ -0,0 +1,490 @@
+/*******************************************************************************
+ * Copyright (C) 2019, Tim Neumann <Tim.Neumann@advantest.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.history;
+
+import java.util.Set;
+
+import org.eclipse.egit.ui.internal.UIText;
+import org.eclipse.egit.ui.internal.dialogs.AbstractBranchSelectionDialog;
+import org.eclipse.egit.ui.internal.history.RefFilterHelper.RefFilter;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ICheckStateProvider;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.preferences.ViewSettingsDialog;
+
+/**
+ * The dialog for creating ref filters for the git history view.
+ */
+public class GitHistoryRefFilterConfigurationDialog
+ extends ViewSettingsDialog {
+
+ private static final String FILTER_COLUMN_NAME = "filter"; //$NON-NLS-1$
+
+ private static final String NEW_FILTER_INITIAL_STRING = "refs/*"; //$NON-NLS-1$
+
+ private final Repository repo;
+
+ private final RefFilterHelper helper;
+
+ private Set<RefFilter> filters;
+
+ private CheckboxTableViewer configsTable;
+ private Button removeButton;
+ private Button editButton;
+ private TextCellEditor editor;
+
+ private volatile boolean editingMode = false;
+
+ private boolean defaultsPerformed = false;
+
+ /**
+ * Create a new instance of the receiver.
+ *
+ * @param parentShell
+ * @param repo
+ * @param helper
+ */
+ public GitHistoryRefFilterConfigurationDialog(Shell parentShell,
+ Repository repo, RefFilterHelper helper) {
+ super(parentShell);
+ this.repo = repo;
+ this.helper = helper;
+ }
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ newShell.setText(UIText.GitHistoryPage_filterRefDialog_dialogTitle);
+ }
+
+ @Override
+ protected Point getInitialSize() {
+ return new Point(convertHorizontalDLUsToPixels(400),
+ convertHorizontalDLUsToPixels(300));
+ }
+
+ @Override
+ protected boolean isResizable() {
+ return true;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite container = createUi(parent);
+ init();
+ return container;
+ }
+
+ private Composite createUi(Composite parent) {
+ Composite container = new Composite(parent, SWT.NONE);
+ container.setLayout(new GridLayout());
+
+ container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ container.setFont(parent.getFont());
+
+ Composite composite = new Composite(container, SWT.NONE);
+ composite.setLayout(new GridLayout());
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ composite.setBackground(container.getBackground());
+
+ Group filtersComposite = new Group(composite, SWT.NONE);
+ filtersComposite
+ .setText(
+ UIText.GitHistoryPage_filterRefDialog_filtersCompositLabel);
+
+ filtersComposite.setLayout(new GridLayout(2, false));
+ filtersComposite
+ .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ filtersComposite.setBackground(composite.getBackground());
+
+ fillFiltersComposite(filtersComposite);
+
+ Composite actionsComposite = new Composite(composite, SWT.NONE);
+
+ actionsComposite.setLayout(new GridLayout());
+ actionsComposite
+ .setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ actionsComposite.setBackground(composite.getBackground());
+
+ createActionCompositeButtons(actionsComposite);
+
+ // Line above OK and cancel buttons
+ Label separator = new Label(parent, SWT.HORIZONTAL | SWT.SEPARATOR);
+ separator
+ .setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ return container;
+ }
+
+ private void fillFiltersComposite(Group filtersComposite) {
+ Composite tableComposite = new Composite(filtersComposite, SWT.NONE);
+ tableComposite.setLayout(new GridLayout());
+ tableComposite
+ .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ tableComposite.setBackground(filtersComposite.getBackground());
+
+ createTable(tableComposite);
+
+ createFilterCompositeButtons(filtersComposite);
+
+ Label patternExplanation = new Label(filtersComposite,
+ SWT.CENTER | SWT.WRAP);
+ patternExplanation
+ .setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ patternExplanation.setText(
+ UIText.GitHistoryPage_filterRefDialog_patternExplanation);
+ }
+
+ private void createTable(Composite parent) {
+ configsTable = CheckboxTableViewer
+ .newCheckList(parent, SWT.BORDER | SWT.FULL_SELECTION);
+ GridData tableData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ tableData.widthHint = convertHorizontalDLUsToPixels(120);
+ configsTable.getControl().setLayoutData(tableData);
+
+ configsTable.setContentProvider(ArrayContentProvider.getInstance());
+
+ configsTable.setLabelProvider(new RefLableProvider());
+
+ configsTable.setComparator(new ViewerComparator() {
+ @Override
+ public int category(Object element) {
+ RefFilter filter = ((RefFilter) element);
+ if (filter.isPreconfigured()) {
+ return 100;
+ }
+ return 1000;
+ }
+ });
+
+ configsTable.addSelectionChangedListener(event -> {
+ updateButtonEnablement();
+ });
+
+ configsTable.addCheckStateListener(new ICheckStateListener() {
+ @Override
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ ((RefFilter) event.getElement())
+ .setSelected(event.getChecked());
+ }
+ });
+
+ configsTable.setCheckStateProvider(new ICheckStateProvider() {
+ @Override
+ public boolean isGrayed(Object element) {
+ return false;
+ }
+
+ @Override
+ public boolean isChecked(Object element) {
+ return ((RefFilter) element).isSelected();
+ }
+ });
+
+ configsTable.addDoubleClickListener(new IDoubleClickListener() {
+ @Override
+ public void doubleClick(DoubleClickEvent event) {
+ editCurrentRow();
+ }
+ });
+
+ editor = new TextCellEditor(configsTable.getTable()) {
+ @Override
+ public void deactivate() {
+ super.deactivate();
+ if (editingMode) {
+ editingMode = false;
+ updateButtonEnablement();
+ }
+ }
+ };
+ CellEditor[] editors = new CellEditor[1];
+ editors[0] = editor;
+ configsTable.setColumnProperties(new String[] { FILTER_COLUMN_NAME });
+ configsTable.setCellEditors(editors);
+ configsTable.setCellModifier(new ICellModifier() {
+
+ @Override
+ public void modify(Object element, String property, Object value) {
+ RefFilter filter = (RefFilter) ((TableItem) element).getData();
+ filter.setFilterString((String) value);
+ configsTable.refresh();
+ }
+
+ @Override
+ public Object getValue(Object element, String property) {
+ RefFilter filter = (RefFilter) element;
+ return filter.getFilterString();
+ }
+
+ @Override
+ public boolean canModify(Object element, String property) {
+ if (!editingMode) {
+ return false;
+ }
+ RefFilter filter = (RefFilter) element;
+ return !filter.isPreconfigured();
+ }
+ });
+ }
+
+ private void createFilterCompositeButtons(Composite parent) {
+ Composite buttonComposite = new Composite(parent, SWT.NONE);
+ buttonComposite.setLayout(new GridLayout());
+ buttonComposite.setLayoutData(
+ new GridData(SWT.CENTER, SWT.BEGINNING, false, false));
+
+ Button addNew = new Button(buttonComposite, SWT.PUSH);
+ addNew.setText(UIText.GitHistoryPage_filterRefDialog_button_add);
+ addNew.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ RefFilter newFilter = helper.new RefFilter(
+ NEW_FILTER_INITIAL_STRING);
+ filters.add(newFilter);
+ configsTable.refresh();
+ editFilter(newFilter);
+ }
+ });
+ setButtonLayoutData(addNew);
+
+ Button addRefButton = new Button(buttonComposite, SWT.PUSH);
+ addRefButton
+ .setText(UIText.GitHistoryPage_filterRefDialog_button_addRef);
+ addRefButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ updateButtonEnablement();
+ RefSelectionDialog dialog = new RefSelectionDialog(getShell(),
+ repo);
+ if (dialog.open() == Window.OK) {
+ RefFilter newFilter = helper.new RefFilter(
+ dialog.getRefName());
+ filters.add(newFilter);
+ configsTable.refresh();
+ }
+ }
+ });
+ setButtonLayoutData(addRefButton);
+
+ removeButton = new Button(buttonComposite, SWT.PUSH);
+ removeButton
+ .setText(UIText.GitHistoryPage_filterRefDialog_button_remove);
+ removeButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ removeSelectedFilter();
+ }
+ });
+ removeButton.setEnabled(false);
+ setButtonLayoutData(removeButton);
+
+ editButton = new Button(buttonComposite, SWT.PUSH);
+ editButton.setText(UIText.GitHistoryPage_filterRefDialog_button_edit);
+ editButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ editCurrentRow();
+ updateButtonEnablement();
+ }
+ });
+ editButton.setEnabled(false);
+ setButtonLayoutData(editButton);
+ }
+
+ private void createActionCompositeButtons(Composite parent) {
+ Composite buttonComposite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ buttonComposite.setLayout(layout);
+ buttonComposite.setLayoutData(
+ new GridData(SWT.CENTER, SWT.BEGINNING, false, false));
+
+ Button setHeadOnly = new Button(buttonComposite, SWT.PUSH);
+ setHeadOnly.setText(
+ UIText.GitHistoryPage_filterRefDialog_button_headOnly);
+ setHeadOnly.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ helper.selectOnlyHEAD(filters);
+ configsTable.refresh();
+ }
+ });
+ setButtonLayoutData(setHeadOnly);
+
+ Button setCurrentBranchOnly = new Button(buttonComposite, SWT.PUSH);
+ setCurrentBranchOnly
+ .setText(
+ UIText.GitHistoryPage_filterRefDialog_button_currentBranchOnly);
+ setCurrentBranchOnly.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ helper.selectOnlyCurrentBranch(filters);
+ configsTable.refresh();
+ }
+ });
+ setButtonLayoutData(setCurrentBranchOnly);
+
+ Button setAllBranchesAndTags = new Button(buttonComposite, SWT.PUSH);
+ setAllBranchesAndTags.setText(
+ UIText.GitHistoryPage_filterRefDialog_button_allBranchesAndTags);
+ setAllBranchesAndTags.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ helper.selectExactlyAllBranchesAndTags(filters);
+ configsTable.refresh();
+ }
+ });
+ setButtonLayoutData(setAllBranchesAndTags);
+ }
+
+ @Override
+ protected void okPressed() {
+ helper.setRefFilters(filters);
+ if (defaultsPerformed) {
+ helper.resetLastSelectionStateToDefault();
+ }
+ super.okPressed();
+ }
+
+ @Override
+ protected void performDefaults() {
+ filters = helper.getDefaults();
+ configsTable.setInput(filters);
+ defaultsPerformed = true;
+ super.performDefaults();
+ }
+
+ private void init() {
+ filters = helper.getRefFilters();
+ if (helper.isOnlyHEADSelected(filters)) {
+ helper.restoreLastSelectionState(filters);
+ }
+ configsTable.setInput(filters);
+ configsTable.refresh();
+ }
+
+ private void editCurrentRow() {
+ editFilter(getSelectionFromTable());
+ }
+
+ private void editFilter(RefFilter filter) {
+ editingMode = true;
+ configsTable.editElement(filter, 0);
+ updateButtonEnablement();
+ }
+
+ private void removeSelectedFilter() {
+ RefFilter filter = getSelectionFromTable();
+ if (filter == null) {
+ return;
+ }
+ filters.remove(filter);
+ configsTable.refresh();
+ }
+
+ private void updateButtonEnablement() {
+ RefFilter filter = getSelectionFromTable();
+ boolean writableRow = filter != null && !filter.isPreconfigured();
+ removeButton.setEnabled(writableRow);
+ editButton.setEnabled(writableRow);
+ }
+
+ private RefFilter getSelectionFromTable() {
+ IStructuredSelection selection = configsTable.getStructuredSelection();
+ return (RefFilter) selection.getFirstElement();
+ }
+
+ private static class RefLableProvider extends LabelProvider
+ implements IColorProvider {
+
+ @Override
+ public String getText(Object element) {
+ RefFilter filter = ((RefFilter) element);
+ String result = filter.getFilterString();
+ if (filter.isPreconfigured()) {
+ result += UIText.GitHistoryPage_filterRefDialog_preconfiguredText;
+ }
+ return result;
+ }
+
+ @Override
+ public Color getForeground(Object element) {
+ RefFilter filter = ((RefFilter) element);
+ if (filter.isPreconfigured()) {
+ return PlatformUI.getWorkbench().getDisplay()
+ .getSystemColor(SWT.COLOR_DARK_GRAY);
+ }
+ return null;
+ }
+
+ @Override
+ public Color getBackground(Object element) {
+ return null;
+ }
+
+ }
+
+ private static class RefSelectionDialog
+ extends AbstractBranchSelectionDialog {
+
+ public RefSelectionDialog(Shell parentShell, Repository repository) {
+ // Using empty string instead of null to select nothing instead of
+ // the current branch.
+ super(parentShell, repository, "", SHOW_LOCAL_BRANCHES //$NON-NLS-1$
+ | SHOW_REMOTE_BRANCHES | SHOW_TAGS | SHOW_REFERENCES
+ | SELECT_CURRENT_REF | EXPAND_LOCAL_BRANCHES_NODE
+ | EXPAND_REMOTE_BRANCHES_NODE);
+ }
+
+ @Override
+ protected void refNameSelected(String refName) {
+ setOkButtonEnabled(refName != null);
+ }
+
+ @Override
+ protected String getTitle() {
+ return UIText.GitHistoryPage_filterRefDialog_selectRefDialog_dialogTitle;
+ }
+
+ @Override
+ protected String getMessageText() {
+ return UIText.GitHistoryPage_filterRefDialog_selectRefDialog_dialogMessage;
+ }
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryWalk.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryWalk.java
index 57ccd8e79..18e541ef1 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryWalk.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryWalk.java
@@ -12,14 +12,15 @@ package org.eclipse.egit.ui.internal.history;
import java.io.IOException;
import java.text.MessageFormat;
+import java.util.Set;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIPreferences;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
@@ -38,13 +39,10 @@ class GitHistoryWalk extends SWTWalk {
private boolean initialized = false;
- private final AnyObjectId headId;
-
private final ObjectId toShow;
- GitHistoryWalk(Repository repository, AnyObjectId headId, ObjectId toShow) {
+ GitHistoryWalk(@NonNull Repository repository, ObjectId toShow) {
super(repository);
- this.headId = headId;
this.toShow = toShow;
}
@@ -73,12 +71,8 @@ class GitHistoryWalk extends SWTWalk {
IPreferenceStore store = Activator.getDefault().getPreferenceStore();
RefDatabase db = getRepository().getRefDatabase();
try {
- if (store.getBoolean(
- UIPreferences.RESOURCEHISTORY_SHOW_ALL_BRANCHES)) {
- markStartAllRefs(db, Constants.R_HEADS);
- markStartAllRefs(db, Constants.R_REMOTES);
- markStartAllRefs(db, Constants.R_TAGS);
- }
+ markStartAllRefs(new RefFilterHelper(getRepository())
+ .getMatchingRefsForSelectedRefFilters());
if (store.getBoolean(
UIPreferences.RESOURCEHISTORY_SHOW_ADDITIONAL_REFS)) {
markStartAdditionalRefs(db);
@@ -88,7 +82,6 @@ class GitHistoryWalk extends SWTWalk {
} else {
markUninteresting(db, Constants.R_NOTES);
}
- markStart(parseCommit(headId));
if (toShow != null) {
markStart(toShow);
}
@@ -111,6 +104,13 @@ class GitHistoryWalk extends SWTWalk {
}
}
+ private void markStartAllRefs(Set<Ref> refs)
+ throws IOException, IncorrectObjectTypeException {
+ for (Ref ref : refs) {
+ markStartRef(ref);
+ }
+ }
+
private void markStartAdditionalRefs(RefDatabase db)
throws IOException, IncorrectObjectTypeException {
for (Ref ref : db.getAdditionalRefs()) {
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/RefFilterHelper.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/RefFilterHelper.java
new file mode 100644
index 000000000..1727e6e3d
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/RefFilterHelper.java
@@ -0,0 +1,727 @@
+/*******************************************************************************
+ * Copyright (C) 2019, Tim Neumann <Tim.Neumann@advantest.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.history;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.apache.tools.ant.types.selectors.TokenizedPath;
+import org.apache.tools.ant.types.selectors.TokenizedPattern;
+import org.eclipse.egit.ui.Activator;
+import org.eclipse.egit.ui.UIPreferences;
+import org.eclipse.jface.preference.IPersistentPreferenceStore;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefDatabase;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * A class for handling the config reading, writing and parsing for the ref
+ * filters as well as matching refs against a filter.
+ */
+public class RefFilterHelper {
+
+ private static final String ANY = "**"; //$NON-NLS-1$
+
+ private static final String REF_SEPERATOR = ":"; //$NON-NLS-1$
+
+ private static final String MACRO_CURRENT_BRANCH = "[CURRENT-BRANCH]"; //$NON-NLS-1$
+
+ private static final String DEFAULT_SELECTED_REFS = Constants.HEAD;
+
+ private static final String DEFAULT_SELECTED_REFS_ALL_BRANCHES =
+ Constants.HEAD + REF_SEPERATOR
+ + Constants.R_HEADS + ANY + REF_SEPERATOR
+ + Constants.R_REMOTES + ANY + REF_SEPERATOR
+ + Constants.R_TAGS + ANY;
+
+ private final IPreferenceStore store;
+
+ @NonNull
+ private final Repository repository;
+
+ private List<RefFilter> preconfiguredFilters;
+
+ private List<RefFilter> filtersForHEAD;
+ private List<RefFilter> filtersForCurrentBranch;
+ private List<RefFilter> filtersForAllBranchesAndTags;
+
+ private Map<String, Function<Repository, String>> macros;
+
+ private static @NonNull IPreferenceStore checkNull(IPreferenceStore store) {
+ if (store == null) {
+ throw new NullPointerException("Preference store is null."); //$NON-NLS-1$
+ }
+ return store;
+ }
+
+ /**
+ * Create a new RefFilterHelper for the given repository using the
+ * preference store provided by the activator of this ui plugin.
+ *
+ * @param repository
+ * The repository to create the helper for; must not be null
+ */
+ public RefFilterHelper(@NonNull Repository repository) {
+ this(repository,
+ checkNull(Activator.getDefault().getPreferenceStore()));
+ }
+
+ /**
+ * Create a new RefFilterHelper for the given repository using the given
+ * preference store.
+ *
+ * @param repository
+ * The repository to create the helper for; must not be null
+ * @param store
+ * The preference store to use; must not be null
+ */
+ public RefFilterHelper(@NonNull Repository repository,
+ @NonNull IPreferenceStore store) {
+ this.repository = repository;
+ this.store = store;
+ setupPreconfigueredFilters();
+ setupMacros();
+ // Just always init the repo defaults as we don't know if this repo had
+ // a helper before.
+ initDefaultsForRepo();
+ }
+
+ private RefFilter newPreConfFilter(String filter) {
+ return new RefFilter(filter, true);
+ }
+
+ private RefFilter newPreConfPrefixFilter(String prefix) {
+ return newPreConfFilter(prefix + "**"); //$NON-NLS-1$
+ }
+
+ private void setupPreconfigueredFilters() {
+ preconfiguredFilters = new ArrayList<>();
+ filtersForHEAD = new ArrayList<>();
+ filtersForCurrentBranch = new ArrayList<>();
+ filtersForAllBranchesAndTags = new ArrayList<>();
+
+ RefFilter head = newPreConfFilter(Constants.HEAD);
+ preconfiguredFilters.add(head);
+ filtersForHEAD.add(head);
+ filtersForAllBranchesAndTags.add(head);
+
+ RefFilter current_branch = newPreConfFilter(
+ Constants.R_REFS + "**/" + MACRO_CURRENT_BRANCH); //$NON-NLS-1$
+ preconfiguredFilters.add(current_branch);
+ filtersForCurrentBranch.add(current_branch);
+
+ RefFilter branches = newPreConfPrefixFilter(Constants.R_HEADS);
+ preconfiguredFilters.add(branches);
+ filtersForAllBranchesAndTags.add(branches);
+
+ RefFilter remoteBranches = newPreConfPrefixFilter(Constants.R_REMOTES);
+ preconfiguredFilters.add(remoteBranches);
+ filtersForAllBranchesAndTags.add(remoteBranches);
+
+ RefFilter tags = newPreConfPrefixFilter(Constants.R_TAGS);
+ preconfiguredFilters.add(tags);
+ filtersForAllBranchesAndTags.add(tags);
+ }
+
+ private void setupMacros() {
+ macros = new HashMap<>();
+ macros.put(MACRO_CURRENT_BRANCH, repo -> {
+ try {
+ return repo.getBranch();
+ } catch (IOException e) {
+ Activator.handleError(e.getMessage(), e, false);
+ }
+ return ""; //$NON-NLS-1$
+ });
+ }
+
+ private void setDefaultSelectionBasedOnShowAllBranches() {
+ String currentDefault = store.getDefaultString(
+ UIPreferences.RESOURCEHISTORY_SELECTED_REF_FILTERS);
+
+ if (currentDefault != DEFAULT_SELECTED_REFS
+ && currentDefault != DEFAULT_SELECTED_REFS_ALL_BRANCHES) {
+ // The default was changed elsewhere.
+ // Probably a plugin customization.
+ // Don't overwrite it.
+ return;
+ }
+
+ boolean showAll = store
+ .getBoolean(UIPreferences.RESOURCEHISTORY_SHOW_ALL_BRANCHES);
+
+ if (showAll) {
+ store.setDefault(UIPreferences.RESOURCEHISTORY_SELECTED_REF_FILTERS,
+ DEFAULT_SELECTED_REFS_ALL_BRANCHES);
+ } else {
+ store.setDefault(UIPreferences.RESOURCEHISTORY_SELECTED_REF_FILTERS,
+ DEFAULT_SELECTED_REFS);
+ }
+ }
+
+ private void initDefaultForRepo(String preferenceName) {
+ String repoSepcificPrefName = Activator.getDefault().getRepositoryUtil()
+ .getRepositorySpecificPreferenceKey(this.repository,
+ preferenceName);
+
+ store.setDefault(repoSepcificPrefName,
+ store.getDefaultString(preferenceName));
+ }
+
+ /**
+ * Init the default of the repo specific pref from global default. This
+ * needs to happen after each eclipse startup (as the default is not
+ * persistet) for each repo.
+ */
+ private void initDefaultsForRepo() {
+ setDefaultSelectionBasedOnShowAllBranches();
+ initDefaultForRepo(UIPreferences.RESOURCEHISTORY_REF_FILTERS);
+ initDefaultForRepo(UIPreferences.RESOURCEHISTORY_SELECTED_REF_FILTERS);
+ initDefaultForRepo(
+ UIPreferences.RESOURCEHISTORY_LAST_SELECTED_REF_FILTERS);
+ }
+
+ /**
+ * Get a preference string from the preference store. This should return the
+ * repository specific preference string if applicable.
+ *
+ * @param preferenceName
+ * the name of the preference
+ * @return the string-valued preference
+ */
+ protected String getPreferenceString(String preferenceName) {
+ String repoSepcificPrefName = Activator.getDefault().getRepositoryUtil()
+ .getRepositorySpecificPreferenceKey(this.repository,
+ preferenceName);
+
+ return store.getString(repoSepcificPrefName);
+ }
+
+ private List<String> getFiltersFromPref(String preferenceName) {
+ String refFiltersString = getPreferenceString(preferenceName);
+ String[] filters = refFiltersString.split(REF_SEPERATOR);
+
+ return Arrays.asList(filters);
+ }
+
+ private void savePreferencStoreIfNeeded() {
+ if (store.needsSaving()
+ && store instanceof IPersistentPreferenceStore) {
+ try {
+ ((IPersistentPreferenceStore) store).save();
+ } catch (IOException e) {
+ Activator.handleError(e.getMessage(), e, false);
+ }
+ }
+ }
+
+ private void setFiltersInPref(String preferenceName, List<String> filters,
+ boolean save) {
+ String repoSepcificPrefName = Activator.getDefault().getRepositoryUtil()
+ .getRepositorySpecificPreferenceKey(this.repository,
+ preferenceName);
+ String refFiltersString = String.join(REF_SEPERATOR, filters);
+ store.setValue(repoSepcificPrefName, refFiltersString);
+
+ if (save) {
+ savePreferencStoreIfNeeded();
+ }
+ }
+
+ /**
+ * Get the configured ref filters from the preference store.
+ *
+ * @return A list of all configuered ref filter strings
+ */
+ public List<String> getConfiguredFilters() {
+ return getFiltersFromPref(UIPreferences.RESOURCEHISTORY_REF_FILTERS);
+ }
+
+ /**
+ * Set the configured ref filters in the preference store.
+ *
+ * @param filters
+ * The list of configuered ref filter strings to set
+ * @param save
+ * Whether to save the preference store if necessary
+ */
+ public void setConfiguredFilters(List<String> filters, boolean save) {
+ setFiltersInPref(UIPreferences.RESOURCEHISTORY_REF_FILTERS, filters,
+ save);
+ }
+
+ /**
+ * Get the selected ref filters from the preference store.
+ *
+ * @return A list of all selected ref filter strings
+ */
+ public List<String> getSelectedFilters() {
+ return getFiltersFromPref(
+ UIPreferences.RESOURCEHISTORY_SELECTED_REF_FILTERS);
+ }
+
+ /**
+ * Set the selected ref filters in the preference store.
+ *
+ * @param filters
+ * The list of selected ref filter strings to set
+ * @param save
+ * Whether to save the preference store if necessary
+ */
+ public void setSelectedFilters(List<String> filters, boolean save) {
+ setFiltersInPref(UIPreferences.RESOURCEHISTORY_SELECTED_REF_FILTERS,
+ filters, save);
+ }
+
+ /**
+ * Get the last selected ref filters from the preference store.
+ *
+ * @return A list of the last selected ref filter strings
+ */
+ public List<String> getLastSelectedFilters() {
+ return getFiltersFromPref(
+ UIPreferences.RESOURCEHISTORY_LAST_SELECTED_REF_FILTERS);
+ }
+
+ /**
+ * Set the last selected ref filters in the preference store.
+ *
+ * @param filters
+ * The list of last selected ref filter strings to set
+ * @param save
+ * Whether to save the preference store if necessary
+ */
+ public void setLastSelectedFilters(List<String> filters, boolean save) {
+ setFiltersInPref(
+ UIPreferences.RESOURCEHISTORY_LAST_SELECTED_REF_FILTERS,
+ filters, save);
+ }
+
+ private void addPreconfigueredFilters(Map<String, RefFilter> filters) {
+ for (RefFilter filter : preconfiguredFilters) {
+ // Don't use the existing object because selection states would be
+ // persisted immediately without calling setRefFilters.
+ filters.put(filter.getFilterString(), new RefFilter(filter));
+ }
+ }
+
+ /**
+ * @return the set of all ref filters
+ */
+ public Set<RefFilter> getRefFilters() {
+ Map<String, RefFilter> filters = new HashMap<>();
+ addPreconfigueredFilters(filters);
+
+ for (String filter : getConfiguredFilters()) {
+ if (filter == null || filter.isEmpty()) {
+ continue;
+ }
+ filters.put(filter, new RefFilter(filter, false));
+ }
+
+ for (String filter : getSelectedFilters()) {
+ if (filter == null || filter.isEmpty()) {
+ continue;
+ }
+ // A user could change the pref files manually
+ // Therefore we need to make sure all selected filters are also
+ // available.
+ // So we add them to the set if they are not already there
+ filters.putIfAbsent(filter, new RefFilter(filter, false));
+ filters.get(filter).setSelected(true);
+ }
+ return new HashSet<>(filters.values());
+ }
+
+ /**
+ * Restore the last selection state.
+ * @param filters The set of filters to restore the state for.
+ */
+ public void restoreLastSelectionState(Set<RefFilter> filters) {
+ for(RefFilter filter : filters) {
+ filter.setSelected(getLastSelectedFilters()
+ .contains(filter.getFilterString()));
+ }
+ }
+
+ /**
+ * Set the given rev filters in the preference store.
+ * <p>
+ * This overrides the selected and the configuered filters in the preference
+ * store.
+ * <p>
+ *
+ * @param filters
+ * The set of filters to save.
+ */
+ public void setRefFilters(Set<RefFilter> filters) {
+ List<String> selected = filters.stream().filter(RefFilter::isSelected)
+ .map(RefFilter::getFilterString).collect(Collectors.toList());
+ setSelectedFilters(selected, false);
+
+ List<String> configured = filters.stream()
+ .filter(f -> !f.isPreconfigured())
+ .map(RefFilter::getFilterString).collect(Collectors.toList());
+ setConfiguredFilters(configured, false);
+
+ savePreferencStoreIfNeeded();
+ }
+
+ /**
+ * Save the selection state of the given filter set as the last selection
+ * state.
+ *
+ * @param filters
+ * The filters to get the selection state from
+ */
+ public void saveSelectionStateAsLastSelectionState(Set<RefFilter> filters) {
+ List<String> selected = new ArrayList<>();
+ for(RefFilter filter : filters) {
+ if (filter.isSelected()) {
+ selected.add(filter.getFilterString());
+ }
+ }
+ setLastSelectedFilters(selected, true);
+ }
+
+ /**
+ * Reset the last selection state to the default.
+ */
+ public void resetLastSelectionStateToDefault() {
+ String repoSepcificPrefName = Activator.getDefault().getRepositoryUtil()
+ .getRepositorySpecificPreferenceKey(this.repository,
+ UIPreferences.RESOURCEHISTORY_LAST_SELECTED_REF_FILTERS);
+ store.setToDefault(repoSepcificPrefName);
+ savePreferencStoreIfNeeded();
+ }
+
+ /**
+ * Get all matching refs in the given repository for the currently selected
+ * ref filters.
+ *
+ * @return All matching refs from the repo
+ * @throws IOException
+ * the reference space cannot be accessed.
+ */
+ public Set<Ref> getMatchingRefsForSelectedRefFilters()
+ throws IOException {
+ RefDatabase db = this.repository.getRefDatabase();
+ Set<Ref> result = new HashSet<>();
+ Set<RefFilter> selectedFilters = getRefFilters().stream()
+ .filter(f -> f.isSelected()).collect(Collectors.toSet());
+
+ for (Ref ref : db.getRefs()) {
+ TokenizedPath refPath = new TokenizedPath(ref.getName());
+ for (RefFilter filter : selectedFilters) {
+ if (filter.matches(refPath)) {
+ result.add(ref);
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Select only the HEAD preconfigured ref filter.
+ * <p>
+ * This will modify objects in the given list.
+ * </p>
+ *
+ * @param filters
+ * The filters to change the selection of
+ */
+ public void selectOnlyHEAD(Set<RefFilter> filters) {
+ for (RefFilter filter : filters) {
+ filter.setSelected(filtersForHEAD.contains(filter));
+ }
+ }
+
+ /**
+ * Check whether only the HEAD preconfigured ref filter is selected.
+ *
+ * @param filters
+ * The filters to check
+ * @return Whether exactly HEAD is selected
+ */
+ public boolean isOnlyHEADSelected(Set<RefFilter> filters) {
+ for (RefFilter filter : filters) {
+ if (filter.isSelected()) {
+ if (!filtersForHEAD.contains(filter)) {
+ return false;
+ }
+ } else {
+ if (filtersForHEAD.contains(filter)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Select only the preconfigured ref filter for the current branch (local
+ * and remote).
+ * <p>
+ * This will modify objects in the given list.
+ * </p>
+ *
+ * @param filters
+ * The filters to change the selection of
+ */
+ public void selectOnlyCurrentBranch(Set<RefFilter> filters) {
+ for (RefFilter filter : filters) {
+ filter.setSelected(filtersForCurrentBranch.contains(filter));
+ }
+ }
+
+ /**
+ * Check whether only the preconfigured ref filter for the current branch
+ * (local and remote) is selected.
+ *
+ * @param filters
+ * The filters to check
+ * @return Whether exactly the current branch is selected
+ */
+ public boolean isOnlyCurrentBranchSelected(Set<RefFilter> filters) {
+ for (RefFilter filter : filters) {
+ if (filter.isSelected()) {
+ if (!filtersForCurrentBranch.contains(filter)) {
+ return false;
+ }
+ } else {
+ if (filtersForCurrentBranch.contains(filter)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Select exactly the preconfigured ref filters, which represent all
+ * branches and tags.
+ * <p>
+ * This will modify objects in the given list.
+ * </p>
+ *
+ * @param filters
+ * The filters to change the selection of.
+ */
+ public void selectExactlyAllBranchesAndTags(Set<RefFilter> filters) {
+ for (RefFilter filter : filters) {
+ filter.setSelected(filtersForAllBranchesAndTags.contains(filter));
+ }
+ }
+
+ /**
+ * Check whether exactly the preconfigured ref filters which represent all
+ * branches and tags.
+ *
+ * @param filters
+ * The filters to check
+ * @return Whether exactly all branches and tags are selected
+ */
+ public boolean isExactlyAllBranchesAndTagsSelected(Set<RefFilter> filters) {
+ for (RefFilter filter : filters) {
+ if (filter.isSelected()) {
+ if (!filtersForAllBranchesAndTags.contains(filter))
+ return false;
+ } else {
+ if (filtersForAllBranchesAndTags.contains(filter))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Get the default ref filters
+ *
+ * @return a set of the default ref filters.
+ */
+ public Set<RefFilter> getDefaults() {
+ setDefaultSelectionBasedOnShowAllBranches();
+ RefFilterHelper defaultsHelper = new RefFilterHelper(this.repository) {
+ @Override
+ protected String getPreferenceString(String preferenceName) {
+ return store.getDefaultString(preferenceName);
+ }
+ };
+ return defaultsHelper.getRefFilters();
+ }
+
+ /**
+ * Representation of a ref filter
+ */
+ public class RefFilter {
+ private final boolean preconfigured;
+
+ private String filterString;
+ private TokenizedPattern filterPattern;
+
+ private boolean selected = false;
+
+ /**
+ * Create a ref filter as the copy of an original.
+ * <p>
+ * The new filter has the same values as the original, but future
+ * changes on either of the original or this new filter won't affect the
+ * other one.
+ * </p>
+ *
+ * @param original
+ */
+ public RefFilter(RefFilter original) {
+ this(original.getFilterString(), original.isPreconfigured());
+ this.selected = original.isSelected();
+ }
+
+ /**
+ * Create a new ref filter
+ *
+ * @param filterString
+ * The filter string for the new ref filter; must not be
+ * null; must not be empty.
+ *
+ * @throws IllegalArgumentException
+ * if the filter string is null or empty
+ */
+ public RefFilter(String filterString) {
+ this(filterString, false);
+ }
+
+ /**
+ * Create a new ref filter
+ *
+ * @param filterString
+ * The filter string for the new ref filter; must not be
+ * null; must not be empty.
+ * @param isPreconfigured
+ * Whether the new Filter is a preconfiguered one
+ *
+ * @throws IllegalArgumentException
+ * if the filter string is null or empty
+ */
+ private RefFilter(String filterString, boolean isPreconfigured) {
+ if (filterString == null || filterString.isEmpty()) {
+ throw new IllegalArgumentException(
+ "Filter string is null or empty."); //$NON-NLS-1$
+ }
+ this.filterString = filterString;
+ this.filterPattern = new TokenizedPattern(filterString);
+ this.preconfigured = isPreconfigured;
+ }
+
+ /**
+ * @return whether this is a preconfigured filter
+ */
+ public boolean isPreconfigured() {
+ return preconfigured;
+ }
+
+ private TokenizedPattern patternWithExpandedMacros() {
+ TokenizedPattern currentPattern = filterPattern;
+ for(Map.Entry<String, Function<Repository, String>> macro : macros.entrySet()) {
+ if (currentPattern.containsPattern(macro.getKey())) {
+ String oldString = currentPattern.getPattern();
+ String macroString = macro.getKey();
+ String replacingString = macro.getValue().apply(repository);
+ String newString = oldString.replace(macroString,
+ replacingString);
+ currentPattern = new TokenizedPattern(newString);
+ }
+ }
+ return currentPattern;
+ }
+
+ /**
+ * Tries to match the given ref against this filter.
+ *
+ * @param refPath
+ * The path of the ref to match
+ * @return true if the ref path matches the pattern of this filter
+ */
+ public boolean matches(TokenizedPath refPath) {
+ return patternWithExpandedMacros().matchPath(refPath,
+ true);
+ }
+
+ /**
+ * @return the filter string; cannot be null; cannot be empty
+ */
+ public String getFilterString() {
+ return this.filterString;
+ }
+
+ /**
+ * @param filterString
+ * the filterString to set; must not be null; must not be
+ * empty
+ * @throws IllegalArgumentException
+ * if the filter string is null or empty
+ * @throws IllegalStateException
+ * if this is a preconfigured filter
+ */
+ public void setFilterString(String filterString) {
+ if (filterString == null || filterString.isEmpty()) {
+ throw new IllegalArgumentException(
+ "Filter string is null or empty."); //$NON-NLS-1$
+ }
+ if (preconfigured) {
+ throw new IllegalStateException(
+ "Cannot change a preconfigured filter."); //$NON-NLS-1$
+ }
+ this.filterString = filterString;
+ this.filterPattern = new TokenizedPattern(filterString);
+ }
+
+ /**
+ * @return whether this filter is currently selected
+ */
+ public boolean isSelected() {
+ return selected;
+ }
+
+ /**
+ * @param selected
+ * whether this filter is selected
+ */
+ public void setSelected(boolean selected) {
+ this.selected = selected;
+ }
+
+ @Override
+ public int hashCode() {
+ return filterPattern.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof RefFilter)) {
+ return false;
+ }
+ return filterPattern.equals(((RefFilter) obj).filterPattern);
+ }
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/SWTWalk.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/SWTWalk.java
index f8945dc80..5113eacb0 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/SWTWalk.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/SWTWalk.java
@@ -15,6 +15,7 @@ package org.eclipse.egit.ui.internal.history;
import java.io.IOException;
+import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.AnyObjectId;
@@ -26,17 +27,19 @@ import org.eclipse.jgit.revwalk.RevCommit;
class SWTWalk extends PlotWalk {
+ @NonNull
private final Repository repo;
private Ref head;
private boolean headInitialized;
- SWTWalk(final Repository repo) {
+ SWTWalk(final @NonNull Repository repo) {
super(repo);
this.repo = repo;
}
+ @NonNull
Repository getRepository() {
return repo;
}
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 4f41a5e3e..462c44a66 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
@@ -186,7 +186,8 @@ GitHistoryPage_CreatePatchMenuLabel=Create P&atch...
GitHistoryPage_CreateTagMenuLabel=Create &Tag...
GitHistoryPage_cherryPickMenuItem=C&herry-Pick...
GitHistoryPage_compareMode=Compare Mode
-GitHistoryPage_showAllBranches=Show All Branches and Tags
+GitHistoryPage_showingHistoryOfHead=Change what commits to show. Current: Only HEAD and its parents
+GitHistoryPage_showingHistoryOfConfiguredFilters=Change what commits to show. Current: All branches matching the configured ref filters
GitHistoryPage_showFirstParentOnly=Show First Parent Only
GitHistoryPage_squashMenuItem=Squash
GitHistoryPage_errorLookingUpPath=IO error looking up path {0} in {1}.
@@ -227,7 +228,7 @@ GitHistoryPage_rewordMenuItem=&Reword
GitHistoryPage_editMenuItem=&Edit
GitHistoryPage_SetAsBaselineMenuLabel=&Set as Baseline
GitHistoryPage_ShowAdditionalRefsMenuLabel=&Additional Refs
-GitHistoryPage_ShowAllBranchesMenuLabel=All &Branches and Tags
+GitHistoryPage_SelectShownRefsMenuLabel=Select shown &Refs
GitHistoryPage_ShowFirstParentOnlyMenuLabel=First &Parent Only
GitHistoryPage_FollowRenames=&Follow Renames
GitHistoryPage_FormatDiffJobName=Updating Diff
@@ -241,6 +242,20 @@ GitHistoryPage_pushCommit=&Push Commit...
GitHistoryPage_ShowSubMenuLabel=&Show
GitHistoryPage_ColumnsSubMenuLabel=&Columns
GitHistoryPage_toggleEmailAddresses=&E-mail Addresses
+GitHistoryPage_configureFilters=Ref F&ilters...
+GitHistoryPage_filterRefDialog_dialogTitle=Configure ref filters
+GitHistoryPage_filterRefDialog_filtersCompositLabel=Filters
+GitHistoryPage_filterRefDialog_patternExplanation=Filters are treated as path filters ('?', '*' and '**' are valid wildcards). Valid macros are "[CURRENT-BRANCH]", which will be replaced by the current branch name.
+GitHistoryPage_filterRefDialog_button_add=Add
+GitHistoryPage_filterRefDialog_button_remove=Remove
+GitHistoryPage_filterRefDialog_button_edit=Edit
+GitHistoryPage_filterRefDialog_button_addRef=Add Ref ...
+GitHistoryPage_filterRefDialog_button_headOnly=HEAD Only
+GitHistoryPage_filterRefDialog_button_currentBranchOnly=Current Branch (Local and Remote)
+GitHistoryPage_filterRefDialog_button_allBranchesAndTags=All Branches and Tags
+GitHistoryPage_filterRefDialog_preconfiguredText=\ - (preconfigured)
+GitHistoryPage_filterRefDialog_selectRefDialog_dialogTitle=Select Ref
+GitHistoryPage_filterRefDialog_selectRefDialog_dialogMessage=Select ref for branch filter
GitLightweightDecorator_name=Git resource decorations
GitPreferenceRoot_automaticallyEnableChangesetModel=Automatically enable commit &grouping in Git synchronizations
GitPreferenceRoot_BlameGroupHeader=Revision Information
@@ -734,7 +749,7 @@ HistoryPage_findbar_changeto_reference=Change to Branch/Tag
HistoryPage_findbar_exceeded=Results limit exceeded
HistoryPage_findbar_notFound=String not found
HistoryPage_findbar_reference=Branch/Tag
-HistoryPreferencePage_toggleAllBranches=All &Branches and Tags
+HistoryPreferencePage_toggleAllBranches=All &Branches and Tags initially
HistoryPreferencePage_showFirstParentOnlyDefault=F&irst parent only by default
HistoryPreferencePage_toggleAdditionalRefs=&Additional Refs
HistoryPreferencePage_toggleEmailAddresses=&E-mail addresses in Author/Committer columns

Back to the top