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

Java tutorial

Introduction

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

Source

/*******************************************************************************
 * Copyright (c) 2013, 2016 Robin Stocker <robin@nibor.org> 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.push;

import java.io.IOException;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import org.eclipse.egit.core.op.PushOperationResult;
import org.eclipse.egit.core.op.PushOperationSpecification;
import org.eclipse.egit.ui.internal.SecureStoreUtils;
import org.eclipse.egit.ui.internal.UIIcons;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.egit.ui.internal.components.RepositorySelection;
import org.eclipse.egit.ui.internal.credentials.EGitCredentialsProvider;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jgit.lib.BranchConfig.BranchRebaseMode;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
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;

/**
 * A wizard dedicated to pushing a commit.
 */
public class PushBranchWizard extends Wizard {

    private final Repository repository;

    private final ObjectId commitToPush;

    /**
     * In case of detached HEAD, reference is null.
     */
    private final Ref ref;

    private AddRemotePage addRemotePage;
    private PushBranchPage pushBranchPage;
    private ConfirmationPage confirmationPage;

    /**
     * @param repository
     *            the repository the ref belongs to
     * @param ref
     */
    public PushBranchWizard(final Repository repository, Ref ref) {
        this(repository, ref.getObjectId(), ref);
    }

    /**
     * @param repository
     *            the repository commit belongs to
     * @param commitToPush
     */
    public PushBranchWizard(final Repository repository, ObjectId commitToPush) {
        this(repository, commitToPush, null);
    }

    private PushBranchWizard(final Repository repository, ObjectId commitToPush, Ref ref) {
        this.repository = repository;
        this.commitToPush = commitToPush;
        this.ref = ref;
        assert (this.repository != null);
        assert (this.commitToPush != null);

        Set<String> remoteNames = repository.getConfig().getSubsections(ConfigConstants.CONFIG_REMOTE_SECTION);
        if (remoteNames.isEmpty())
            addRemotePage = new AddRemotePage(repository);

        pushBranchPage = new PushBranchPage(repository, commitToPush, ref) {
            @Override
            public void setVisible(boolean visible) {
                if (visible && addRemotePage != null) {
                    setSelectedRemote(addRemotePage.getRemoteName(), addRemotePage.getSelection().getURI());
                }
                super.setVisible(visible);
            }
        };
        // Don't show button if we're configuring a remote in the first step
        pushBranchPage.setShowNewRemoteButton(addRemotePage == null);

        confirmationPage = new ConfirmationPage(repository) {
            @Override
            public void setVisible(boolean visible) {
                setSelection(getRepositorySelection(), getRefSpecs());
                AddRemotePage remotePage = getAddRemotePage();
                if (remotePage != null)
                    setCredentials(remotePage.getCredentials());
                super.setVisible(visible);
            }
        };

        setDefaultPageImageDescriptor(UIIcons.WIZBAN_PUSH);
    }

    @Override
    public void addPages() {
        if (addRemotePage != null)
            addPage(addRemotePage);
        addPage(pushBranchPage);
        addPage(confirmationPage);
    }

    @Override
    public String getWindowTitle() {
        if (ref != null)
            return MessageFormat.format(UIText.PushBranchWizard_WindowTitle,
                    Repository.shortenRefName(this.ref.getName()));
        else
            return UIText.PushCommitHandler_pushCommitTitle;
    }

    @Override
    public boolean canFinish() {
        return getContainer().getCurrentPage() == confirmationPage && confirmationPage.isPageComplete();
    }

    @Override
    public boolean performFinish() {
        try {
            AddRemotePage remotePage = getAddRemotePage();
            if (remotePage != null) {
                storeCredentials(remotePage);
                URIish uri = remotePage.getSelection().getURI();
                configureNewRemote(uri);
            }
            if (pushBranchPage.getUpstreamConfig() != null) {
                configureUpstream();
            }
            startPush();
        } catch (IOException e) {
            confirmationPage.setErrorMessage(e.getMessage());
            return false;
        } catch (URISyntaxException e) {
            confirmationPage.setErrorMessage(e.getMessage());
            return false;
        }

        return true;
    }

    private AddRemotePage getAddRemotePage() {
        if (addRemotePage != null)
            return addRemotePage;
        else
            return pushBranchPage.getAddRemotePage();
    }

    private RepositorySelection getRepositorySelection() {
        AddRemotePage remotePage = getAddRemotePage();
        if (remotePage != null)
            return remotePage.getSelection();
        else
            return new RepositorySelection(null, pushBranchPage.getRemoteConfig());
    }

    private List<RefSpec> getRefSpecs() {
        String src = this.ref != null ? this.ref.getName() : this.commitToPush.getName();
        String dst = pushBranchPage.getFullRemoteReference();
        RefSpec refSpec = new RefSpec().setSourceDestination(src, dst)
                .setForceUpdate(pushBranchPage.isForceUpdateSelected());
        return Arrays.asList(refSpec);
    }

    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 = getRemoteName();
        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 {
        if (this.ref == null) {
            // Don't configure upstream for detached HEAD
            return;
        }
        String remoteName = getRemoteName();
        String fullRemoteBranchName = pushBranchPage.getFullRemoteReference();
        String localBranchName = Repository.shortenRefName(this.ref.getName());

        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);
        BranchRebaseMode rebaseMode = pushBranchPage.getUpstreamConfig();
        if (rebaseMode != null) {
            config.setEnum(ConfigConstants.CONFIG_BRANCH_SECTION, localBranchName,
                    ConfigConstants.CONFIG_KEY_REBASE, rebaseMode);
        }

        config.save();
    }

    private void startPush() throws IOException {
        PushOperationResult result = confirmationPage.getConfirmedResult();
        PushOperationSpecification pushSpec = result
                .deriveSpecification(confirmationPage.isRequireUnchangedSelected());

        PushOperationUI pushOperationUI = new PushOperationUI(repository, pushSpec, false);
        pushOperationUI.setCredentialsProvider(new EGitCredentialsProvider());
        pushOperationUI.setShowConfigureButton(false);
        if (confirmationPage.isShowOnlyIfChangedSelected())
            pushOperationUI.setExpectedResult(result);
        pushOperationUI.start();
    }

    private String getRemoteName() {
        return pushBranchPage.getRemoteConfig().getName();
    }
}