org.eclipse.egit.ui.internal.push.PushToGerritPage.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.egit.ui.internal.push.PushToGerritPage.java

Source

/*******************************************************************************
 * Copyright (c) 2012 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.push;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.egit.core.op.PushOperationResult;
import org.eclipse.egit.core.op.PushOperationSpecification;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIPreferences;
import org.eclipse.egit.ui.UIUtils;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.egit.ui.internal.credentials.EGitCredentialsProvider;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.bindings.keys.ParseException;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogSettings;
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.wizard.WizardPage;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.RemoteRefUpdate;
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.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

/**
 * Push the current HEAD to Gerrit
 */
class PushToGerritPage extends WizardPage {
    private static final String PUSH_TO_GERRIT_PAGE_SECTION = "PushToGerritPage"; //$NON-NLS-1$

    private static final String LAST_URI_POSTFIX = ".lastUri"; //$NON-NLS-1$

    private static final String LAST_BRANCH_POSTFIX = ".lastBranch"; //$NON-NLS-1$

    private final Repository repository;

    private final IDialogSettings settings;

    private final String lastUriKey;

    private final String lastBranchKey;

    private Combo uriCombo;

    private Combo prefixCombo;

    private Label branchTextlabel;

    private Text branchText;

    /**
     * @param repository
     */
    PushToGerritPage(Repository repository) {
        super(PushToGerritPage.class.getName());
        this.repository = repository;
        setTitle(NLS.bind(UIText.PushToGerritPage_Title,
                Activator.getDefault().getRepositoryUtil().getRepositoryName(repository)));
        setMessage(UIText.PushToGerritPage_Message);
        settings = getDialogSettings();
        lastUriKey = repository + LAST_URI_POSTFIX;
        lastBranchKey = repository + LAST_BRANCH_POSTFIX;
    }

    protected IDialogSettings getDialogSettings() {
        IDialogSettings s = Activator.getDefault().getDialogSettings();
        IDialogSettings section = s.getSection(PUSH_TO_GERRIT_PAGE_SECTION);
        if (section == null)
            section = s.addNewSection(PUSH_TO_GERRIT_PAGE_SECTION);
        return section;
    }

