Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathias Kinzler2011-02-07 18:02:15 -0500
committerMatthias Sohn2011-02-07 18:02:15 -0500
commit93e541a9fcacd91f3ea80f52f0f200d0b011cbdb (patch)
tree53a66d25b6e3e3239e87c95b8d1768dadc2d92ed
parent521ad3aaf06318840bac3992c39df74faed68567 (diff)
downloadegit-93e541a9fcacd91f3ea80f52f0f200d0b011cbdb.tar.gz
egit-93e541a9fcacd91f3ea80f52f0f200d0b011cbdb.tar.xz
egit-93e541a9fcacd91f3ea80f52f0f200d0b011cbdb.zip
Add a "Fetch Change from Gerrit" action
The action is available from the Repository view (on Repository nodes) as well as via Team > Remote > Fetch a change from Gerrit. The user needs to select a URI (the dropdown is populated from all URIs available from all remotes of the current Repository) and a change. There is a content assist for the change. By clicking CTRL+Space, the user can see a list of changes and select one. The user can also paste the change in the form refs/changes/<nn>/<nnnn>/<nn> from the Gerrit WebUI or type it in manually if they know the specifics... There are several options available to perform after fetch was done: creation of a local branch (default), creation of a tag, checking out FETCH_HEAD, or doing nothing else (just updating FETCH_HEAD). If a branch or tag is to be created, a name is suggested in some pseudo-hierarchical format ("change/<nnnn>/<nn>" which comes in handy when the user activates the "hierarchical branch layout" in the Repositories view)... Change-Id: Ie639e3662cc3994331e26c8c94e11458ad9dd8fa Signed-off-by: Mathias Kinzler <mathias.kinzler@sap.com> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
-rw-r--r--org.eclipse.egit.ui/META-INF/MANIFEST.MF1
-rw-r--r--org.eclipse.egit.ui/plugin.properties3
-rw-r--r--org.eclipse.egit.ui/plugin.xml33
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java72
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commands/shared/AbstractSharedCommandHandler.java77
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commands/shared/FetchChangeFromGerritCommand.java33
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchGerritChangePage.java598
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchGerritChangeWizard.java46
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties24
9 files changed, 887 insertions, 0 deletions
diff --git a/org.eclipse.egit.ui/META-INF/MANIFEST.MF b/org.eclipse.egit.ui/META-INF/MANIFEST.MF
index 00330844a..b0ff34292 100644
--- a/org.eclipse.egit.ui/META-INF/MANIFEST.MF
+++ b/org.eclipse.egit.ui/META-INF/MANIFEST.MF
@@ -60,6 +60,7 @@ Export-Package: org.eclipse.egit.ui;version="0.11.0",
org.eclipse.egit.ui.internal.actions;version="0.11.0";x-internal:=true,
org.eclipse.egit.ui.internal.clone;version="0.11.0";x-internal:=true,
org.eclipse.egit.ui.internal.commands;version="0.11.0";x-internal:=true,
+ org.eclipse.egit.ui.internal.commands.shared;version="0.11.0";x-internal:=true,
org.eclipse.egit.ui.internal.components;version="0.11.0";x-internal:=true,
org.eclipse.egit.ui.internal.decorators;version="0.11.0";x-internal:=true,
org.eclipse.egit.ui.internal.dialogs;version="0.11.0";x-internal:=true,
diff --git a/org.eclipse.egit.ui/plugin.properties b/org.eclipse.egit.ui/plugin.properties
index 5abe019ba..d10995c40 100644
--- a/org.eclipse.egit.ui/plugin.properties
+++ b/org.eclipse.egit.ui/plugin.properties
@@ -245,3 +245,6 @@ OpenInTextEditorCommand.name = Open in Text Editor
ConfigureFetchFromUpstreamCommand.label = Configure F&etch from Upstream...
ConfigurePushToUpstreamCommand.label = Configure P&ush to Upstream...
CommitMessageProviderExtension-point.name = CommitMessageProvider
+
+FetchFromGerritCommand.name = Fetch from Gerrit
+FetchFromGerritCommand.label = Fetch from &Gerrit... \ No newline at end of file
diff --git a/org.eclipse.egit.ui/plugin.xml b/org.eclipse.egit.ui/plugin.xml
index 06ff907e4..1b9c375d4 100644
--- a/org.eclipse.egit.ui/plugin.xml
+++ b/org.eclipse.egit.ui/plugin.xml
@@ -615,6 +615,12 @@
id="org.eclipse.egit.ui.command.configureTrace"
name="%ConfigureTraceCommand.name">
</command>
+ <command
+ categoryId="org.eclipse.egit.ui.commandCategory"
+ defaultHandler="org.eclipse.egit.ui.internal.commands.shared.FetchChangeFromGerritCommand"
+ id="org.eclipse.egit.ui.FetchGerritChange"
+ name="%FetchFromGerritCommand.name">
+ </command>
</extension>
<extension
point="org.eclipse.ui.views">
@@ -1352,6 +1358,24 @@
</visibleWhen>
</command>
<command
+ commandId="org.eclipse.egit.ui.FetchGerritChange"
+ label="%FetchFromGerritCommand.label"
+ style="push">
+ <visibleWhen
+ checkEnabled="false">
+ <and>
+ <count
+ value="1">
+ </count>
+ <iterate>
+ <instanceof
+ value="org.eclipse.egit.ui.internal.repository.tree.RepositoryNode">
+ </instanceof>
+ </iterate>
+ </and>
+ </visibleWhen>
+ </command>
+ <command
commandId="org.eclipse.egit.ui.RepositoriesViewPull"
icon="icons/obj16/pull.gif"
label="%RepoViewPullMenu.label"
@@ -2265,6 +2289,10 @@
commandId="org.eclipse.egit.ui.team.Push"
icon="icons/obj16/push.gif">
</image>
+ <image
+ commandId="org.eclipse.egit.ui.FetchGerritChange"
+ icon="icons/obj16/gerrit_obj.gif">
+ </image>
</extension>
<extension
point="org.eclipse.core.expressions.propertyTesters">
@@ -2694,6 +2722,11 @@
style="push">
</command>
<command
+ commandId="org.eclipse.egit.ui.FetchGerritChange"
+ label="%FetchFromGerritCommand.label"
+ style="push">
+ </command>
+ <command
commandId="org.eclipse.egit.ui.team.Push"
label="%PushAction_label"
style="push">
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java
index 6ca4e5368..5db0a21bb 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java
@@ -1957,6 +1957,78 @@ public class UIText extends NLS {
public static String FetchDestinationPage_TrackingBranchNotFoundMessage;
/** */
+ public static String FetchGerritChangePage_AfterFetchGroup;
+
+ /** */
+ public static String FetchGerritChangePage_BranchNameText;
+
+ /** */
+ public static String FetchGerritChangePage_ChangeLabel;
+
+ /** */
+ public static String FetchGerritChangePage_CheckingOutTaskName;
+
+ /** */
+ public static String FetchGerritChangePage_CheckoutRadio;
+
+ /** */
+ public static String FetchGerritChangePage_ContentAssistDescription;
+
+ /** */
+ public static String FetchGerritChangePage_ContentAssistTooltip;
+
+ /** */
+ public static String FetchGerritChangePage_CreatingBranchTaskName;
+
+ /** */
+ public static String FetchGerritChangePage_CreatingTagTaskName;
+
+ /** */
+ public static String FetchGerritChangePage_ExistingRefMessage;
+
+ /** */
+ public static String FetchGerritChangePage_FetchingTaskName;
+
+ /** */
+ public static String FetchGerritChangePage_GeneratedTagMessage;
+
+ /** */
+ public static String FetchGerritChangePage_GetChangeTaskName;
+
+ /** */
+ public static String FetchGerritChangePage_LocalBranchRadio;
+
+ /** */
+ public static String FetchGerritChangePage_MissingChangeMessage;
+
+ /** */
+ public static String FetchGerritChangePage_PageMessage;
+
+ /** */
+ public static String FetchGerritChangePage_PageTitle;
+
+ /** */
+ public static String FetchGerritChangePage_ProvideRefNameMessage;
+
+ /** */
+ public static String FetchGerritChangePage_SuggestedRefNamePattern;
+
+ /** */
+ public static String FetchGerritChangePage_TagNameText;
+
+ /** */
+ public static String FetchGerritChangePage_TagRadio;
+
+ /** */
+ public static String FetchGerritChangePage_UpdateRadio;
+
+ /** */
+ public static String FetchGerritChangePage_UriLabel;
+
+ /** */
+ public static String FetchGerritChangeWizard_WizardTitle;
+
+ /** */
public static String FetchResultDialog_ConfigureButton;
/** */
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commands/shared/AbstractSharedCommandHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commands/shared/AbstractSharedCommandHandler.java
new file mode 100644
index 000000000..cac288f66
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commands/shared/AbstractSharedCommandHandler.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2010 SAP AG.
+ * 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:
+ * Mathias Kinzler (SAP AG) - initial implementation
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.commands.shared;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNode;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Abstract super class for commands shared between different components in EGit
+ */
+public abstract class AbstractSharedCommandHandler extends AbstractHandler {
+ /**
+ * @param event
+ * the {@link ExecutionEvent}
+ * @return a {@link Repository} if all elements in the current selection map
+ * to the same {@link Repository}, otherwise null
+ */
+ protected Repository getRepository(ExecutionEvent event) {
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ if (selection.isEmpty())
+ return null;
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection ssel = (IStructuredSelection) selection;
+ Repository result = null;
+ for (Object element : ssel.toList()) {
+ Repository elementRepository = null;
+ if (element instanceof RepositoryTreeNode) {
+ elementRepository = ((RepositoryTreeNode) element)
+ .getRepository();
+ } else if (element instanceof IResource) {
+ IResource resource = (IResource) element;
+ RepositoryMapping mapping = RepositoryMapping
+ .getMapping(resource.getProject());
+ if (mapping != null)
+ elementRepository = mapping.getRepository();
+ } else if (element instanceof IAdaptable) {
+ IResource adapted = (IResource) ((IAdaptable) element)
+ .getAdapter(IResource.class);
+ if (adapted != null) {
+ RepositoryMapping mapping = RepositoryMapping
+ .getMapping(adapted.getProject());
+ if (mapping != null)
+ elementRepository = mapping.getRepository();
+ }
+ }
+ if (elementRepository == null)
+ continue;
+ if (result != null && !elementRepository.equals(result))
+ return null;
+ if (result == null)
+ result = elementRepository;
+ }
+ return result;
+ }
+ if (selection instanceof TextSelection) {
+ // TODO find editor input and adapt to IResource
+ }
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commands/shared/FetchChangeFromGerritCommand.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commands/shared/FetchChangeFromGerritCommand.java
new file mode 100644
index 000000000..ecdd7dff9
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/commands/shared/FetchChangeFromGerritCommand.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2010 SAP AG.
+ * 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:
+ * Mathias Kinzler (SAP AG) - initial implementation
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.commands.shared;
+
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.egit.ui.internal.fetch.FetchGerritChangeWizard;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Fetch a change from Gerrit
+ */
+public class FetchChangeFromGerritCommand extends AbstractSharedCommandHandler {
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ Repository repository = getRepository(event);
+ FetchGerritChangeWizard wiz = new FetchGerritChangeWizard(repository);
+ WizardDialog dlg = new WizardDialog(HandlerUtil
+ .getActiveShellChecked(event), wiz);
+ dlg.setHelpAvailable(false);
+ dlg.open();
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchGerritChangePage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchGerritChangePage.java
new file mode 100644
index 000000000..2f35e6e24
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchGerritChangePage.java
@@ -0,0 +1,598 @@
+/*******************************************************************************
+ * Copyright (c) 2010 SAP AG.
+ * 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:
+ * Mathias Kinzler (SAP AG) - initial implementation
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.fetch;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.op.BranchOperation;
+import org.eclipse.egit.core.op.CreateLocalBranchOperation;
+import org.eclipse.egit.core.op.ListRemoteOperation;
+import org.eclipse.egit.core.op.TagOperation;
+import org.eclipse.egit.ui.Activator;
+import org.eclipse.egit.ui.UIPreferences;
+import org.eclipse.egit.ui.UIText;
+import org.eclipse.egit.ui.UIUtils;
+import org.eclipse.jface.bindings.keys.KeyStroke;
+import org.eclipse.jface.bindings.keys.ParseException;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.fieldassist.ContentProposalAdapter;
+import org.eclipse.jface.fieldassist.IContentProposal;
+import org.eclipse.jface.fieldassist.IContentProposalProvider;
+import org.eclipse.jface.fieldassist.TextContentAdapter;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.jgit.api.Git;
+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.lib.TagBuilder;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.FetchResult;
+import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.transport.RemoteConfig;
+import org.eclipse.jgit.transport.URIish;
+import org.eclipse.osgi.util.NLS;
+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.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Fetch a change from Gerrit
+ */
+public class FetchGerritChangePage extends WizardPage {
+ private final Repository repository;
+
+ private Combo uriCombo;
+
+ private List<Change> changeRefs;
+
+ private Text refText;
+
+ private Button createBranch;
+
+ private Button createTag;
+
+ private Button checkout;
+
+ private Button dontCheckout;
+
+ private Label tagTextlabel;
+
+ private Text tagText;
+
+ private Label branchTextlabel;
+
+ private Text branchText;
+
+ /**
+ * @param repository
+ */
+ public FetchGerritChangePage(Repository repository) {
+ super(FetchGerritChangePage.class.getName());
+ this.repository = repository;
+ setTitle(NLS
+ .bind(UIText.FetchGerritChangePage_PageTitle,
+ Activator.getDefault().getRepositoryUtil()
+ .getRepositoryName(repository)));
+ setMessage(UIText.FetchGerritChangePage_PageMessage);
+ }
+
+ public void createControl(Composite parent) {
+ Composite main = new Composite(parent, SWT.NONE);
+ main.setLayout(new GridLayout(2, false));
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(main);
+ new Label(main, SWT.NONE)
+ .setText(UIText.FetchGerritChangePage_UriLabel);
+ uriCombo = new Combo(main, SWT.DROP_DOWN);
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(uriCombo);
+ uriCombo.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ changeRefs = null;
+ }
+ });
+ new Label(main, SWT.NONE)
+ .setText(UIText.FetchGerritChangePage_ChangeLabel);
+ refText = new Text(main, SWT.BORDER);
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(refText);
+ addRefContentProposalToText(refText);
+
+ Group checkoutGroup = new Group(main, SWT.SHADOW_ETCHED_IN);
+ checkoutGroup.setLayout(new GridLayout(2, false));
+ GridDataFactory.fillDefaults().span(2, 1).grab(true, true)
+ .applyTo(checkoutGroup);
+ checkoutGroup.setText(UIText.FetchGerritChangePage_AfterFetchGroup);
+
+ // radio: create local branch
+ createBranch = new Button(checkoutGroup, SWT.RADIO);
+ GridDataFactory.fillDefaults().span(2, 1).applyTo(createBranch);
+ createBranch.setText(UIText.FetchGerritChangePage_LocalBranchRadio);
+ createBranch.setSelection(true);
+ createBranch.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ checkPage();
+ }
+ });
+
+ branchTextlabel = new Label(checkoutGroup, SWT.NONE);
+ branchTextlabel.setText(UIText.FetchGerritChangePage_BranchNameText);
+ branchText = new Text(checkoutGroup, SWT.SINGLE | SWT.BORDER);
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(branchText);
+ branchText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ checkPage();
+ }
+ });
+
+ // radio: create tag
+ createTag = new Button(checkoutGroup, SWT.RADIO);
+ GridDataFactory.fillDefaults().span(2, 1).applyTo(createTag);
+ createTag.setText(UIText.FetchGerritChangePage_TagRadio);
+ createTag.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ checkPage();
+ }
+ });
+
+ tagTextlabel = new Label(checkoutGroup, SWT.NONE);
+ GridDataFactory.defaultsFor(tagTextlabel).exclude(true)
+ .applyTo(tagTextlabel);
+ tagTextlabel.setText(UIText.FetchGerritChangePage_TagNameText);
+ tagText = new Text(checkoutGroup, SWT.SINGLE | SWT.BORDER);
+ GridDataFactory.fillDefaults().exclude(true).grab(true, false)
+ .applyTo(tagText);
+ tagText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ checkPage();
+ }
+ });
+
+ // radio: checkout FETCH_HEAD
+ checkout = new Button(checkoutGroup, SWT.RADIO);
+ GridDataFactory.fillDefaults().span(2, 1).applyTo(checkout);
+ checkout.setText(UIText.FetchGerritChangePage_CheckoutRadio);
+ checkout.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ checkPage();
+ }
+ });
+
+ // radio: don't checkout
+ dontCheckout = new Button(checkoutGroup, SWT.RADIO);
+ GridDataFactory.fillDefaults().span(2, 1).applyTo(checkout);
+ dontCheckout.setText(UIText.FetchGerritChangePage_UpdateRadio);
+ dontCheckout.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ checkPage();
+ }
+ });
+
+ refText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ Change change = Change.fromRef(refText.getText());
+ if (change != null) {
+ branchText.setText(NLS
+ .bind(UIText.FetchGerritChangePage_SuggestedRefNamePattern,
+ change.getChangeNumber(),
+ change.getPatchSetNumber()));
+ tagText.setText(branchText.getText());
+ } else {
+ branchText.setText(""); //$NON-NLS-1$
+ tagText.setText(""); //$NON-NLS-1$
+ }
+ checkPage();
+ }
+ });
+
+ // get all available URIs from the repository
+ SortedSet<String> uris = new TreeSet<String>();
+ try {
+ for (RemoteConfig rc : RemoteConfig.getAllRemoteConfigs(repository
+ .getConfig())) {
+ if (rc.getURIs().size() > 0)
+ uris.add(rc.getURIs().get(0).toPrivateString());
+ for (URIish u : rc.getPushURIs())
+ uris.add(u.toPrivateString());
+
+ }
+ } catch (URISyntaxException e) {
+ Activator.handleError(e.getMessage(), e, false);
+ setErrorMessage(e.getMessage());
+ }
+ for (String aUri : uris)
+ uriCombo.add(aUri);
+ uriCombo.select(0);
+
+ Dialog.applyDialogFont(main);
+ setControl(main);
+ }
+
+ private void checkPage() {
+ boolean createBranchSelected = createBranch.getSelection();
+ branchText.setEnabled(createBranchSelected);
+ branchText.setVisible(createBranchSelected);
+ branchTextlabel.setVisible(createBranchSelected);
+ GridData gd = (GridData) branchText.getLayoutData();
+ gd.exclude = !createBranchSelected;
+ gd = (GridData) branchTextlabel.getLayoutData();
+ gd.exclude = !createBranchSelected;
+
+ boolean createTagSelected = createTag.getSelection();
+ tagText.setEnabled(createTagSelected);
+ tagText.setVisible(createTagSelected);
+ tagTextlabel.setVisible(createTagSelected);
+ gd = (GridData) tagText.getLayoutData();
+ gd.exclude = !createTagSelected;
+ gd = (GridData) tagTextlabel.getLayoutData();
+ gd.exclude = !createTagSelected;
+ branchText.getParent().layout(true);
+
+ setErrorMessage(null);
+ try {
+ if (refText.getText().length() > 0) {
+ Change change = Change.fromRef(refText.getText());
+ if (change == null) {
+ setErrorMessage(UIText.FetchGerritChangePage_MissingChangeMessage);
+ return;
+ }
+ } else {
+ setErrorMessage(UIText.FetchGerritChangePage_MissingChangeMessage);
+ return;
+ }
+
+ boolean emptyRefName = (createBranchSelected && branchText
+ .getText().length() == 0)
+ || (createTagSelected && tagText.getText().length() == 0);
+ if (emptyRefName) {
+ setErrorMessage(UIText.FetchGerritChangePage_ProvideRefNameMessage);
+ return;
+ }
+
+ boolean existingRefName = (createBranchSelected && repository
+ .getRef(branchText.getText()) != null)
+ || (createTagSelected && repository.getRef(tagText
+ .getText()) != null);
+ if (existingRefName) {
+ setErrorMessage(NLS.bind(
+ UIText.FetchGerritChangePage_ExistingRefMessage,
+ branchText.getText()));
+ return;
+ }
+ } catch (IOException e1) {
+ // ignore here
+ } finally {
+ setPageComplete(getErrorMessage() == null);
+ }
+ }
+
+ private List<Change> getRefsForContentAssist()
+ throws InvocationTargetException, InterruptedException {
+ if (changeRefs == null) {
+ final String uriText = uriCombo.getText();
+ getWizard().getContainer().run(true, true,
+ new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor)
+ throws InvocationTargetException,
+ InterruptedException {
+ changeRefs = new ArrayList<Change>();
+ ListRemoteOperation listOp;
+ try {
+ listOp = new ListRemoteOperation(
+ repository,
+ new URIish(uriText),
+ Activator
+ .getDefault()
+ .getPreferenceStore()
+ .getInt(UIPreferences.REMOTE_CONNECTION_TIMEOUT));
+ } catch (URISyntaxException e) {
+ throw new InvocationTargetException(e);
+ }
+
+ listOp.run(monitor);
+ for (Ref ref : listOp.getRemoteRefs()) {
+ Change change = Change.fromRef(ref.getName());
+ if (change != null)
+ changeRefs.add(change);
+ }
+ Collections.sort(changeRefs,
+ new Comparator<Change>() {
+ public int compare(Change o1, Change o2) {
+ // change number descending
+ int changeDiff = o2.changeNumber
+ .compareTo(o1.changeNumber);
+ if (changeDiff == 0)
+ // patch set number descending
+ changeDiff = o2
+ .getPatchSetNumber()
+ .compareTo(
+ o1.getPatchSetNumber());
+ return changeDiff;
+ }
+ });
+ }
+ });
+
+ }
+ return changeRefs;
+ }
+
+ boolean doFetch() {
+ try {
+ final RefSpec spec = new RefSpec().setSource(refText.getText())
+ .setDestination(Constants.FETCH_HEAD);
+ final String uri = uriCombo.getText();
+ final boolean doCheckout = checkout.getSelection();
+ final boolean doCreateTag = createTag.getSelection();
+ final boolean doCreateBranch = createBranch.getSelection();
+ final String textForTag = tagText.getText();
+ final String textForBranch = branchText.getText();
+ getWizard().getContainer().run(true, true,
+ new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor)
+ throws InvocationTargetException,
+ InterruptedException {
+ int totalWork = 1;
+ if (doCheckout)
+ totalWork++;
+ if (doCreateTag || doCreateBranch)
+ totalWork++;
+ monitor.beginTask(
+ UIText.FetchGerritChangePage_GetChangeTaskName,
+ totalWork);
+ List<RefSpec> specs = new ArrayList<RefSpec>(1);
+ specs.add(spec);
+ int timeout = Activator
+ .getDefault()
+ .getPreferenceStore()
+ .getInt(UIPreferences.REMOTE_CONNECTION_TIMEOUT);
+ FetchResult fetchRes;
+ try {
+ String taskName = NLS
+ .bind(UIText.FetchGerritChangePage_FetchingTaskName,
+ spec.getSource());
+ monitor.setTaskName(taskName);
+ fetchRes = new FetchOperationUI(repository,
+ new URIish(uri), specs, timeout, false)
+ .execute(monitor);
+
+ monitor.worked(1);
+ RevCommit commit = new RevWalk(repository)
+ .parseCommit(fetchRes.getAdvertisedRef(
+ spec.getSource()).getObjectId());
+
+ if (doCreateTag) {
+ monitor.setTaskName(UIText.FetchGerritChangePage_CreatingTagTaskName);
+ final TagBuilder tag = new TagBuilder();
+ PersonIdent personIdent = new PersonIdent(
+ repository);
+
+ tag.setTag(textForTag);
+ tag.setTagger(personIdent);
+ tag.setMessage(NLS
+ .bind(UIText.FetchGerritChangePage_GeneratedTagMessage,
+ spec.getSource()));
+ tag.setObjectId(commit);
+ new TagOperation(repository, tag, false)
+ .execute(monitor);
+ monitor.worked(1);
+ }
+ if (doCreateBranch) {
+ monitor.setTaskName(UIText.FetchGerritChangePage_CreatingBranchTaskName);
+ CreateLocalBranchOperation bop = new CreateLocalBranchOperation(
+ repository, textForBranch, commit);
+ bop.execute(monitor);
+ new Git(repository).checkout()
+ .setName(textForBranch).call();
+ monitor.worked(1);
+ }
+ if (doCheckout || doCreateTag) {
+ monitor.setTaskName(UIText.FetchGerritChangePage_CheckingOutTaskName);
+ new BranchOperation(repository, commit)
+ .execute(monitor);
+ monitor.worked(1);
+ }
+ } catch (Exception e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+ }
+ });
+ } catch (InvocationTargetException e) {
+ Activator
+ .handleError(e.getCause().getMessage(), e.getCause(), true);
+ return false;
+ } catch (InterruptedException e) {
+ // just return
+ }
+ return true;
+ }
+
+ private void addRefContentProposalToText(final Text textField) {
+ KeyStroke stroke;
+ try {
+ stroke = KeyStroke.getInstance("CTRL+SPACE"); //$NON-NLS-1$
+ UIUtils.addBulbDecorator(textField, NLS.bind(
+ UIText.FetchGerritChangePage_ContentAssistTooltip,
+ stroke.format()));
+ } catch (ParseException e1) {
+ Activator.handleError(e1.getMessage(), e1, false);
+ stroke = null;
+ }
+
+ IContentProposalProvider cp = new IContentProposalProvider() {
+ public IContentProposal[] getProposals(String contents, int position) {
+ List<IContentProposal> resultList = new ArrayList<IContentProposal>();
+
+ // make the simplest possible pattern check: allow "*"
+ // for multiple characters
+ String patternString = contents;
+ // ignore spaces in the beginning
+ while (patternString.length() > 0
+ && patternString.charAt(0) == ' ') {
+ patternString = patternString.substring(1);
+ }
+
+ // we quote the string as it may contain spaces
+ // and other stuff colliding with the Pattern
+ patternString = Pattern.quote(patternString);
+
+ patternString = patternString.replaceAll("\\x2A", ".*"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ // make sure we add a (logical) * at the end
+ if (!patternString.endsWith(".*")) { //$NON-NLS-1$
+ patternString = patternString + ".*"; //$NON-NLS-1$
+ }
+
+ // let's compile a case-insensitive pattern (assumes ASCII only)
+ Pattern pattern;
+ try {
+ pattern = Pattern.compile(patternString,
+ Pattern.CASE_INSENSITIVE);
+ } catch (PatternSyntaxException e) {
+ pattern = null;
+ }
+
+ List<Change> proposals;
+ try {
+ proposals = getRefsForContentAssist();
+ } catch (InvocationTargetException e) {
+ Activator.handleError(e.getMessage(), e, false);
+ return null;
+ } catch (InterruptedException e) {
+ return null;
+ }
+
+ if (proposals != null)
+ for (final Change ref : proposals) {
+ if (pattern != null
+ && !pattern.matcher(
+ ref.getChangeNumber().toString())
+ .matches())
+ continue;
+ IContentProposal propsal = new ChangeContentProposal(
+ ref);
+ resultList.add(propsal);
+ }
+
+ return resultList.toArray(new IContentProposal[resultList
+ .size()]);
+ }
+ };
+
+ ContentProposalAdapter adapter = new ContentProposalAdapter(textField,
+ new TextContentAdapter(), cp, stroke, null);
+ // set the acceptance style to always replace the complete content
+ adapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);
+ }
+
+ private final static class Change {
+ private final String refName;
+
+ private final Integer changeNumber;
+
+ private final Integer patchSetNumber;
+
+ static Change fromRef(String refName) {
+ try {
+ if (!refName.startsWith("refs/changes/")) //$NON-NLS-1$
+ return null;
+ String[] tokens = refName.substring(13).split("/"); //$NON-NLS-1$
+ if (tokens.length != 3)
+ return null;
+ Integer changeNumber = Integer.valueOf(tokens[1]);
+ Integer patchSetNumber = Integer.valueOf(tokens[2]);
+ return new Change(refName, changeNumber, patchSetNumber);
+ } catch (NumberFormatException e) {
+ // if we can't parse this, just return null
+ return null;
+ } catch (IndexOutOfBoundsException e) {
+ // if we can't parse this, just return null
+ return null;
+ }
+ }
+
+ private Change(String refName, Integer changeNumber,
+ Integer patchSetNumber) {
+ this.refName = refName;
+ this.changeNumber = changeNumber;
+ this.patchSetNumber = patchSetNumber;
+ }
+
+ public String getRefName() {
+ return refName;
+ }
+
+ public Integer getChangeNumber() {
+ return changeNumber;
+ }
+
+ public Integer getPatchSetNumber() {
+ return patchSetNumber;
+ }
+ }
+
+ private final static class ChangeContentProposal implements
+ IContentProposal {
+ private final Change myChange;
+
+ ChangeContentProposal(Change change) {
+ myChange = change;
+ }
+
+ public String getContent() {
+ return myChange.getRefName();
+ }
+
+ public int getCursorPosition() {
+ return 0;
+ }
+
+ public String getDescription() {
+ return NLS.bind(
+ UIText.FetchGerritChangePage_ContentAssistDescription,
+ myChange.getPatchSetNumber(), myChange.getChangeNumber());
+ }
+
+ public String getLabel() {
+ return NLS
+ .bind("{0} - {1}", myChange.getChangeNumber(), myChange.getPatchSetNumber()); //$NON-NLS-1$
+ }
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchGerritChangeWizard.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchGerritChangeWizard.java
new file mode 100644
index 000000000..c70b85f41
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchGerritChangeWizard.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2010 SAP AG.
+ * 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:
+ * Mathias Kinzler (SAP AG) - initial implementation
+ *******************************************************************************/
+package org.eclipse.egit.ui.internal.fetch;
+
+import org.eclipse.egit.ui.UIText;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Wizard for fetching a Gerrit change
+ */
+public class FetchGerritChangeWizard extends Wizard {
+ private final Repository repository;
+
+ FetchGerritChangePage page;
+
+ /**
+ * @param repository
+ * the repository
+ */
+ public FetchGerritChangeWizard(Repository repository) {
+ this.repository = repository;
+ setNeedsProgressMonitor(true);
+ setHelpAvailable(false);
+ setWindowTitle(UIText.FetchGerritChangeWizard_WizardTitle);
+ }
+
+ @Override
+ public void addPages() {
+ page = new FetchGerritChangePage(repository);
+ addPage(page);
+ }
+
+ @Override
+ public boolean performFinish() {
+ return page.doFetch();
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties
index 5bb3e9222..f4526320d 100644
--- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties
@@ -644,6 +644,30 @@ FetchDestinationPage_PageMessage=The destination is a Remote Tracking Branch in
FetchDestinationPage_RepositoryLabel=Local Repository:
FetchDestinationPage_SourceLabel=Source:
FetchDestinationPage_TrackingBranchNotFoundMessage=Remote Tracking branch "{0}" not found in local Repository
+FetchGerritChangePage_AfterFetchGroup=Action to perform after fetch
+FetchGerritChangePage_BranchNameText=Branch &name
+FetchGerritChangePage_ChangeLabel=&Change:
+FetchGerritChangePage_CheckingOutTaskName=Checking out change
+FetchGerritChangePage_CheckoutRadio=Check&out FETCH_HEAD
+FetchGerritChangePage_ContentAssistDescription=Patch Set {0} of change {1}
+FetchGerritChangePage_ContentAssistTooltip=Press {0} to see a filtered list of changes
+FetchGerritChangePage_CreatingBranchTaskName=Creating branch
+FetchGerritChangePage_CreatingTagTaskName=Creating tag
+FetchGerritChangePage_ExistingRefMessage=A branch or tag with name {0} already exists
+FetchGerritChangePage_FetchingTaskName=Fetching change {0}
+FetchGerritChangePage_GeneratedTagMessage=Generated for Gerrit change {0}
+FetchGerritChangePage_GetChangeTaskName=Get change from Gerrit
+FetchGerritChangePage_LocalBranchRadio=Create and checkout a local &branch
+FetchGerritChangePage_MissingChangeMessage=Please provide a change
+FetchGerritChangePage_PageMessage=Please select a Gerrit URI and change to fetch
+FetchGerritChangePage_PageTitle=Fetch a change from Gerrit into Repository {0}
+FetchGerritChangePage_ProvideRefNameMessage=Please provide a name for the new branch or tag
+FetchGerritChangePage_SuggestedRefNamePattern=change/{0}/{1}
+FetchGerritChangePage_TagNameText=Tag &name
+FetchGerritChangePage_TagRadio=Create and checkout a &tag
+FetchGerritChangePage_UpdateRadio=Update &FETCH_HEAD only
+FetchGerritChangePage_UriLabel=&URI:
+FetchGerritChangeWizard_WizardTitle=Fetch a change from Gerrit
FetchResultDialog_ConfigureButton=&Configure...
FetchResultDialog_labelEmptyResult=No ref to fetch from {0} - everything up to date.
FetchResultDialog_labelNonEmptyResult=Fetched from {0}.

Back to the top