/* * Copyright 2011-2017 Amazon Technologies, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://aws.amazon.com/apache2.0 * * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES * OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and * limitations under the License. */ package com.amazonaws.eclipse.core.egit.jobs; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.net.URISyntaxException; import java.util.Collection; import java.util.Collections; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.egit.core.RepositoryUtil; import org.eclipse.egit.core.op.CloneOperation; import org.eclipse.egit.core.op.ConfigureFetchAfterCloneTask; import org.eclipse.egit.core.op.ConfigurePushAfterCloneTask; import org.eclipse.egit.core.op.SetRepositoryConfigPropertyTask; import org.eclipse.egit.core.securestorage.UserPasswordCredentials; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIPreferences; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.transport.URIish; import org.eclipse.osgi.util.NLS; import org.eclipse.ui.PlatformUI; import com.amazonaws.eclipse.core.AwsToolkitCore; import com.amazonaws.eclipse.core.egit.EGitCredentialsProvider; import com.amazonaws.eclipse.core.egit.GitRepositoryInfo; import com.amazonaws.eclipse.core.egit.SecureStoreUtils; import com.amazonaws.eclipse.core.egit.UIText; import com.amazonaws.eclipse.core.egit.GitRepositoryInfo.PushInfo; import com.amazonaws.eclipse.core.egit.GitRepositoryInfo.RepositoryConfigProperty; import com.amazonaws.eclipse.core.egit.ui.CloneDestinationPage; import com.amazonaws.eclipse.core.egit.ui.SourceBranchPage; /** * A UI sync job that manages cloning a remote Git repository to local. */ @SuppressWarnings("restriction") public class CloneGitRepositoryJob { private final Wizard wizard; private final SourceBranchPage sourceBranchPage; private final CloneDestinationPage cloneDestinationPage; private final GitRepositoryInfo gitRepositoryInfo; public CloneGitRepositoryJob(Wizard wizard, SourceBranchPage sourceBranchPage, CloneDestinationPage cloneDestinationPage, GitRepositoryInfo gitRepositoryInfo) { this.wizard = wizard; this.sourceBranchPage = sourceBranchPage; this.cloneDestinationPage = cloneDestinationPage; this.gitRepositoryInfo = gitRepositoryInfo; } public void execute(IProgressMonitor monitor) { PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { public void run() { try { final CloneOperation cloneOperation = generateCloneOperation(); wizard.getContainer().run(true, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { executeCloneOperation(cloneOperation, monitor); } }); cloneDestinationPage.saveSettingsForClonedRepo(); } catch (Exception e) { AwsToolkitCore.getDefault() .reportException(e.getMessage(), e); } } }); } /** * Do the clone using data which were collected on the pages * {@code validSource} and {@code cloneDestination} * * @param gitRepositoryInfo * @return if clone was successful * @throws URISyntaxException */ private CloneOperation generateCloneOperation() throws URISyntaxException { final boolean allSelected; final Collection<Ref> selectedBranches; if (sourceBranchPage.isSourceRepoEmpty()) { // fetch all branches of empty repo allSelected = true; selectedBranches = Collections.emptyList(); } else { allSelected = sourceBranchPage.isAllSelected(); selectedBranches = sourceBranchPage.getSelectedBranches(); } final File workdir = cloneDestinationPage.getDestinationFile(); boolean created = workdir.exists(); if (!created) created = workdir.mkdirs(); if (!created || !workdir.isDirectory()) { final String errorMessage = NLS.bind( UIText.GitCloneWizard_errorCannotCreate, workdir.getPath()); ErrorDialog.openError(wizard.getShell(), wizard.getWindowTitle(), UIText.GitCloneWizard_failed, new Status(IStatus.ERROR, Activator.getPluginId(), 0, errorMessage, null)); // let's give user a chance to fix this minor problem return null; } return createCloneOperation(allSelected, selectedBranches, workdir, cloneDestinationPage.getInitialBranch(), cloneDestinationPage.getRemote(), cloneDestinationPage.isCloneSubmodules()); } private CloneOperation createCloneOperation( final boolean allSelected, final Collection<Ref> selectedBranches, final File workdir, final Ref ref, final String remoteName, final boolean isCloneSubmodules) throws URISyntaxException { URIish uri = new URIish(gitRepositoryInfo.getCloneUri()); UserPasswordCredentials credentials = gitRepositoryInfo.getCredentials(); int timeout = Activator.getDefault().getPreferenceStore() .getInt(UIPreferences.REMOTE_CONNECTION_TIMEOUT); wizard.setWindowTitle(NLS.bind(UIText.GitCloneWizard_jobName, uri.toString())); final CloneOperation op = new CloneOperation(uri, allSelected, selectedBranches, workdir, ref != null ? ref.getName() : null, remoteName, timeout); if (credentials != null) op.setCredentialsProvider(new EGitCredentialsProvider(credentials .getUser(), credentials.getPassword())); else op.setCredentialsProvider(new EGitCredentialsProvider()); op.setCloneSubmodules(isCloneSubmodules); configureFetchSpec(op, remoteName); configurePush(op, remoteName); configureRepositoryConfig(op); return op; } private void configureFetchSpec(CloneOperation op, String remoteName) { for (String fetchRefSpec : gitRepositoryInfo.getFetchRefSpecs()) op.addPostCloneTask(new ConfigureFetchAfterCloneTask(remoteName, fetchRefSpec)); } private void configurePush(CloneOperation op, String remoteName) { for (PushInfo pushInfo : gitRepositoryInfo.getPushInfos()) try { URIish uri = pushInfo.getPushUri() != null ? new URIish( pushInfo.getPushUri()) : null; ConfigurePushAfterCloneTask task = new ConfigurePushAfterCloneTask( remoteName, pushInfo.getPushRefSpec(), uri); op.addPostCloneTask(task); } catch (URISyntaxException e) { Activator.handleError(UIText.GitCloneWizard_failed, e, true); } } private void configureRepositoryConfig(CloneOperation op) { for (RepositoryConfigProperty p : gitRepositoryInfo .getRepositoryConfigProperties()) { SetRepositoryConfigPropertyTask task = new SetRepositoryConfigPropertyTask( p.getSection(), p.getSubsection(), p.getName(), p.getValue()); op.addPostCloneTask(task); } } private IStatus executeCloneOperation(final CloneOperation op, final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { final RepositoryUtil util = Activator.getDefault().getRepositoryUtil(); op.run(monitor); util.addConfiguredRepository(op.getGitDir()); try { if (gitRepositoryInfo.shouldSaveCredentialsInSecureStore()) SecureStoreUtils.storeCredentials(gitRepositoryInfo.getCredentials(), new URIish(gitRepositoryInfo.getCloneUri())); } catch (Exception e) { AwsToolkitCore.getDefault().logWarning(e.getMessage(), e); } return Status.OK_STATUS; } }