    public void createControl(Composite parent) {
        Composite main = new Composite(parent, SWT.NONE);
        main.setLayout(new GridLayout(3, false));
        GridDataFactory.fillDefaults().grab(true, true).applyTo(main);
        new Label(main, SWT.NONE).setText(UIText.PushToGerritPage_UriLabel);
        uriCombo = new Combo(main, SWT.DROP_DOWN);
        GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(uriCombo);
        uriCombo.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                checkPage();
            }
        });

        branchTextlabel = new Label(main, SWT.NONE);

        // we visualize the prefix here
        prefixCombo = new Combo(main, SWT.READ_ONLY | SWT.DROP_DOWN);
        prefixCombo.add("refs/for/"); //$NON-NLS-1$
        prefixCombo.add("refs/drafts/"); //$NON-NLS-1$
        prefixCombo.select(0);

        branchTextlabel.setText(UIText.PushToGerritPage_BranchLabel);
        branchText = new Text(main, SWT.SINGLE | SWT.BORDER);
        GridDataFactory.fillDefaults().grab(true, false).applyTo(branchText);
        branchText.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                checkPage();
            }
        });

        // give focus to the nameText if label is activated using the mnemonic
        branchTextlabel.addTraverseListener(new TraverseListener() {
            public void keyTraversed(TraverseEvent e) {
                branchText.setFocus();
                branchText.selectAll();
            }
        });
        addRefContentProposalToText(branchText);

        // 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);
        selectLastUsedUri();
        setLastUsedBranch();
        branchText.setFocus();
        Dialog.applyDialogFont(main);
        setControl(main);
    }

    private void storeLastUsedUri(String uri) {
        settings.put(lastUriKey, uri.trim());
    }

    private void storeLastUsedBranch(String branch) {
        settings.put(lastBranchKey, branch.trim());
    }

    private void selectLastUsedUri() {
        String lastUri = settings.get(lastUriKey);
        if (lastUri != null) {
            int i = uriCombo.indexOf(lastUri);
            if (i != -1) {
                uriCombo.select(i);
                return;
            }
        }
        uriCombo.select(0);
    }

    private void setLastUsedBranch() {
        String lastBranch = settings.get(lastBranchKey);
        if (lastBranch != null)
            branchText.setText(lastBranch);
    }

    private void checkPage() {
        setErrorMessage(null);
        try {
            if (uriCombo.getText().length() == 0) {
                setErrorMessage(UIText.PushToGerritPage_MissingUriMessage);
                return;
            }
            if (branchText.getText().length() == 0) {
                setErrorMessage(UIText.PushToGerritPage_MissingBranchMessage);
                return;
            }
        } finally {
            setPageComplete(getErrorMessage() == null);
        }
    }

    void doPush(IProgressMonitor monitor) {
        try {
            int timeout = Activator.getDefault().getPreferenceStore()
                    .getInt(UIPreferences.REMOTE_CONNECTION_TIMEOUT);
            URIish uri = new URIish(uriCombo.getText());
            Ref currentHead = repository.getRef(Constants.HEAD);
            RemoteRefUpdate update = new RemoteRefUpdate(repository, currentHead,
                    prefixCombo.getItem(prefixCombo.getSelectionIndex()) + branchText.getText(), false, null, null);
            PushOperationSpecification spec = new PushOperationSpecification();

            spec.addURIRefUpdates(uri, Arrays.asList(update));
            PushOperationUI op = new PushOperationUI(repository, spec, timeout, false);
            op.setCredentialsProvider(new EGitCredentialsProvider());
            PushOperationResult result = op.execute(monitor);
            PushResultDialog dlg = new PushResultDialog(getShell(), repository, result, op.getDestinationString());
            dlg.showConfigureButton(false);
            dlg.open();
            storeLastUsedUri(uriCombo.getText());
            storeLastUsedBranch(branchText.getText());
        } catch (CoreException e) {
            Activator.handleError(e.getMessage(), e, true);
        } catch (URISyntaxException e) {
            Activator.handleError(e.getMessage(), e, true);
        } catch (IOException e) {
            Activator.handleError(e.getMessage(), e, true);
        }
    }

    private void addRefContentProposalToText(final Text textField) {
        KeyStroke stroke;
        try {
            stroke = KeyStroke.getInstance("CTRL+SPACE"); //$NON-NLS-1$
            UIUtils.addBulbDecorator(textField,
                    NLS.bind(UIText.PushToGerritPage_ContentProposalHoverText, 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;
                }

                Set<String> proposals = new TreeSet<String>();

                try {
                    Set<String> remotes = repository.getRefDatabase().getRefs(Constants.R_REMOTES).keySet();
                    for (String remote : remotes) {
                        // these are "origin/master", "origin/xxx"...
                        int slashIndex = remote.indexOf('/');
                        if (slashIndex > 0 && slashIndex < remote.length() - 1)
                            proposals.add(remote.substring(remote.indexOf('/') + 1));
                    }
                } catch (IOException e) {
                    // simply ignore, no proposals then
                }

                for (final String proposal : proposals) {
                    if (pattern != null && !pattern.matcher(proposal).matches())
                        continue;
                    IContentProposal propsal = new BranchContentProposal(proposal);
                    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 BranchContentProposal implements IContentProposal {
        private final String myString;

        BranchContentProposal(String string) {
            myString = string;
        }

        public String getContent() {
            return myString;
        }

        public int getCursorPosition() {
            return 0;
        }

        public String getDescription() {
            return myString;
        }

        public String getLabel() {
            return myString;
        }

        @Override
        public String toString() {
            return getContent();
        }
    }
}