| /******************************************************************************* |
| * 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(); |
| } |
| } |