Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMickael Istria2016-01-08 13:28:03 +0000
committerThomas Wolf2016-02-13 12:13:06 +0000
commitc6a421bcccd8b07382af86e00781f03e2118c00b (patch)
tree4b2de0dcac4946cdadde22ff514d06c7f4afea96 /org.eclipse.egit.ui
parent292099f2d5bfbd6acff3ef4de981220ca285323c (diff)
downloadegit-c6a421bcccd8b07382af86e00781f03e2118c00b.tar.gz
egit-c6a421bcccd8b07382af86e00781f03e2118c00b.tar.xz
egit-c6a421bcccd8b07382af86e00781f03e2118c00b.zip
Wizard to configure pull operation
This is accessible on project's context menu, as "Pull..." just below "Pull". The wizard enables the user to specify the remote or add a new one, and also to specify the remote reference. There is content assist for published remote references, but the user may also pull from non-published remote refs, such as pull requests on Github or patch sets in Gerrit. Bug: 485124 Change-Id: I88122d3fedf10de35a0c1c233b7dd9920bb8c0c7 Signed-off-by: Mickael Istria <mistria@redhat.com> Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
Diffstat (limited to 'org.eclipse.egit.ui')
-rw-r--r--org.eclipse.egit.ui/icons/obj16/pull_with_options.pngbin0 -> 652 bytes
-rw-r--r--org.eclipse.egit.ui/plugin.properties2
-rw-r--r--org.eclipse.egit.ui/plugin.xml85
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/UIText.java18
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ActionCommands.java3
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PullWithOptionsAction.java28
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PullWithOptionsActionHandler.java41
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullOperationUI.java16
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullWizard.java145
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullWizardPage.java454
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/AddRemoteWizard.java5
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/uitext.properties6
12 files changed, 802 insertions, 1 deletions
diff --git a/org.eclipse.egit.ui/icons/obj16/pull_with_options.png b/org.eclipse.egit.ui/icons/obj16/pull_with_options.png
new file mode 100644
index 0000000000..264559c997
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/obj16/pull_with_options.png
Binary files differ
diff --git a/org.eclipse.egit.ui/plugin.properties b/org.eclipse.egit.ui/plugin.properties
index bb194a87b3..0eb5319c95 100644
--- a/org.eclipse.egit.ui/plugin.properties
+++ b/org.eclipse.egit.ui/plugin.properties
@@ -272,6 +272,8 @@ RepoViewHierarchicalBranchRepresenation.tooltip = Hierarchical Branch Layout
RepoViewBranchCommit.tooltip = Display Latest Branch Commit
ConfigureTraceCommand.name = Configure Git Debug Trace
PullIntoCurrentBranchMenuLabel = P&ull
+PullWithOptions.name=Pull...
+PullWithOptions.tooltip=Specify remote and reference for a pull operation and run it
CherryPickCommand.name = Cherry Pick
SquashCommitsCommand.name = Squash Commits
RewordCommitCommand.name = Reword Commit
diff --git a/org.eclipse.egit.ui/plugin.xml b/org.eclipse.egit.ui/plugin.xml
index cd6f19414f..da37e720be 100644
--- a/org.eclipse.egit.ui/plugin.xml
+++ b/org.eclipse.egit.ui/plugin.xml
@@ -790,6 +790,17 @@
toolbarPath="org.eclipse.egit.ui"
tooltip="%PullIntoCurrentBranch.tooltip">
</action>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.PullWithOptionsAction"
+ definitionId="org.eclipse.egit.ui.team.PullWithOptions"
+ icon="icons/obj16/pull_with_options.png"
+ id="org.eclipse.egit.ui.actionpullwithoptions"
+ label="%PullWithOptions.name"
+ menubarPath="org.eclipse.egit.ui.gitmenu/repo"
+ style="push"
+ toolbarPath="org.eclipse.egit.ui"
+ tooltip="%PullWithOptions.tooltip">
+ </action>
<action
class="org.eclipse.egit.ui.internal.actions.SimpleFetchAction"
definitionId="org.eclipse.egit.ui.team.SimpleFetch"
@@ -942,6 +953,11 @@
</command>
<command
categoryId="org.eclipse.egit.ui.commandCategory"
+ id="org.eclipse.egit.ui.team.PullWithOptions"
+ name="%PullWithOptions.name">
+ </command>
+ <command
+ categoryId="org.eclipse.egit.ui.commandCategory"
id="org.eclipse.egit.ui.team.Fetch"
name="%FetchCommand.name">
</command>
@@ -1196,6 +1212,36 @@
</activeWhen>
</handler>
<handler
+ commandId="org.eclipse.egit.ui.team.PullWithOptions">
+ <class
+ class="org.eclipse.egit.ui.internal.actions.PullWithOptionsActionHandler">
+ </class>
+ <activeWhen>
+ <or>
+ <reference
+ definitionId="org.eclipse.egit.ui.resourcesSingleRepository">
+ </reference>
+ <and>
+ <count
+ value="1">
+ </count>
+ <iterate>
+ <and>
+ <instanceof
+ value="org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode">
+ </instanceof>
+ <not>
+ <test
+ property="GitRepository.isBare">
+ </test>
+ </not>
+ </and>
+ </iterate>
+ </and>
+ </or>
+ </activeWhen>
+ </handler>
+ <handler
commandId="org.eclipse.egit.ui.team.Fetch">
<class
class="org.eclipse.egit.ui.internal.repository.tree.command.FetchCommand">
@@ -3147,6 +3193,30 @@
</and>
</visibleWhen>
</command>
+ <command
+ commandId="org.eclipse.egit.ui.team.PullWithOptions"
+ icon="icons/obj16/pull.png"
+ label="%PullWithOptions.name"
+ style="push">
+ <visibleWhen
+ checkEnabled="false">
+ <and>
+ <count
+ value="1">
+ </count>
+ <iterate>
+ <and>
+ <instanceof
+ value="org.eclipse.egit.ui.internal.repository.tree.RepositoryNode">
+ </instanceof>
+ <test
+ property="GitRepository.canMerge">
+ </test>
+ </and>
+ </iterate>
+ </and>
+ </visibleWhen>
+ </command>
<menu
label="%RemoteSubMenu.label">
<command
@@ -3873,6 +3943,17 @@
</test>
</visibleWhen>
</command>
+ <command
+ commandId="org.eclipse.egit.ui.team.PullWithOptions"
+ label="%PullWithOptions.name"
+ style="push">
+ <visibleWhen
+ checkEnabled="false">
+ <test
+ property="GitSelection.projectsSingleRepository">
+ </test>
+ </visibleWhen>
+ </command>
<separator
name="org.eclipse.egit.ui.remoteSeparator"
visible="true">
@@ -5140,6 +5221,10 @@
icon="icons/obj16/pull.png">
</image>
<image
+ commandId="org.eclipse.egit.ui.team.PullWithOptions"
+ icon="icons/obj16/pull.png">
+ </image>
+ <image
commandId="org.eclipse.egit.ui.team.Reset"
icon="icons/obj16/reset.gif">
</image>
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 be2d9e64b4..f728a484fb 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
@@ -2040,6 +2040,24 @@ public class UIText extends NLS {
public static String HistoryPreferencePage_toggleEmailAddresses;
/** */
+ public static String PullWizardPage_PageName;
+
+ /** */
+ public static String PullWizardPage_PageTitle;
+
+ /** */
+ public static String PullWizardPage_PageMessage;
+
+ /** */
+ public static String PullWizardPage_referenceLabel;
+
+ /** */
+ public static String PullWizardPage_referenceTooltip;
+
+ /** */
+ public static String PullWizardPage_ChooseReference;
+
+ /** */
public static String PullOperationUI_ConnectionProblem;
/** */
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ActionCommands.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ActionCommands.java
index fb5ff006b1..41b650d9f4 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ActionCommands.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ActionCommands.java
@@ -128,6 +128,9 @@ public class ActionCommands {
/** "Pull from upstream configuration" action command id */
public static final String PULL_FROM_UPSTREAM_CONFIG = "org.eclipse.egit.ui.team.PullFromUpstreamConfig"; //$NON-NLS-1$
+ /** "Pull with a config dialog" action command id */
+ public static final String PULL_WITH_OPTIONS = "org.eclipse.egit.ui.team.PullWithOptions"; //$NON-NLS-1$
+
/** "Merge Tool" action command id */
public static final String MERGE_TOOL_ACTION = "org.eclipse.egit.ui.team.MergeTool"; //$NON-NLS-1$
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PullWithOptionsAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PullWithOptionsAction.java
new file mode 100644
index 0000000000..60ac938ecb
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PullWithOptionsAction.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2016, Red Hat Inc. and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Mickael Istria (Red Hat Inc.) - [485124] initial implementation
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.actions;
+
+/**
+ * An action for asking user to specify a pull operation (via wizard) and run it
+ *
+ * @see PullWithOptionsActionHandler
+ */
+public class PullWithOptionsAction extends RepositoryAction {
+
+ /**
+ *
+ */
+ public PullWithOptionsAction() {
+ super(ActionCommands.PULL_WITH_OPTIONS,
+ new PullWithOptionsActionHandler());
+ }
+
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PullWithOptionsActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PullWithOptionsActionHandler.java
new file mode 100644
index 0000000000..1fc9562b6b
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PullWithOptionsActionHandler.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2016, Red Hat Inc. and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Mickael Istria (Red Hat Inc.) - [485124] initial implementation
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.actions;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.egit.ui.internal.pull.PullWizard;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * A handler action for asking user to specify a pull operation (via wizard) and
+ * run it
+ *
+ * @see PullWithOptionsAction
+ */
+public class PullWithOptionsActionHandler extends RepositoryActionHandler {
+
+ @Override
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ Repository repo = getRepository();
+ WizardDialog dialog = new WizardDialog(getShell(event),
+ new PullWizard(repo));
+ dialog.open();
+ return null;
+
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return getRepository() != null;
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullOperationUI.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullOperationUI.java
index ac645a2507..ca36e0d2e4 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullOperationUI.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullOperationUI.java
@@ -32,6 +32,7 @@ import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.egit.core.internal.job.RuleUtil;
import org.eclipse.egit.core.op.PullOperation;
+import org.eclipse.egit.core.op.PullOperation.PullReferenceConfig;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.JobFamilies;
import org.eclipse.egit.ui.UIPreferences;
@@ -85,6 +86,21 @@ public class PullOperationUI extends JobChangeAdapter {
}
/**
+ * @param configs
+ */
+ public PullOperationUI(Map<Repository, PullReferenceConfig> configs) {
+ this.repositories = configs.keySet()
+ .toArray(new Repository[configs.size()]);
+ int timeout = Activator.getDefault().getPreferenceStore()
+ .getInt(UIPreferences.REMOTE_CONNECTION_TIMEOUT);
+ pullOperation = new PullOperation(configs, timeout);
+ pullOperation.setCredentialsProvider(new EGitCredentialsProvider());
+ for (Repository repository : repositories) {
+ results.put(repository, NOT_TRIED_STATUS);
+ }
+ }
+
+ /**
* Starts this operation asynchronously
*/
public void start() {
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullWizard.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullWizard.java
new file mode 100644
index 0000000000..cf490ebf91
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullWizard.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Red Hat Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.pull;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.egit.core.op.PullOperation.PullReferenceConfig;
+import org.eclipse.egit.ui.Activator;
+import org.eclipse.egit.ui.internal.SecureStoreUtils;
+import org.eclipse.egit.ui.internal.UIText;
+import org.eclipse.egit.ui.internal.push.AddRemotePage;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.transport.RemoteConfig;
+import org.eclipse.jgit.transport.URIish;
+
+/**
+ * A wizard to allow to specify a pull operation with options
+ */
+public class PullWizard extends Wizard {
+
+ private final Repository repository;
+
+ private PullWizardPage page;
+ private AddRemotePage addRemotePage;
+
+ /**
+ * @param repo
+ * the repository
+ */
+ public PullWizard(final Repository repo) {
+ this.repository = repo;
+ setWindowTitle(UIText.PullWizardPage_PageTitle);
+ }
+
+ @Override
+ public void addPages() {
+ Set<String> remoteNames = repository.getConfig()
+ .getSubsections(ConfigConstants.CONFIG_REMOTE_SECTION);
+ if (remoteNames.isEmpty()) {
+ this.addRemotePage = new AddRemotePage(repository);
+ addPage(this.addRemotePage);
+ }
+ this.page = new PullWizardPage(this.repository);
+ addPage(this.page);
+ }
+
+ @Override
+ public boolean performFinish() {
+ try {
+ if (this.addRemotePage != null) {
+ storeCredentials(this.addRemotePage);
+ URIish uri = this.addRemotePage.getSelection().getURI();
+ configureNewRemote(uri);
+ }
+ if (this.page.overrideUpstreamConfiguration()) {
+ configureUpstream();
+ }
+ startPull();
+ return true;
+ } catch (IOException e) {
+ Activator.logError(e.getMessage(), e);
+ return false;
+ } catch (URISyntaxException e) {
+ Activator.logError(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ private void storeCredentials(AddRemotePage remotePage) {
+ if (remotePage.getStoreInSecureStore()) {
+ URIish uri = remotePage.getSelection().getURI();
+ if (uri != null) {
+ SecureStoreUtils.storeCredentials(remotePage.getCredentials(),
+ uri);
+ }
+ }
+ }
+
+ private void configureNewRemote(URIish uri)
+ throws URISyntaxException, IOException {
+ StoredConfig config = repository.getConfig();
+ String remoteName = this.page.getRemoteConfig().getName();
+ RemoteConfig remoteConfig = new RemoteConfig(config, remoteName);
+ remoteConfig.addURI(uri);
+ RefSpec defaultFetchSpec = new RefSpec().setForceUpdate(true)
+ .setSourceDestination(Constants.R_HEADS + "*", //$NON-NLS-1$
+ Constants.R_REMOTES + remoteName + "/*"); //$NON-NLS-1$
+ remoteConfig.addFetchRefSpec(defaultFetchSpec);
+ remoteConfig.update(config);
+ config.save();
+ }
+
+ private void configureUpstream() throws IOException {
+ String fullBranch = this.repository.getFullBranch();
+ if (fullBranch == null || !fullBranch.startsWith(Constants.R_HEADS)) {
+ // Don't configure upstream for detached HEAD
+ return;
+ }
+ String remoteName = this.page.getRemoteConfig().getName();
+ String fullRemoteBranchName = this.page.getFullRemoteReference();
+
+ String localBranchName = this.repository.getBranch();
+ StoredConfig config = repository.getConfig();
+ config.setString(ConfigConstants.CONFIG_BRANCH_SECTION, localBranchName,
+ ConfigConstants.CONFIG_KEY_REMOTE, remoteName);
+ config.setString(ConfigConstants.CONFIG_BRANCH_SECTION, localBranchName,
+ ConfigConstants.CONFIG_KEY_MERGE, fullRemoteBranchName);
+ if (this.page.isRebaseSelected()) {
+ config.setBoolean(ConfigConstants.CONFIG_BRANCH_SECTION,
+ localBranchName, ConfigConstants.CONFIG_KEY_REBASE, true);
+ } else {
+ // Make sure we overwrite any previous configuration
+ config.unset(ConfigConstants.CONFIG_BRANCH_SECTION, localBranchName,
+ ConfigConstants.CONFIG_KEY_REBASE);
+ }
+
+ config.save();
+ }
+
+ private void startPull() {
+ Map<Repository, PullReferenceConfig> repos = new HashMap<>(1);
+ PullReferenceConfig config = new PullReferenceConfig(
+ this.page.getRemoteConfig().getName(),
+ this.page.getFullRemoteReference(),
+ this.page.getUpstreamConfig());
+ repos.put(this.repository, config);
+ PullOperationUI pullOperationUI = new PullOperationUI(repos);
+ pullOperationUI.start();
+ }
+
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullWizardPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullWizardPage.java
new file mode 100644
index 0000000000..25d0c62933
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/pull/PullWizardPage.java
@@ -0,0 +1,454 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Red Hat Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.pull;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.eclipse.egit.core.op.CreateLocalBranchOperation.UpstreamConfig;
+import org.eclipse.egit.ui.Activator;
+import org.eclipse.egit.ui.UIUtils;
+import org.eclipse.egit.ui.UIUtils.IRefListProvider;
+import org.eclipse.egit.ui.internal.UIIcons;
+import org.eclipse.egit.ui.internal.UIText;
+import org.eclipse.egit.ui.internal.components.RefContentAssistProvider;
+import org.eclipse.egit.ui.internal.components.RemoteSelectionCombo;
+import org.eclipse.egit.ui.internal.components.RemoteSelectionCombo.IRemoteSelectionListener;
+import org.eclipse.egit.ui.internal.components.RemoteSelectionCombo.SelectionType;
+import org.eclipse.egit.ui.internal.push.AddRemoteWizard;
+import org.eclipse.egit.ui.internal.push.PushBranchPage;
+import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.fieldassist.ControlDecoration;
+import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.jgit.lib.BranchConfig;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.transport.RemoteConfig;
+import org.eclipse.jgit.transport.URIish;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+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.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * This Wizard Page allows to configure a Push operation (remote, reference,
+ * rebase/merge)
+ *
+ * It is heavily inspired/copy-pasted from the {@link PushBranchPage} and a lot
+ * of code could be factorized.
+ */
+public class PullWizardPage extends WizardPage {
+
+ private RemoteSelectionCombo remoteSelectionCombo;
+
+ private List<RemoteConfig> remoteConfigs;
+ private RemoteConfig remoteConfig;
+
+ private RefContentAssistProvider assist;
+
+ private Repository repository;
+
+ private String fullBranch;
+
+ private Button mergeRadio;
+
+ private Button rebaseRadio;
+
+ private Button rememberConfigForBranch;
+
+ private UpstreamConfig upstreamConfig;
+
+ private Ref head;
+
+ private Text remoteBranchNameText;
+
+ private ControlDecoration missingBranchDecorator;
+
+ private boolean configureUpstream;
+
+ /**
+ * Create the page.
+ *
+ * @param repository
+ */
+ public PullWizardPage(Repository repository) {
+ super(UIText.PullWizardPage_PageName);
+ setTitle(UIText.PullWizardPage_PageTitle);
+ setMessage(UIText.PullWizardPage_PageMessage);
+ setImageDescriptor(UIIcons.WIZBAN_PULL);
+ this.repository = repository;
+ try {
+ this.head = repository.findRef(Constants.HEAD);
+ this.fullBranch = repository.getFullBranch();
+ } catch (IOException ex) {
+ Activator.logError(ex.getMessage(), ex);
+ }
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ try {
+ this.remoteConfigs = RemoteConfig
+ .getAllRemoteConfigs(repository.getConfig());
+ Collections.sort(remoteConfigs, new Comparator<RemoteConfig>() {
+ @Override
+ public int compare(RemoteConfig first, RemoteConfig second) {
+ return String.CASE_INSENSITIVE_ORDER
+ .compare(first.getName(), second.getName());
+ }
+ });
+ setDefaultUpstreamConfig();
+ } catch (URISyntaxException e) {
+ this.remoteConfigs = new ArrayList<RemoteConfig>();
+ handleError(e);
+ }
+
+ Composite res = new Composite(parent, SWT.NONE);
+ res.setLayout(new GridLayout(3, false));
+
+ Label remoteLabel = new Label(res, SWT.NONE);
+ remoteLabel.setText(UIText.PushBranchPage_RemoteLabel);
+
+ this.remoteSelectionCombo = new RemoteSelectionCombo(
+ res, SWT.NONE, SelectionType.PUSH);
+ GridDataFactory.fillDefaults().grab(true, false)
+ .applyTo(remoteSelectionCombo);
+ setRemoteConfigs();
+ remoteSelectionCombo
+ .addRemoteSelectionListener(new IRemoteSelectionListener() {
+ @Override
+ public void remoteSelected(RemoteConfig rc) {
+ remoteConfig = rc;
+ setRefAssist(rc);
+ checkPage();
+ }
+ });
+
+ Button newRemoteButton = new Button(res, SWT.PUSH);
+ newRemoteButton.setText(UIText.PushBranchPage_NewRemoteButton);
+ GridDataFactory.fillDefaults().applyTo(newRemoteButton);
+ newRemoteButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ showNewRemoteDialog();
+ }
+ });
+
+ Label branchNameLabel = new Label(res, SWT.NONE);
+ branchNameLabel.setText(UIText.PullWizardPage_referenceLabel);
+ branchNameLabel.setToolTipText(UIText.PullWizardPage_referenceTooltip);
+
+ remoteBranchNameText = new Text(res, SWT.BORDER);
+ GridDataFactory.fillDefaults().grab(true, false).span(2, 1)
+ .applyTo(remoteBranchNameText);
+ UIUtils.addRefContentProposalToText(remoteBranchNameText,
+ this.repository, new IRefListProvider() {
+
+ @Override
+ public List<Ref> getRefList() {
+ if (PullWizardPage.this.assist != null) {
+ return PullWizardPage.this.assist
+ .getRefsForContentAssist(false, true);
+ }
+ return Collections.emptyList();
+ }
+ });
+ remoteBranchNameText.setText(getSuggestedBranchName());
+ remoteBranchNameText.addModifyListener(new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ checkPage();
+ }
+ });
+
+ this.mergeRadio = new Button(res, SWT.RADIO);
+ this.mergeRadio.setText(UIText.UpstreamConfigComponent_MergeRadio);
+ this.mergeRadio.setLayoutData(
+ new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 3, 1));
+ this.mergeRadio.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ upstreamConfig = UpstreamConfig.MERGE;
+ }
+ });
+ this.rebaseRadio = new Button(res, SWT.RADIO);
+ this.rebaseRadio.setText(UIText.UpstreamConfigComponent_RebaseRadio);
+ this.rebaseRadio.setLayoutData(
+ new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 3, 1));
+ this.mergeRadio.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ upstreamConfig = UpstreamConfig.REBASE;
+ }
+ });
+ this.mergeRadio
+ .setSelection(this.upstreamConfig == UpstreamConfig.MERGE);
+ this.rebaseRadio
+ .setSelection(this.upstreamConfig == UpstreamConfig.REBASE);
+ if (this.fullBranch != null
+ && this.fullBranch.startsWith(Constants.R_HEADS)) {
+ this.rememberConfigForBranch = new Button(res, SWT.CHECK);
+ GridData checkboxLayoutData = new GridData(SWT.BEGINNING,
+ SWT.CENTER, false, false, 3, 1);
+ checkboxLayoutData.verticalIndent = 20;
+ this.rememberConfigForBranch.setText(
+ UIText.UpstreamConfigComponent_ConfigureUpstreamCheck);
+ this.rememberConfigForBranch.setToolTipText(
+ UIText.UpstreamConfigComponent_ConfigureUpstreamToolTip);
+ this.rememberConfigForBranch.setLayoutData(checkboxLayoutData);
+ this.rememberConfigForBranch.setSelection(this.configureUpstream);
+ this.rememberConfigForBranch
+ .addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ configureUpstream = rememberConfigForBranch
+ .getSelection();
+ checkPage();
+ }
+ });
+ }
+
+ setPageComplete(isPageComplete());
+ setControl(res);
+ }
+
+ private void setRemoteConfigs() {
+ remoteSelectionCombo.setItems(remoteConfigs);
+ if (this.head != null) {
+ String branchName = Repository.shortenRefName(this.head.getName());
+ BranchConfig branchConfig = new BranchConfig(repository.getConfig(),
+ branchName);
+ String remoteName = branchConfig.getRemote();
+ if (remoteName != null) {
+ for (RemoteConfig rc : remoteConfigs) {
+ if (remoteName.equals(rc.getName()))
+ remoteSelectionCombo.setSelectedRemote(rc);
+ }
+ }
+ }
+
+ remoteConfig = remoteSelectionCombo.getSelectedRemote();
+ setRefAssist(remoteConfig);
+ }
+
+ private void showNewRemoteDialog() {
+ AddRemoteWizard wizard = new AddRemoteWizard(repository);
+ WizardDialog dialog = new WizardDialog(getShell(), wizard);
+ int result = dialog.open();
+ if (result == Window.OK) {
+ URIish uri = wizard.getUri();
+ String remoteName = wizard.getRemoteName();
+ try {
+ StoredConfig repoConfig = repository.getConfig();
+ RemoteConfig newRemoteConfig = new RemoteConfig(repoConfig,
+ remoteName);
+ newRemoteConfig.addURI(uri);
+ RefSpec defaultFetchSpec = new RefSpec().setForceUpdate(true)
+ .setSourceDestination(Constants.R_HEADS + "*", //$NON-NLS-1$
+ Constants.R_REMOTES + remoteName + "/*"); //$NON-NLS-1$
+ newRemoteConfig.addFetchRefSpec(defaultFetchSpec);
+ newRemoteConfig.update(repoConfig);
+ repoConfig.save();
+ List<RemoteConfig> allRemoteConfigs = RemoteConfig
+ .getAllRemoteConfigs(repository.getConfig());
+ remoteSelectionCombo.setItems(allRemoteConfigs);
+ // find the new remote in the list, as the initial
+ // newRemoteConfig object
+ // isn't what's stored and returned by getAllRemoteConfigs
+ for (RemoteConfig current : allRemoteConfigs) {
+ if (newRemoteConfig.getName().equals(current.getName())) {
+ setSelectedRemote(current);
+ }
+ }
+ } catch (URISyntaxException ex) {
+ Activator.logError(ex.getMessage(), ex);
+ } catch (IOException ex) {
+ Activator.logError(ex.getMessage(), ex);
+ }
+ }
+ }
+
+ private void setRefAssist(RemoteConfig config) {
+ if (config != null && config.getURIs().size() > 0) {
+ this.assist = new RefContentAssistProvider(
+ PullWizardPage.this.repository, config.getURIs().get(0),
+ getShell());
+ }
+ }
+
+ void setSelectedRemote(RemoteConfig config) {
+ remoteSelectionCombo.setSelectedRemote(config);
+ this.remoteConfig = config;
+ setRefAssist(this.remoteConfig);
+ checkPage();
+ }
+
+ @Override
+ public boolean isPageComplete() {
+ return remoteConfig != null && remoteBranchNameText.getText() != null
+ && !remoteBranchNameText.getText().isEmpty();
+ }
+
+ private void checkPage() {
+ try {
+ if (remoteConfig == null) {
+ setErrorMessage(UIText.PushBranchPage_ChooseRemoteError);
+ return;
+ }
+ String branchName = remoteBranchNameText.getText();
+ String branchNameMessage = null;
+ if (branchName.length() == 0) {
+ branchNameMessage = MessageFormat.format(
+ UIText.PullWizardPage_ChooseReference,
+ remoteConfig.getName());
+ }
+ if (branchNameMessage != null) {
+ setErrorMessage(branchNameMessage);
+ if (this.missingBranchDecorator == null) {
+ this.missingBranchDecorator = new ControlDecoration(this.remoteBranchNameText, SWT.TOP | SWT.LEFT);
+ this.missingBranchDecorator
+ .setImage(FieldDecorationRegistry.getDefault()
+ .getFieldDecoration(
+ FieldDecorationRegistry.DEC_ERROR)
+ .getImage());
+ }
+ this.missingBranchDecorator
+ .setDescriptionText(branchNameMessage);
+ this.missingBranchDecorator.show();
+ return;
+ } else if (this.missingBranchDecorator != null) {
+ this.missingBranchDecorator.hide();
+ }
+
+ if (overrideUpstreamConfiguration()
+ && hasDifferentUpstreamConfiguration()) {
+ setMessage(UIText.PushBranchPage_UpstreamConfigOverwriteWarning,
+ IMessageProvider.WARNING);
+ } else {
+ setMessage(UIText.PullWizardPage_PageMessage);
+ }
+ setErrorMessage(null);
+ } finally {
+ setPageComplete(getErrorMessage() == null);
+ }
+ }
+
+ private void handleError(URISyntaxException e) {
+ Activator.handleError(e.getMessage(), e, false);
+ setErrorMessage(e.getMessage());
+ }
+
+ private String getSuggestedBranchName() {
+ if (fullBranch != null) {
+ String branchName = Repository.shortenRefName(fullBranch);
+ StoredConfig config = repository.getConfig();
+ BranchConfig branchConfig = new BranchConfig(config, branchName);
+ String merge = branchConfig.getMerge();
+ if (!branchConfig.isRemoteLocal() && merge != null
+ && merge.startsWith(Constants.R_HEADS)) {
+ return Repository.shortenRefName(merge);
+ } else if (merge == null
+ && fullBranch.startsWith(Constants.R_HEADS)) {
+ return branchName;
+ }
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ boolean overrideUpstreamConfiguration() {
+ return this.configureUpstream;
+ }
+
+ boolean isRebaseSelected() {
+ return upstreamConfig == UpstreamConfig.REBASE;
+ }
+
+ UpstreamConfig getUpstreamConfig() {
+ return this.upstreamConfig;
+ }
+
+ private boolean hasDifferentUpstreamConfiguration() {
+ String branchName = Repository.shortenRefName(this.fullBranch);
+ BranchConfig branchConfig = new BranchConfig(repository.getConfig(),
+ branchName);
+
+ String remote = branchConfig.getRemote();
+ // No upstream config -> don't show warning
+ if (remote == null)
+ return false;
+ if (!remote.equals(remoteConfig.getName()))
+ return true;
+
+ String merge = branchConfig.getMerge();
+ if (merge == null || !merge.equals(getFullRemoteReference()))
+ return true;
+
+ boolean rebase = branchConfig.isRebase();
+ if (rebase != isRebaseSelected())
+ return true;
+
+ return false;
+ }
+
+ private void setDefaultUpstreamConfig() {
+ String branchName = Repository.shortenRefName(this.fullBranch);
+ BranchConfig branchConfig = new BranchConfig(repository.getConfig(),
+ branchName);
+ boolean alreadyConfigured = branchConfig.getMerge() != null;
+ UpstreamConfig config;
+ if (alreadyConfigured) {
+ boolean rebase = branchConfig.isRebase();
+ config = rebase ? UpstreamConfig.REBASE : UpstreamConfig.MERGE;
+ } else {
+ config = UpstreamConfig.getDefault(repository, Constants.R_REMOTES
+ + Constants.DEFAULT_REMOTE_NAME + "/" + branchName); //$NON-NLS-1$
+ }
+ this.upstreamConfig = config;
+ }
+
+ /**
+ * @return the chosen short name of the branch on the remote
+ */
+ String getFullRemoteReference() {
+ if (!remoteBranchNameText.getText().startsWith(Constants.R_REFS))
+ return Constants.R_HEADS + remoteBranchNameText.getText();
+ else
+ return remoteBranchNameText.getText();
+ }
+
+ RemoteConfig getRemoteConfig() {
+ return this.remoteConfig;
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ if (this.missingBranchDecorator != null) {
+ this.missingBranchDecorator.dispose();
+ }
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/AddRemoteWizard.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/AddRemoteWizard.java
index 5fc496f466..652c63a83b 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/AddRemoteWizard.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/AddRemoteWizard.java
@@ -47,7 +47,10 @@ public class AddRemoteWizard extends Wizard {
return page.getSelection();
}
- AddRemotePage getAddRemotePage() {
+ /**
+ * @return the wizard page
+ */
+ public AddRemotePage getAddRemotePage() {
return page;
}
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 fd6d72827e..363f21446a 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
@@ -707,6 +707,12 @@ HistoryPreferencePage_MaxTagLength=&Maximum characters to show for a tag:
HistoryPreferencePage_ShowGroupLabel=Show
HistoryPreferencePage_ShowInRevCommentGroupLabel=Show in Revision Comment
+PullWizardPage_PageName=PullWizardPage
+PullWizardPage_PageTitle=Pull
+PullWizardPage_PageMessage=Configure a pull operation to import remote changes.
+PullWizardPage_referenceLabel=Reference:
+PullWizardPage_referenceTooltip=Reference can be a branch, a tag, a commit id...
+PullWizardPage_ChooseReference=Please select a reference to pull from remote \"{0}\"
PullOperationUI_ConnectionProblem=Git connection problem.\
\n\nMaybe you are offline or behind a proxy.\nCheck your network connection and proxy configuration.
PullOperationUI_NotTriedMessage=Not tried

Back to the top