diff options
author | Tim Neumann | 2019-07-19 13:31:12 +0000 |
---|---|---|
committer | Thomas Wolf | 2019-08-14 16:46:27 +0000 |
commit | e48ed04cd3f86f698c453ca6295621cde7501157 (patch) | |
tree | 68488496f8ac38dd69dbe855fd3780418fdb0794 | |
parent | 37f68e0f7151b67592b592d07d4356811895ce3e (diff) | |
download | egit-e48ed04cd3f86f698c453ca6295621cde7501157.tar.gz egit-e48ed04cd3f86f698c453ca6295621cde7501157.tar.xz egit-e48ed04cd3f86f698c453ca6295621cde7501157.zip |
Add "show first parent only" button to the history view
This includes:
- action in GitHistoryPage
- allow the setting to be sticky to one repository
- add getter and setter for GitHistoryPage.currentRepo
-> so a repo change can be detected
- add the action to the menu and toolbar
- add corresponding preference to the preference page
-> "Team -> Git -> History"
- add a new icon for the action
- based on the preference do a first-parent-only RevWalk
- create some new helper methods in RepositoryUtil
Bug: 549424
Change-Id: I548ef25f8c13661fadf725952bc25d2f481c7a43
Signed-off-by: Tim Neumann <Tim.Neumann@advantest.com>
Also-by: Tetiana Pliekhova <tetiana.pliekhova@advantest.com>
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
12 files changed, 458 insertions, 38 deletions
diff --git a/icons/org.eclipse.egit.ui/icons/obj16/first_parent_only.svg b/icons/org.eclipse.egit.ui/icons/obj16/first_parent_only.svg new file mode 100644 index 0000000000..c7c439d263 --- /dev/null +++ b/icons/org.eclipse.egit.ui/icons/obj16/first_parent_only.svg @@ -0,0 +1,165 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + id="svg2" + version="1.1" + inkscape:version="0.92.2 (5c3e80d, 2017-08-06)" + sodipodi:docname="first_parent_only.svg"> + <defs + id="defs4"> + <linearGradient + id="linearGradient3861"> + <stop + style="stop-color:#caf3f6;stop-opacity:1;" + offset="0" + id="stop3863" /> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="1" + id="stop3865" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3861" + id="linearGradient3867" + x1="-11" + y1="1054.3622" + x2="-11" + y2="1029.3622" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.5,0,0,0.5,13.03125,521.1811)" /> + <linearGradient + id="linearGradient4844-4"> + <stop + id="stop4846-8" + offset="0" + style="stop-color:#414141;stop-opacity:1;" /> + <stop + id="stop4848-8" + offset="1" + style="stop-color:#535353;stop-opacity:1;" /> + </linearGradient> + <linearGradient + gradientTransform="matrix(0.47199644,0,0,0.47199414,7.4742532,550.36311)" + gradientUnits="userSpaceOnUse" + y2="1038.5814" + x2="4.7528968" + y1="1051.0466" + x1="4.7528968" + id="x-bg" + xlink:href="#x-bg-3" + inkscape:collect="always" /> + <linearGradient + id="x-bg-3" + inkscape:collect="always"> + <stop + id="x-bg-stop0" + offset="0" + style="stop-color:#df2c33;stop-opacity:1" /> + <stop + id="x-bg-stop1" + offset="1" + style="stop-color:#f5817d;stop-opacity:1" /> + </linearGradient> + <linearGradient + gradientTransform="matrix(0.47199644,0,0,0.47199414,7.4742532,550.36311)" + gradientUnits="userSpaceOnUse" + y2="1037.7" + x2="8.6566515" + y1="1050.7386" + x1="8.6566515" + id="x-stroke" + xlink:href="#x-stroke-6" + inkscape:collect="always" /> + <linearGradient + id="x-stroke-6" + inkscape:collect="always"> + <stop + id="x-stroke-stop0" + offset="0" + style="stop-color:#c51325;stop-opacity:1;" /> + <stop + id="x-stroke-stop1" + offset="1" + style="stop-color:#ca5d49;stop-opacity:1" /> + </linearGradient> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="45.254834" + inkscape:cx="4.621357" + inkscape:cy="9.1963964" + inkscape:document-units="px" + inkscape:current-layer="g6616" + showgrid="true" + inkscape:window-width="1920" + inkscape:window-height="1082" + inkscape:window-x="-4" + inkscape:window-y="-4" + inkscape:window-maximized="1" + showguides="true" + inkscape:guide-bbox="true" + inkscape:snap-global="false"> + <inkscape:grid + type="xygrid" + id="grid4000" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + style="display:inline" + transform="translate(0,-1036.3622)"> + <g + id="g6616"> + <path + style="fill:url(#linearGradient3867);fill-opacity:1;stroke:#679093;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 6.53125,1037.3622 0,4.5 -2,0 c -1,0 -2,1 -2,2 l 0,2 -2,0 0,1 3,3 3,-3 0,-1 -2,0 0,-1 c 0,-0.5 0.5,-1 1,-1 l 4,0 c 0.5,0 1,0.5 1,1 l 0,1 -2,0 0,1 3,3 3,-3 0,-1 -2,0 0,-2 c 0,-1 -1,-2 -2,-2 l -2,0 0,-4.5" + id="path3091" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccccccccccccccccccccccc" /> + <g + style="display:inline" + id="layer1-4" + inkscape:label="Layer 1" + transform="matrix(0.60535164,0,0,0.60535164,6.3760192,414.27492)" /> + <path + sodipodi:nodetypes="sccccccccssccsccsccss" + inkscape:connector-curvature="0" + id="x-0" + d="m 13.808113,1040.6023 c -0.220982,-0.2209 -0.576769,-0.2209 -0.797739,0 l -1.469229,1.4694 -1.469216,-1.4694 c -0.2209502,-0.2209 -0.5767696,-0.2209 -0.7977394,0 l -0.4059426,0.4059 c -0.2209596,0.2211 -0.2209544,0.5769 1.74e-5,0.7979 l 1.4691946,1.4692 -1.4691976,1.4691 c -0.2209914,0.221 -0.2209873,0.5768 -6.2e-6,0.7978 l 0.4059652,0.4058 c 0.2209564,0.2212 0.5767434,0.2212 0.7977376,0 l 1.46922,-1.4691 1.479428,1.4794 c 0.220958,0.2212 0.576745,0.2212 0.797739,0 l 0.405941,-0.4058 c 0.220971,-0.221 0.218752,-0.5746 -1.5e-5,-0.7977 l -1.47943,-1.4795 1.469221,-1.4692 c 0.220978,-0.221 0.220972,-0.5768 1.4e-5,-0.7979 z" + style="display:inline;fill:url(#x-bg);fill-opacity:1;stroke:url(#x-stroke);stroke-width:0.46284017;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"> + <title + id="title3202-1">x</title> + </path> + </g> + </g> +</svg> 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 15a3964dd9..e3172fb0fc 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 @@ -557,14 +557,27 @@ public class RepositoryUtil { } /** + * Relativize the given absolute path. + * <p> + * The result is the path of {@code pathString} relative to the workspace + * root if the given {@code pathString} is under the workspace root, + * otherwise the absolute path {@code pathString}. + * </p> + * <p> + * This enables moving or copying the workspace, when saving this path and + * later resolving it relative to the workspace path. + * </p> + * <p> + * It is required, that the given pathString is absolute + * </p> + * * @param pathString - * an absolute path String - * @return if the given {@code pathString} is under the workspace root the - * relative path of {@code pathString} relative to the workspace - * root, otherwise the absolute path {@code pathString}. This - * enables moving or copying the workspace. + * an absolute path String. Must be absolute. + * @return the relativized path String + * @throws java.nio.file.InvalidPathException + * if the path string cannot be converted to a Path */ - private String relativizeToWorkspace(String pathString) { + public @NonNull String relativizeToWorkspace(@NonNull String pathString) { java.nio.file.Path p = java.nio.file.Paths.get(pathString); if (p.startsWith(workspacePath)) { return workspacePath.relativize(p).toString(); @@ -574,6 +587,27 @@ public class RepositoryUtil { } /** + * Get the relativized path of the given repository. + * <p> + * If the repository is not local this method will return null. + * </p> + * + * @param repository + * The repository to get the path String of + * @return the relativized path String + * @see #relativizeToWorkspace(String) + */ + @Nullable + public String getRelativizedRepositoryPath( + final @NonNull Repository repository) { + File dir = repository.getDirectory(); + if (dir == null) { + return null; + } + return relativizeToWorkspace(dir.getAbsolutePath()); + } + + /** * Does the collection of repository returned by * {@link #getConfiguredRepositories()} contain the given repository? * diff --git a/org.eclipse.egit.ui/icons/obj16/first_parent_only.png b/org.eclipse.egit.ui/icons/obj16/first_parent_only.png Binary files differnew file mode 100644 index 0000000000..1ceb1ed3cc --- /dev/null +++ b/org.eclipse.egit.ui/icons/obj16/first_parent_only.png diff --git a/org.eclipse.egit.ui/icons/obj16/first_parent_only@2x.png b/org.eclipse.egit.ui/icons/obj16/first_parent_only@2x.png Binary files differnew file mode 100644 index 0000000000..746da3dc7b --- /dev/null +++ b/org.eclipse.egit.ui/icons/obj16/first_parent_only@2x.png diff --git a/org.eclipse.egit.ui/plugin.properties b/org.eclipse.egit.ui/plugin.properties index 22cce65ccd..3130ebb806 100644 --- a/org.eclipse.egit.ui/plugin.properties +++ b/org.eclipse.egit.ui/plugin.properties @@ -82,7 +82,7 @@ CommittingPreferencePage_keywords = git egit committing staging stage untracked StagingViewPreferencePage_keywords = git egit staging stage DialogsPreferencePage_keywords = git egit confirmation dialog configuration rebase checkout detached launch branch clone lfs fetch push log home SynchronizePreferencePage_keywords = git egit synchronize fetch commit models merge -HistoryPreferencePage_keywords = git egit history branches tags refs notes rename revision comment date author committer diff +HistoryPreferencePage_keywords = git egit history branches tags refs notes rename revision comment date author committer diff first parent HistoryColumnsPreferencePage_keywords = git egit history columns id author committer date GitActions_label=Git 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 9ef7e469bd..79208d709f 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 @@ -60,6 +60,8 @@ public class PluginPreferenceInitializer extends AbstractPreferenceInitializer { 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_FIRST_PARENT_ONLY_DEFAULT, + false); store.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_ADDITIONAL_REFS, false); store.setDefault(UIPreferences.RESOURCEHISTORY_FOLLOW_RENAMES, true); 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 cf161b712e..61b9069f6d 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,8 @@ public class UIPreferences { /** */ public final static String RESOURCEHISTORY_SHOW_ALL_BRANCHES = "resourcehistory_show_all_branches"; //$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$ /** */ public static final String RESOURCEHISTORY_FOLLOW_RENAMES = "resourcehistory_follow_renames"; //$NON-NLS-1$ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java index a217e0280f..effd4247f4 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIIcons.java @@ -268,6 +268,9 @@ public class UIIcons { /** Merge icon */ public final static ImageDescriptor MERGE; + /** First parent only icon */ + public final static ImageDescriptor FIRST_PARENT_ONLY; + /** Annotated tag icon */ public final static ImageDescriptor TAG_ANNOTATED; @@ -452,6 +455,7 @@ public class UIIcons { REBASE_PROCESS_STEPS = map("elcl16/start.png"); //$NON-NLS-1$ OVR_ERROR = map("ovr/error.png"); //$NON-NLS-1$ MERGE = map("obj16/merge.png"); //$NON-NLS-1$ + FIRST_PARENT_ONLY = map("obj16/first_parent_only.png"); //$NON-NLS-1$ TAG_ANNOTATED = map("obj16/annotated-tag.png"); //$NON-NLS-1$ CREATE_REPOSITORY = map("etool16/createRepository.png"); //$NON-NLS-1$ SUBMODULES = map("obj16/submodules.png"); //$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 4f7e617fdc..63fdde843b 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 @@ -475,6 +475,9 @@ public class UIText extends NLS { public static String GitHistoryPage_showAllBranches; /** */ + public static String GitHistoryPage_showFirstParentOnly; + + /** */ public static String GitHistoryPage_squashMenuItem; /** */ @@ -625,6 +628,9 @@ public class UIText extends NLS { public static String GitHistoryPage_ShowAllBranchesMenuLabel; /** */ + public static String GitHistoryPage_ShowFirstParentOnlyMenuLabel; + + /** */ public static String GitHistoryPage_FollowRenames; /** */ @@ -2131,6 +2137,9 @@ public class UIText extends NLS { public static String HistoryPreferencePage_toggleAllBranches; /** */ + public static String HistoryPreferencePage_showFirstParentOnlyDefault; + + /** */ public static String HistoryPreferencePage_toggleEmailAddresses; /** */ 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 d9c53516d0..1e33ac4c36 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 @@ -23,8 +23,10 @@ package org.eclipse.egit.ui.internal.history; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -87,6 +89,7 @@ import org.eclipse.jface.bindings.keys.SWTKeySupport; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.preference.IPersistentPreferenceStore; +import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.JFaceResources; @@ -189,6 +192,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, private static final int INITIAL_ITEM = -1; + private static final String P_REPOSITORY = "GitHistoryPage.Repository"; //$NON-NLS-1$ + /** actions used in GitHistoryPage **/ private static class GitHistoryPageActions { @@ -206,12 +211,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, @Override public void run() { historyPage.store.setValue(prefName, isChecked()); - if (historyPage.store.needsSaving()) - try { - historyPage.store.save(); - } catch (IOException e) { - Activator.handleError(e.getMessage(), e, false); - } + historyPage.saveStoreIfNeeded(); } abstract void apply(boolean value); @@ -319,6 +319,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, IWorkbenchAction showAllBranchesAction; + IWorkbenchAction showFirstParentOnlyAction; + IWorkbenchAction showAdditionalRefsAction; BooleanPrefAction followRenamesAction; @@ -356,6 +358,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, createCompareModeAction(); createReuseCompareEditorAction(); createShowAllBranchesAction(); + createShowFirstParentOnlyAction(); createShowAdditionalRefsAction(); createShowCommentAction(); createShowFilesAction(); @@ -374,9 +377,9 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, private void createRepositorySwitchAction() { switchRepositoryAction = new RepositoryToolbarAction(true, - () -> historyPage.currentRepo, + () -> historyPage.getCurrentRepo(), repo -> { - Repository current = historyPage.currentRepo; + Repository current = historyPage.getCurrentRepo(); if (current != null && repo.getDirectory() .equals(current.getDirectory())) { HistoryPageInput currentInput = historyPage @@ -406,13 +409,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, historyPage.store.setValue( UIPreferences.RESOURCEHISTORY_SHOW_FINDTOOLBAR, isChecked()); - if (historyPage.store.needsSaving()) { - try { - historyPage.store.save(); - } catch (IOException e) { - Activator.handleError(e.getMessage(), e, false); - } - } + historyPage.saveStoreIfNeeded(); historyPage.searchBar.setVisible(isChecked()); } @@ -520,6 +517,100 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, actionsToDispose.add(showAllBranchesAction); } + private class ShowFirstParentOnlyPrefAction extends Action + implements IPropertyChangeListener, IWorkbenchAction { + + ShowFirstParentOnlyPrefAction() { + super(UIText.GitHistoryPage_ShowFirstParentOnlyMenuLabel); + historyPage.addPropertyChangeListener(this); + historyPage.store.addPropertyChangeListener(this); + setChecked(historyPage.isShowFirstParentOnly()); + setImageDescriptor(UIIcons.FIRST_PARENT_ONLY); + setToolTipText(UIText.GitHistoryPage_showFirstParentOnly); + } + + @Override + public void run() { + final String prefKey = UIPreferences.RESOURCEHISTORY_SHOW_FIRST_PARENT_ONLY_DEFAULT; + Repository repo = historyPage.getCurrentRepo(); + if (repo != null) { + String repoSpecificKey = getRepoSpecificKey(repo, prefKey); + boolean newBoolean = isChecked(); + if (newBoolean == historyPage.store.getBoolean(prefKey)) { + historyPage.store.setToDefault(repoSpecificKey); + } else { + String newValue = newBoolean ? IPreferenceStore.TRUE + : IPreferenceStore.FALSE; + historyPage.store.putValue(repoSpecificKey, newValue); + } + + historyPage.saveStoreIfNeeded(); + } + historyPage.refresh(); + } + + /** + * Applies the new boolean state to the checkbox and refreshes the + * historyPage if the state was changed. + * + * @param newState + * the new state to apply. + */ + private void applyNewState(boolean newState) { + Control control = historyPage.getControl(); + if (control != null && !control.isDisposed()) { + control.getDisplay().asyncExec(() -> { + if (!control.isDisposed()) { + setChecked(newState); + } + }); + } + historyPage.refresh(); + } + + @Override + public void propertyChange(PropertyChangeEvent event) { + Repository repo = historyPage.getCurrentRepo(); + + final String prefKey = UIPreferences.RESOURCEHISTORY_SHOW_FIRST_PARENT_ONLY_DEFAULT; + + if (repo == null) { + if (prefKey.equals(event.getProperty())) { + // global first parent preference changed and we have no + // current repo. Apply the new global preference + applyNewState(historyPage.store.getBoolean(prefKey)); + } + return; + } + + String repoSpecificKey = getRepoSpecificKey(repo, prefKey); + + if (prefKey.equals(event.getProperty())) { + // global first parent preference changed, if this repo does + // not have a repo specific one apply the global one + if (!historyPage.store.contains(repoSpecificKey)) { + applyNewState(historyPage.store.getBoolean(prefKey)); + } + } + + if (P_REPOSITORY.equals(event.getProperty())) { + // The repository was switched. Apply that correct state. + applyNewState(historyPage.isShowFirstParentOnly()); + } + } + + @Override + public void dispose() { + historyPage.removePropertyChangeListener(this); + historyPage.store.removePropertyChangeListener(this); + } + } + + private void createShowFirstParentOnlyAction() { + showFirstParentOnlyAction = new ShowFirstParentOnlyPrefAction(); + actionsToDispose.add(showFirstParentOnlyAction); + } + private void createShowAdditionalRefsAction() { showAdditionalRefsAction = new BooleanPrefAction( UIPreferences.RESOURCEHISTORY_SHOW_ADDITIONAL_REFS, @@ -818,6 +909,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, private boolean currentShowAllBranches; + private boolean currentShowFirstParentOnly; + private boolean currentShowAdditionalRefs; private boolean currentShowNotes; @@ -860,6 +953,29 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, }); } } + + Object oldValue = event.getOldValue(); + String pathSep = File.pathSeparator; + + if (oldValue != null) { + String[] oldPaths = oldValue.toString().split(pathSep); + List<String> removedPaths = new ArrayList<>( + Arrays.asList(oldPaths)); + + Object newValue = event.getNewValue(); + if (newValue != null) { + String[] newPaths = newValue.toString().split(pathSep); + for (String path : newPaths) { + removedPaths.remove(path); + } + } + + for (String path : removedPaths) { + unsetRepoSpecificPreference(path, + UIPreferences.RESOURCEHISTORY_SHOW_FIRST_PARENT_ONLY_DEFAULT); + } + saveStoreIfNeeded(); + } }; /** Tracks the selection to display the correct input when linked with editors. */ @@ -1425,12 +1541,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, public void widgetDisposed(DisposeEvent e) { final int[] w = sf.getWeights(); store.putValue(key, UIPreferences.intArrayToString(w)); - if (store.needsSaving()) - try { - store.save(); - } catch (IOException e1) { - Activator.handleError(e1.getMessage(), e1, false); - } + saveStoreIfNeeded(); } }); @@ -1572,6 +1683,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, mgr.add(new Separator()); mgr.add(actions.compareModeAction); mgr.add(actions.showAllBranchesAction); + mgr.add(actions.showFirstParentOnlyAction); } private class ColumnAction extends Action implements IUpdate { @@ -1618,6 +1730,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, UIText.GitHistoryPage_ShowSubMenuLabel); viewMenuMgr.add(showSubMenuMgr); showSubMenuMgr.add(actions.showAllBranchesAction); + showSubMenuMgr.add(actions.showFirstParentOnlyAction); showSubMenuMgr.add(actions.showAdditionalRefsAction); showSubMenuMgr.add(actions.showNotesAction); showSubMenuMgr.add(actions.followRenamesAction); @@ -1693,14 +1806,14 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, } renameTracker.reset(null); Job.getJobManager().cancel(JobFamilies.HISTORY_DIFF); - currentRepo = null; + setCurrentRepo(null); selectedObj = null; super.dispose(); } @Override public void setFocus() { - if (repoHasBeenRemoved(currentRepo)) { + if (repoHasBeenRemoved(getCurrentRepo())) { clearHistoryPage(); graph.getControl().setFocus(); } else { @@ -1718,7 +1831,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, } private void clearHistoryPage() { - currentRepo = null; + setCurrentRepo(null); selectedObj = null; name = ""; //$NON-NLS-1$ input = null; @@ -1741,7 +1854,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, @Override public void refresh() { - if (repoHasBeenRemoved(currentRepo)) { + if (repoHasBeenRemoved(getCurrentRepo())) { clearHistoryPage(); } this.input = null; @@ -2243,6 +2356,19 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, return getInputInternal(); } + private Repository getCurrentRepo() { + return currentRepo; + } + + private void setCurrentRepo(Repository newRepo) { + Repository old = getCurrentRepo(); + this.currentRepo = newRepo; + + if (!Objects.equals(old, newRepo)) { + this.firePropertyChange(this, P_REPOSITORY, old, newRepo); + } + } + void setWarningTextInUIThread(final Job j) { graph.getControl().getDisplay().asyncExec(new Runnable() { @Override @@ -2356,7 +2482,7 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, currentHeadId = null; currentFetchHeadId = null; selectedObj = null; - currentRepo = db; + setCurrentRepo(db); clearViewers(); return; } @@ -2366,9 +2492,9 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, .getFileList(), db); boolean repoChanged = false; - if (!db.equals(currentRepo)) { + if (!db.equals(getCurrentRepo())) { repoChanged = true; - currentRepo = db; + setCurrentRepo(db); } boolean objChanged = false; @@ -2417,6 +2543,10 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, currentShowAllBranches = store .getBoolean(UIPreferences.RESOURCEHISTORY_SHOW_ALL_BRANCHES); + boolean isShowFirstParentOnly = isShowFirstParentOnly(); + boolean firstParentOnlyChanged = currentShowFirstParentOnly != isShowFirstParentOnly; + currentShowFirstParentOnly = isShowFirstParentOnly; + boolean additionalRefsChange = currentShowAdditionalRefs != store .getBoolean(UIPreferences.RESOURCEHISTORY_SHOW_ADDITIONAL_REFS); currentShowAdditionalRefs = store @@ -2433,8 +2563,9 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, currentFollowRenames = getFollowRenames(); return pathChanged || headChanged || fetchHeadChanged - || allBranchesChanged || additionalRefsChange - || showNotesChanged || followRenamesChanged; + || allBranchesChanged || firstParentOnlyChanged + || additionalRefsChange || showNotesChanged + || followRenamesChanged; } /** @@ -2550,11 +2681,76 @@ 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. + * <p> + * This method does not save the preference store. Call + * {@link #saveStoreIfNeeded()} when appropriate. + * </p> + * + * @param repositoryPath + * Representing the repository to remove the preference for + * @param key + * The preference to remove for the given repository. + */ + private void unsetRepoSpecificPreference(String repositoryPath, + String key) { + String prefString = getRepoSpecificKey(repositoryPath, key); + store.setToDefault(prefString); + } + + private void saveStoreIfNeeded() { + if (store.needsSaving()) { + try { + store.save(); + } catch (IOException e) { + Activator.handleError(e.getMessage(), e, false); + } + } + } + + private boolean isShowFirstParentOnly() { + final String prefKey = UIPreferences.RESOURCEHISTORY_SHOW_FIRST_PARENT_ONLY_DEFAULT; + boolean firstParent = store.getBoolean(prefKey); + Repository repo = getCurrentRepo(); + + if (repo != null) { + String repoSpecificKey = getRepoSpecificKey(repo, prefKey); + if (store.contains(repoSpecificKey)) { + firstParent = store.getBoolean(repoSpecificKey); + } + } + return firstParent; + } + private @NonNull SWTWalk createNewWalk(Repository db, AnyObjectId headId, AnyObjectId fetchHeadId) { currentHeadId = headId; currentFetchHeadId = fetchHeadId; SWTWalk walk = new GitHistoryWalk(db, headId, selectedObj); + + if (isShowFirstParentOnly()) { + walk.setFirstParent(true); + } + try { if (store .getBoolean(UIPreferences.RESOURCEHISTORY_SHOW_ADDITIONAL_REFS)) @@ -2731,7 +2927,8 @@ public class GitHistoryPage extends HistoryPage implements RefsChangedListener, if (paths == null || paths.isEmpty()) throw new IllegalArgumentException("paths must not be null nor empty"); //$NON-NLS-1$ - DiffConfig diffConfig = currentRepo.getConfig().get(DiffConfig.KEY); + DiffConfig diffConfig = getCurrentRepo().getConfig() + .get(DiffConfig.KEY); List<TreeFilter> followFilters = new ArrayList<>(paths.size()); for (String path : paths) diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/HistoryPreferencePage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/HistoryPreferencePage.java index 8c03996452..f02c06ff54 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/HistoryPreferencePage.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/HistoryPreferencePage.java @@ -63,6 +63,10 @@ public class HistoryPreferencePage extends FieldEditorPreferencePage implements UIPreferences.RESOURCEHISTORY_SHOW_ALL_BRANCHES, UIText.HistoryPreferencePage_toggleAllBranches, showGroup)); addField(new BooleanFieldEditor( + UIPreferences.RESOURCEHISTORY_SHOW_FIRST_PARENT_ONLY_DEFAULT, + UIText.HistoryPreferencePage_showFirstParentOnlyDefault, + showGroup)); + addField(new BooleanFieldEditor( UIPreferences.RESOURCEHISTORY_SHOW_ADDITIONAL_REFS, UIText.HistoryPreferencePage_toggleAdditionalRefs, showGroup)); addField(new BooleanFieldEditor( 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 857bcfee2c..48cb05abc1 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 @@ -187,6 +187,7 @@ GitHistoryPage_CreateTagMenuLabel=Create &Tag... GitHistoryPage_cherryPickMenuItem=C&herry-Pick... GitHistoryPage_compareMode=Compare Mode GitHistoryPage_showAllBranches=Show All Branches and Tags +GitHistoryPage_showFirstParentOnly=Show First Parent Only GitHistoryPage_squashMenuItem=Squash GitHistoryPage_errorLookingUpPath=IO error looking up path {0} in {1}. GitHistoryPage_errorParsingHead=Cannot parse HEAD in: {0} @@ -227,6 +228,7 @@ GitHistoryPage_editMenuItem=&Edit GitHistoryPage_SetAsBaselineMenuLabel=&Set as Baseline GitHistoryPage_ShowAdditionalRefsMenuLabel=&Additional Refs GitHistoryPage_ShowAllBranchesMenuLabel=All &Branches and Tags +GitHistoryPage_ShowFirstParentOnlyMenuLabel=First &Parent Only GitHistoryPage_FollowRenames=&Follow Renames GitHistoryPage_FormatDiffJobName=Updating Diff GitHistoryPage_FilterSubMenuLabel=&Filter @@ -729,6 +731,7 @@ HistoryPage_findbar_exceeded=Results limit exceeded HistoryPage_findbar_notFound=String not found HistoryPage_findbar_reference=Branch/Tag HistoryPreferencePage_toggleAllBranches=All &Branches and Tags +HistoryPreferencePage_showFirstParentOnlyDefault=F&irst parent only by default HistoryPreferencePage_toggleAdditionalRefs=&Additional Refs HistoryPreferencePage_toggleEmailAddresses=&E-mail addresses in Author/Committer columns HistoryPreferencePage_toggleShortenAtStart=&Shorten long tag and branch names at the front |