--- /dev/null
+/*******************************************************************************\r
+ * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>\r
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>\r
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>\r
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>\r
+ * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>\r
+ * Copyright (C) 2010, Benjamin Muskalla <bmuskalla@eclipsesource.com>\r
+ * Copyright (C) 2012, Stefan Lay <stefan.lay@sap.com>\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.egit.ui.internal.clone;\r
+\r
+import java.io.File;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.net.URISyntaxException;\r
+import java.text.MessageFormat;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.LinkedHashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.eclipse.core.resources.WorkspaceJob;\r
+import org.eclipse.core.runtime.CoreException;\r
+import org.eclipse.core.runtime.IProgressMonitor;\r
+import org.eclipse.core.runtime.IStatus;\r
+import org.eclipse.core.runtime.Status;\r
+import org.eclipse.core.runtime.jobs.Job;\r
+import org.eclipse.egit.core.RepositoryUtil;\r
+import org.eclipse.egit.core.internal.util.ProjectUtil;\r
+import org.eclipse.egit.core.op.CloneOperation;\r
+import org.eclipse.egit.core.op.CloneOperation.PostCloneTask;\r
+import org.eclipse.egit.core.op.ConfigureFetchAfterCloneTask;\r
+import org.eclipse.egit.core.op.ConfigureGerritAfterCloneTask;\r
+import org.eclipse.egit.core.op.ConfigurePushAfterCloneTask;\r
+import org.eclipse.egit.core.op.SetRepositoryConfigPropertyTask;\r
+import org.eclipse.egit.core.securestorage.UserPasswordCredentials;\r
+import org.eclipse.egit.ui.Activator;\r
+import org.eclipse.egit.ui.JobFamilies;\r
+import org.eclipse.egit.ui.UIPreferences;\r
+import org.eclipse.egit.ui.internal.SecureStoreUtils;\r
+import org.eclipse.egit.ui.internal.UIText;\r
+import org.eclipse.egit.ui.internal.clone.GitCloneSourceProviderExtension.CloneSourceProvider;\r
+import org.eclipse.egit.ui.internal.components.RepositorySelection;\r
+import org.eclipse.egit.ui.internal.credentials.EGitCredentialsProvider;\r
+import org.eclipse.egit.ui.internal.provisional.wizards.GitRepositoryInfo;\r
+import org.eclipse.egit.ui.internal.provisional.wizards.GitRepositoryInfo.PushInfo;\r
+import org.eclipse.egit.ui.internal.provisional.wizards.GitRepositoryInfo.RepositoryConfigProperty;\r
+import org.eclipse.egit.ui.internal.provisional.wizards.IRepositorySearchResult;\r
+import org.eclipse.egit.ui.internal.provisional.wizards.NoRepositoryInfoException;\r
+import org.eclipse.jface.dialogs.ErrorDialog;\r
+import org.eclipse.jface.operation.IRunnableWithProgress;\r
+import org.eclipse.jface.wizard.IWizardContainer;\r
+import org.eclipse.jface.wizard.IWizardPage;\r
+import org.eclipse.jface.wizard.Wizard;\r
+import org.eclipse.jface.wizard.WizardPage;\r
+import org.eclipse.jgit.lib.Ref;\r
+import org.eclipse.jgit.lib.Repository;\r
+import org.eclipse.jgit.transport.CredentialsProvider;\r
+import org.eclipse.jgit.transport.URIish;\r
+import org.eclipse.osgi.util.NLS;\r
+import org.eclipse.ui.IWorkingSet;\r
+\r
+/**\r
+ * Implements the basic functionality of a clone wizard\r
+ */\r
+public abstract class AbstractRtGitCloneWizard extends Wizard {\r
+\r
+ /**\r
+ * a page for branch selection\r
+ */\r
+ protected RtSourceBranchPage validSource;\r
+\r
+ /**\r
+ * a page for selection of the clone destination\r
+ */\r
+ protected RtCloneDestinationPage cloneDestination;\r
+\r
+ /**\r
+ * the path where a clone has been created in\r
+ */\r
+ protected String alreadyClonedInto;\r
+\r
+ /**\r
+ * whether the clone operation is done later on by the caller of the wizard\r
+ */\r
+ protected boolean callerRunsCloneOperation;\r
+\r
+ /**\r
+ * the result which was found when the last search was done\r
+ */\r
+ protected IRepositorySearchResult currentSearchResult;\r
+\r
+ private CloneOperation cloneOperation;\r
+\r
+ /**\r
+ * Construct the clone wizard based on given repository search result. If the search result is an instance of org.eclipse.jface.wizard.WizardPage, then the page is shown in the wizard before the\r
+ * repository info is read. The repository location page that allows the repository info to be provided by different search providers is not shown.\r
+ * @param searchResult the search result to initialize the clone wizard with.\r
+ */\r
+ public AbstractRtGitCloneWizard(IRepositorySearchResult searchResult) {\r
+ this();\r
+ this.currentSearchResult = searchResult;\r
+ }\r
+\r
+ /**\r
+ * Construct the clone wizard with a repository location page that allows the repository info to be provided by different search providers.\r
+ */\r
+ public AbstractRtGitCloneWizard() {\r
+ setNeedsProgressMonitor(true);\r
+ validSource = new RtSourceBranchPage() {\r
+\r
+ @Override\r
+ public void setVisible(boolean visible) {\r
+ if (visible) {\r
+ setSelection(getRepositorySelection());\r
+ setCredentials(getCredentials());\r
+ }\r
+ super.setVisible(visible);\r
+ }\r
+ };\r
+ cloneDestination = new RtCloneDestinationPage() {\r
+ @Override\r
+ public void setVisible(boolean visible) {\r
+ if (visible)\r
+ setSelection(getRepositorySelection(),\r
+ validSource.getAvailableBranches(),\r
+ validSource.getSelectedBranches(),\r
+ validSource.getHEAD());\r
+ super.setVisible(visible);\r
+ }\r
+ };\r
+ }\r
+\r
+ /**\r
+ * subclasses may add pages to the Wizard which will be shown before the clone step\r
+ */\r
+ protected abstract void addPreClonePages();\r
+\r
+ /**\r
+ * subclasses may add pages to the Wizard which will be shown after the clone step\r
+ */\r
+ protected abstract void addPostClonePages();\r
+\r
+ @Override\r
+ final public void addPages() {\r
+ if (hasSearchResult())\r
+ addRepositorySearchPage();\r
+ else\r
+ addRepositoryLocationPage();\r
+ addPreClonePages();\r
+ addPage(validSource);\r
+ addPage(cloneDestination);\r
+ addPostClonePages();\r
+ }\r
+\r
+ /**\r
+ * @return if the search result is set\r
+ */\r
+ protected boolean hasSearchResult() {\r
+ return currentSearchResult != null;\r
+ }\r
+\r
+ private void addRepositorySearchPage() {\r
+ if (currentSearchResult instanceof WizardPage)\r
+ addPage((WizardPage) currentSearchResult);\r
+ }\r
+\r
+ private void addRepositoryLocationPage() {\r
+ List<CloneSourceProvider> cloneSourceProviders = getCloneSourceProviders();\r
+ if (hasSingleCloneSourceProviderWithFixedLocation(cloneSourceProviders))\r
+ try {\r
+ addPage(cloneSourceProviders.get(0).getRepositorySearchPage());\r
+ } catch (CoreException e) {\r
+ Activator.logError(e.getLocalizedMessage(), e);\r
+ }\r
+ else\r
+ addPage(new RepositoryLocationPage(cloneSourceProviders));\r
+ }\r
+\r
+ private boolean hasSingleCloneSourceProviderWithFixedLocation(\r
+ List<CloneSourceProvider> cloneSourceProviders) {\r
+ return cloneSourceProviders.size() == 1 && cloneSourceProviders.get(0).hasFixLocation();\r
+ }\r
+\r
+ /**\r
+ * @return a list of CloneSourceProviders, may be extended by a subclass\r
+ */\r
+ protected List<CloneSourceProvider> getCloneSourceProviders() {\r
+ return GitCloneSourceProviderExtension.getCloneSourceProvider();\r
+ }\r
+\r
+ /**\r
+ * Do the clone using data which were collected on the pages {@code validSource} and {@code cloneDestination}\r
+ * @param gitRepositoryInfo\r
+ * @return if clone was successful\r
+ * @throws URISyntaxException\r
+ */\r
+ protected boolean performClone(GitRepositoryInfo gitRepositoryInfo) throws URISyntaxException {\r
+ URIish uri = new URIish(gitRepositoryInfo.getCloneUri());\r
+ UserPasswordCredentials credentials = gitRepositoryInfo.getCredentials();\r
+ setWindowTitle(NLS.bind(UIText.GitCloneWizard_jobName, uri.toString()));\r
+ final boolean allSelected;\r
+ final Collection<Ref> selectedBranches;\r
+ if (validSource.isSourceRepoEmpty()) {\r
+ // fetch all branches of empty repo\r
+ allSelected = true;\r
+ selectedBranches = Collections.emptyList();\r
+ } else {\r
+ allSelected = validSource.isAllSelected();\r
+ selectedBranches = validSource.getSelectedBranches();\r
+ }\r
+ final File workdir = cloneDestination.getDestinationFile();\r
+ final Ref ref = cloneDestination.getInitialBranch();\r
+ final String remoteName = cloneDestination.getRemote();\r
+\r
+ boolean created = workdir.exists();\r
+ if (!created)\r
+ created = workdir.mkdirs();\r
+\r
+ if (!created || !workdir.isDirectory()) {\r
+ final String errorMessage = NLS.bind(\r
+ UIText.GitCloneWizard_errorCannotCreate, workdir.getPath());\r
+ ErrorDialog.openError(getShell(), getWindowTitle(),\r
+ UIText.GitCloneWizard_failed, new Status(IStatus.ERROR,\r
+ Activator.getPluginId(), 0, errorMessage, null));\r
+ // let's give user a chance to fix this minor problem\r
+ return false;\r
+ }\r
+\r
+ int timeout = Activator.getDefault().getPreferenceStore()\r
+ .getInt(UIPreferences.REMOTE_CONNECTION_TIMEOUT);\r
+ final CloneOperation op = new CloneOperation(uri, allSelected,\r
+ selectedBranches, workdir, ref != null ? ref.getName() : null,\r
+ remoteName, timeout);\r
+ CredentialsProvider credentialsProvider = null;\r
+ if (credentials != null) {\r
+ credentialsProvider = new EGitCredentialsProvider(\r
+ credentials.getUser(), credentials.getPassword());\r
+ } else {\r
+ credentialsProvider = new EGitCredentialsProvider();\r
+ }\r
+ op.setCredentialsProvider(credentialsProvider);\r
+ op.setCloneSubmodules(cloneDestination.isCloneSubmodules());\r
+\r
+ configureFetchSpec(op, gitRepositoryInfo, remoteName);\r
+ configurePush(op, gitRepositoryInfo, remoteName);\r
+ configureRepositoryConfig(op, gitRepositoryInfo);\r
+ configureGerrit(op, gitRepositoryInfo, credentialsProvider, remoteName,\r
+ timeout);\r
+\r
+ if (cloneDestination.isImportProjects()) {\r
+ final IWorkingSet[] sets = cloneDestination.getWorkingSets();\r
+ op.addPostCloneTask(new PostCloneTask() {\r
+ @Override\r
+ public void execute(Repository repository,\r
+ IProgressMonitor monitor) throws CoreException {\r
+ importProjects(repository, sets);\r
+ }\r
+ });\r
+ }\r
+\r
+ alreadyClonedInto = workdir.getPath();\r
+\r
+ if (!callerRunsCloneOperation)\r
+ runAsJob(uri, op, gitRepositoryInfo);\r
+ else\r
+ cloneOperation = op;\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public IWizardPage getNextPage(IWizardPage page) {\r
+ if (page instanceof IRepositorySearchResult) {\r
+ currentSearchResult = (IRepositorySearchResult) page;\r
+ return validSource;\r
+ }\r
+ return super.getNextPage(page);\r
+ }\r
+\r
+ /**\r
+ * @return the repository selected by the user\r
+ */\r
+ protected RepositorySelection getRepositorySelection() {\r
+ try {\r
+ return (new RepositorySelection(new URIish(currentSearchResult.getGitRepositoryInfo().getCloneUri()), null));\r
+ } catch (URISyntaxException e) {\r
+ Activator.error(UIText.GitImportWizard_errorParsingURI, e);\r
+ return null;\r
+ } catch (NoRepositoryInfoException e) {\r
+ Activator.error(UIText.GitImportWizard_noRepositoryInfo, e);\r
+ return null;\r
+ } catch (Exception e) {\r
+ Activator.error(e.getMessage(), e);\r
+ return null;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @return the credentials\r
+ */\r
+ protected UserPasswordCredentials getCredentials() {\r
+ try {\r
+ return currentSearchResult.getGitRepositoryInfo().getCredentials();\r
+ } catch (NoRepositoryInfoException e) {\r
+ Activator.error(UIText.GitImportWizard_noRepositoryInfo, e);\r
+ return null;\r
+ } catch (Exception e) {\r
+ Activator.error(e.getMessage(), e);\r
+ return null;\r
+ }\r
+ }\r
+\r
+ private void configureFetchSpec(CloneOperation op,\r
+ GitRepositoryInfo gitRepositoryInfo, String remoteName) {\r
+ for (String fetchRefSpec : gitRepositoryInfo.getFetchRefSpecs())\r
+ op.addPostCloneTask(new ConfigureFetchAfterCloneTask(remoteName, fetchRefSpec));\r
+ }\r
+\r
+ private void configurePush(CloneOperation op,\r
+ GitRepositoryInfo gitRepositoryInfo, String remoteName) {\r
+ for (PushInfo pushInfo : gitRepositoryInfo.getPushInfos())\r
+ try {\r
+ URIish uri = pushInfo.getPushUri() != null ? new URIish(\r
+ pushInfo.getPushUri()) : null;\r
+ ConfigurePushAfterCloneTask task = new ConfigurePushAfterCloneTask(\r
+ remoteName, pushInfo.getPushRefSpec(), uri);\r
+ op.addPostCloneTask(task);\r
+ } catch (URISyntaxException e) {\r
+ Activator.handleError(UIText.GitCloneWizard_failed, e, true);\r
+ }\r
+ }\r
+\r
+ private void configureRepositoryConfig(CloneOperation op, GitRepositoryInfo gitRepositoryInfo) {\r
+ for (RepositoryConfigProperty p : gitRepositoryInfo.getRepositoryConfigProperties()) {\r
+ SetRepositoryConfigPropertyTask task = new SetRepositoryConfigPropertyTask(\r
+ p.getSection(), p.getSubsection(), p.getName(),\r
+ p.getValue());\r
+ op.addPostCloneTask(task);\r
+ }\r
+ }\r
+\r
+ private void configureGerrit(CloneOperation op,\r
+ GitRepositoryInfo gitRepositoryInfo,\r
+ CredentialsProvider credentialsProvider, String remoteName,\r
+ int timeout) {\r
+ ConfigureGerritAfterCloneTask task = new ConfigureGerritAfterCloneTask(\r
+ gitRepositoryInfo.getCloneUri(), remoteName,\r
+ credentialsProvider, timeout);\r
+ op.addPostCloneTask(task);\r
+ }\r
+\r
+ private void importProjects(final Repository repository,\r
+ final IWorkingSet[] sets) {\r
+ String repoName = Activator.getDefault().getRepositoryUtil()\r
+ .getRepositoryName(repository);\r
+ Job importJob = new WorkspaceJob(MessageFormat.format(\r
+ UIText.GitCloneWizard_jobImportProjects, repoName)) {\r
+\r
+ @Override\r
+ public IStatus runInWorkspace(IProgressMonitor monitor) {\r
+ List<File> files = new ArrayList<File>();\r
+ ProjectUtil.findProjectFiles(files, repository.getWorkTree(),\r
+ true, monitor);\r
+ if (files.isEmpty())\r
+ return Status.OK_STATUS;\r
+\r
+ Set<ProjectRecord> records = new LinkedHashSet<ProjectRecord>();\r
+ for (File file : files)\r
+ records.add(new ProjectRecord(file));\r
+ try {\r
+ ProjectUtils.createProjects(records, sets, monitor);\r
+ } catch (InvocationTargetException e) {\r
+ Activator.logError(e.getLocalizedMessage(), e);\r
+ } catch (InterruptedException e) {\r
+ Activator.logError(e.getLocalizedMessage(), e);\r
+ }\r
+ return Status.OK_STATUS;\r
+ }\r
+ };\r
+ importJob.schedule();\r
+ }\r
+\r
+ /**\r
+ * @param container\r
+ * @param repositoryInfo\r
+ */\r
+ public void runCloneOperation(IWizardContainer container, final GitRepositoryInfo repositoryInfo) {\r
+ try {\r
+ container.run(true, true, new IRunnableWithProgress() {\r
+ @Override\r
+ public void run(IProgressMonitor monitor)\r
+ throws InvocationTargetException, InterruptedException {\r
+ executeCloneOperation(cloneOperation, repositoryInfo, monitor);\r
+ }\r
+ });\r
+ } catch (InvocationTargetException e) {\r
+ Activator.handleError(UIText.GitCloneWizard_failed, e.getCause(),\r
+ true);\r
+ } catch (InterruptedException e) {\r
+ // nothing to do\r
+ }\r
+ }\r
+\r
+ private void runAsJob(final URIish uri, final CloneOperation op,\r
+ final GitRepositoryInfo repositoryInfo) {\r
+ final Job job = new Job(NLS.bind(UIText.GitCloneWizard_jobName,\r
+ uri.toString())) {\r
+ @Override\r
+ protected IStatus run(final IProgressMonitor monitor) {\r
+ try {\r
+ return executeCloneOperation(op, repositoryInfo, monitor);\r
+ } catch (InterruptedException e) {\r
+ return Status.CANCEL_STATUS;\r
+ } catch (InvocationTargetException e) {\r
+ Throwable thr = e.getCause();\r
+ return new Status(IStatus.ERROR, Activator.getPluginId(),\r
+ 0, thr.getMessage(), thr);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public boolean belongsTo(Object family) {\r
+ if (JobFamilies.CLONE.equals(family))\r
+ return true;\r
+ return super.belongsTo(family);\r
+ }\r
+ };\r
+ job.setUser(true);\r
+ job.schedule();\r
+ }\r
+\r
+ private IStatus executeCloneOperation(final CloneOperation op,\r
+ final GitRepositoryInfo repositoryInfo,\r
+ final IProgressMonitor monitor) throws InvocationTargetException,\r
+ InterruptedException {\r
+\r
+ final RepositoryUtil util = Activator.getDefault().getRepositoryUtil();\r
+\r
+ op.run(monitor);\r
+ util.addConfiguredRepository(op.getGitDir());\r
+ try {\r
+ if (repositoryInfo.shouldSaveCredentialsInSecureStore())\r
+ SecureStoreUtils.storeCredentials(repositoryInfo.getCredentials(),\r
+ new URIish(repositoryInfo.getCloneUri()));\r
+ } catch (Exception e) {\r
+ Activator.error(e.getMessage(), e);\r
+ }\r
+ return Status.OK_STATUS;\r
+ }\r
+\r
+ /**\r
+ * @param newValue if true the clone wizard just creates a clone operation. The caller has to run this operation using runCloneOperation. If false the clone operation is performed using a job.\r
+ */\r
+ public void setCallerRunsCloneOperation(boolean newValue) {\r
+ callerRunsCloneOperation = newValue;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>\r
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>\r
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>\r
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>\r
+ * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>\r
+ * Copyright (C) 2013, Robin Stocker <robin@nibor.org>\r
+ *\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *******************************************************************************/\r
+package org.eclipse.egit.ui.internal.clone;\r
+\r
+import java.io.File;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.eclipse.egit.core.RepositoryUtil;\r
+import org.eclipse.egit.ui.Activator;\r
+import org.eclipse.egit.ui.UIPreferences;\r
+import org.eclipse.egit.ui.internal.UIText;\r
+import org.eclipse.egit.ui.internal.components.RepositorySelection;\r
+import org.eclipse.jface.dialogs.Dialog;\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.viewers.ArrayContentProvider;\r
+import org.eclipse.jface.viewers.ComboViewer;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.jface.viewers.LabelProvider;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.jface.wizard.WizardPage;\r
+import org.eclipse.jgit.lib.Constants;\r
+import org.eclipse.jgit.lib.Ref;\r
+import org.eclipse.jgit.lib.Repository;\r
+import org.eclipse.osgi.util.NLS;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.FileDialog;\r
+import org.eclipse.swt.widgets.Group;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.eclipse.ui.IWorkingSet;\r
+import org.eclipse.ui.PlatformUI;\r
+import org.eclipse.ui.dialogs.WorkingSetGroup;\r
+\r
+/**\r
+ * Wizard page that allows the user entering the location of a repository to be cloned.\r
+ */\r
+public class RtCloneDestinationPage extends WizardPage {\r
+\r
+ private final List<Ref> availableRefs = new ArrayList<Ref>();\r
+\r
+ private RepositorySelection validatedRepoSelection;\r
+\r
+ private List<Ref> validatedSelectedBranches;\r
+\r
+ private Ref validatedHEAD;\r
+\r
+ private boolean showProjectImport;\r
+\r
+ private ComboViewer initialBranch;\r
+\r
+ private Text directoryText;\r
+\r
+ private Text remoteText;\r
+\r
+ private Button importProjectsButton;\r
+\r
+ private Button cloneSubmodulesButton;\r
+\r
+ private WorkingSetGroup workingSetGroup;\r
+\r
+ private String helpContext = null;\r
+\r
+ private File clonedDestination;\r
+\r
+ private Ref clonedInitialBranch;\r
+\r
+ private String clonedRemote;\r
+\r
+ RtCloneDestinationPage() {\r
+ super(RtCloneDestinationPage.class.getName());\r
+ setTitle(UIText.CloneDestinationPage_title);\r
+ }\r
+\r
+ @Override\r
+ public void createControl(final Composite parent) {\r
+ final Composite panel = new Composite(parent, SWT.NULL);\r
+ final GridLayout layout = new GridLayout();\r
+ layout.numColumns = 1;\r
+ panel.setLayout(layout);\r
+\r
+ createDestinationGroup(panel);\r
+ createConfigGroup(panel);\r
+ if (showProjectImport)\r
+ createProjectGroup(panel);\r
+\r
+ Dialog.applyDialogFont(panel);\r
+ setControl(panel);\r
+ checkPage();\r
+ }\r
+\r
+ @Override\r
+ public void setVisible(final boolean visible) {\r
+ if (visible)\r
+ if (this.availableRefs.isEmpty())\r
+ initialBranch.getCombo().setEnabled(false);\r
+ super.setVisible(visible);\r
+ if (visible)\r
+ directoryText.setFocus();\r
+ }\r
+\r
+ /**\r
+ * @param repositorySelection selection of remote repository made by user\r
+ * @param availableRefs all available refs\r
+ * @param branches branches selected to be cloned\r
+ * @param head HEAD in source repository\r
+ */\r
+ public void setSelection(RepositorySelection repositorySelection, List<Ref> availableRefs, List<Ref> branches, Ref head) {\r
+ this.availableRefs.clear();\r
+ this.availableRefs.addAll(availableRefs);\r
+ checkPreviousPagesSelections(repositorySelection, branches, head);\r
+ revalidate(repositorySelection, branches, head);\r
+ }\r
+\r
+ private void checkPreviousPagesSelections(\r
+ RepositorySelection repositorySelection, List<Ref> branches,\r
+ Ref head) {\r
+ if (!repositorySelection.equals(validatedRepoSelection)\r
+ || !branches.equals(validatedSelectedBranches)\r
+ || !head.equals(validatedHEAD))\r
+ setPageComplete(false);\r
+ else\r
+ checkPage();\r
+ }\r
+\r
+ private void createDestinationGroup(final Composite parent) {\r
+ final Group g = createGroup(parent,\r
+ UIText.CloneDestinationPage_groupDestination);\r
+\r
+ Label dirLabel = new Label(g, SWT.NONE);\r
+ dirLabel.setText(UIText.CloneDestinationPage_promptDirectory + ":"); //$NON-NLS-1$\r
+ dirLabel\r
+ .setToolTipText(UIText.CloneDestinationPage_DefaultRepoFolderTooltip);\r
+ final Composite p = new Composite(g, SWT.NONE);\r
+ final GridLayout grid = new GridLayout();\r
+ grid.numColumns = 2;\r
+ p.setLayout(grid);\r
+ p.setLayoutData(createFieldGridData());\r
+ directoryText = new Text(p, SWT.BORDER);\r
+ directoryText.setLayoutData(createFieldGridData());\r
+ directoryText.addModifyListener(new ModifyListener() {\r
+ @Override\r
+ public void modifyText(final ModifyEvent e) {\r
+ checkPage();\r
+ }\r
+ });\r
+ final Button b = new Button(p, SWT.PUSH);\r
+ b.setText(UIText.CloneDestinationPage_browseButton);\r
+ b.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(final SelectionEvent e) {\r
+ final FileDialog d;\r
+\r
+ d = new FileDialog(getShell(), SWT.APPLICATION_MODAL | SWT.SAVE);\r
+ if (directoryText.getText().length() > 0) {\r
+ final File file = new File(directoryText.getText())\r
+ .getAbsoluteFile();\r
+ d.setFilterPath(file.getParent());\r
+ d.setFileName(file.getName());\r
+ }\r
+ final String r = d.open();\r
+ if (r != null)\r
+ directoryText.setText(r);\r
+ }\r
+ });\r
+\r
+ newLabel(g, UIText.CloneDestinationPage_promptInitialBranch + ":"); //$NON-NLS-1$\r
+ initialBranch = new ComboViewer(g, SWT.DROP_DOWN | SWT.READ_ONLY);\r
+ initialBranch.getCombo().setLayoutData(createFieldGridData());\r
+ initialBranch.getCombo().addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(final SelectionEvent e) {\r
+ checkPage();\r
+ }\r
+ });\r
+ initialBranch.setContentProvider(ArrayContentProvider.getInstance());\r
+ initialBranch.setLabelProvider(new LabelProvider() {\r
+ @Override\r
+ public String getText(Object element) {\r
+ if (((Ref) element).getName().startsWith(Constants.R_HEADS))\r
+ return ((Ref) element).getName().substring(Constants.R_HEADS.length());\r
+ return ((Ref) element).getName();\r
+ }\r
+ });\r
+\r
+ cloneSubmodulesButton = new Button(g, SWT.CHECK);\r
+ cloneSubmodulesButton\r
+ .setText(UIText.CloneDestinationPage_cloneSubmodulesButton);\r
+ GridDataFactory.swtDefaults().span(2, 1).applyTo(cloneSubmodulesButton);\r
+ }\r
+\r
+ private void createConfigGroup(final Composite parent) {\r
+ final Group g = createGroup(parent,\r
+ UIText.CloneDestinationPage_groupConfiguration);\r
+\r
+ newLabel(g, UIText.CloneDestinationPage_promptRemoteName + ":"); //$NON-NLS-1$\r
+ remoteText = new Text(g, SWT.BORDER);\r
+ remoteText.setText(Constants.DEFAULT_REMOTE_NAME);\r
+ remoteText.setLayoutData(createFieldGridData());\r
+ remoteText.addModifyListener(new ModifyListener() {\r
+ @Override\r
+ public void modifyText(ModifyEvent e) {\r
+ checkPage();\r
+ }\r
+ });\r
+ }\r
+\r
+ private void createProjectGroup(final Composite parent) {\r
+ final Group group = createGroup(parent,\r
+ UIText.CloneDestinationPage_groupProjects);\r
+\r
+ GridLayoutFactory.swtDefaults().applyTo(group);\r
+ importProjectsButton = new Button(group, SWT.CHECK);\r
+ importProjectsButton.setText(UIText.CloneDestinationPage_importButton);\r
+ importProjectsButton.setSelection(Activator.getDefault()\r
+ .getPreferenceStore()\r
+ .getBoolean(UIPreferences.CLONE_WIZARD_IMPORT_PROJECTS));\r
+ importProjectsButton.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ Activator\r
+ .getDefault()\r
+ .getPreferenceStore()\r
+ .setValue(UIPreferences.CLONE_WIZARD_IMPORT_PROJECTS,\r
+ importProjectsButton.getSelection());\r
+ }\r
+ });\r
+\r
+ // TODO: replace hardcoded ids once bug 245106 is fixed\r
+ String[] workingSetTypes = new String[] {\r
+ "org.eclipse.ui.resourceWorkingSetPage", //$NON-NLS-1$\r
+ "org.eclipse.jdt.ui.JavaWorkingSetPage" //$NON-NLS-1$\r
+ };\r
+ workingSetGroup = new WorkingSetGroup(group, null, workingSetTypes);\r
+ }\r
+\r
+ private static Group createGroup(final Composite parent, final String text) {\r
+ final Group g = new Group(parent, SWT.NONE);\r
+ final GridLayout layout = new GridLayout();\r
+ layout.numColumns = 2;\r
+ g.setLayout(layout);\r
+ g.setText(text);\r
+ final GridData gd = new GridData();\r
+ gd.grabExcessHorizontalSpace = true;\r
+ gd.horizontalAlignment = SWT.FILL;\r
+ g.setLayoutData(gd);\r
+ return g;\r
+ }\r
+\r
+ private static void newLabel(final Group g, final String text) {\r
+ new Label(g, SWT.NULL).setText(text);\r
+ }\r
+\r
+ private static GridData createFieldGridData() {\r
+ return new GridData(SWT.FILL, SWT.DEFAULT, true, false);\r
+ }\r
+\r
+ /**\r
+ * @return true to import projects, false otherwise\r
+ */\r
+ public boolean isImportProjects() {\r
+ return importProjectsButton != null\r
+ && importProjectsButton.getSelection();\r
+ }\r
+\r
+ /**\r
+ * @return true to clone submodules, false otherwise\r
+ */\r
+ public boolean isCloneSubmodules() {\r
+ return cloneSubmodulesButton != null\r
+ && cloneSubmodulesButton.getSelection();\r
+ }\r
+\r
+ /**\r
+ * @return selected working sets\r
+ */\r
+ public IWorkingSet[] getWorkingSets() {\r
+ if (workingSetGroup == null)\r
+ return new IWorkingSet[0];\r
+ return workingSetGroup.getSelectedWorkingSets();\r
+ }\r
+\r
+ /**\r
+ * @return location the user wants to store this repository.\r
+ */\r
+ public File getDestinationFile() {\r
+ return new File(directoryText.getText());\r
+ }\r
+\r
+ /**\r
+ * @return initial branch selected (includes refs/heads prefix).\r
+ */\r
+ public Ref getInitialBranch() {\r
+ IStructuredSelection selection = (IStructuredSelection) initialBranch.getSelection();\r
+ return (Ref) selection.getFirstElement();\r
+ }\r
+\r
+ /**\r
+ * @return remote name\r
+ */\r
+ public String getRemote() {\r
+ return remoteText.getText().trim();\r
+ }\r
+\r
+ /**\r
+ * Set the ID for context sensitive help\r
+ * @param id help context\r
+ */\r
+ public void setHelpContext(String id) {\r
+ helpContext = id;\r
+ }\r
+\r
+ @Override\r
+ public void performHelp() {\r
+ PlatformUI.getWorkbench().getHelpSystem().displayHelp(helpContext);\r
+ }\r
+\r
+ /**\r
+ * Check internal state for page completion status.\r
+ */\r
+ private void checkPage() {\r
+ if (!cloneSettingsChanged()) {\r
+ setErrorMessage(null);\r
+ setPageComplete(true);\r
+ return;\r
+ }\r
+ final String dstpath = directoryText.getText();\r
+ if (dstpath.length() == 0) {\r
+ setErrorMessage(UIText.CloneDestinationPage_errorDirectoryRequired);\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+ final File absoluteFile = new File(dstpath).getAbsoluteFile();\r
+ if (!isEmptyDir(absoluteFile)) {\r
+ setErrorMessage(NLS.bind(\r
+ UIText.CloneDestinationPage_errorNotEmptyDir, absoluteFile\r
+ .getPath()));\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+\r
+ if (!canCreateSubdir(absoluteFile.getParentFile())) {\r
+ setErrorMessage(NLS.bind(UIText.GitCloneWizard_errorCannotCreate,\r
+ absoluteFile.getPath()));\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+ if (!availableRefs.isEmpty()\r
+ && initialBranch.getCombo().getSelectionIndex() < 0) {\r
+ setErrorMessage(UIText.CloneDestinationPage_errorInitialBranchRequired);\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+ String remoteName = getRemote();\r
+ if (remoteName.length() == 0) {\r
+ setErrorMessage(UIText.CloneDestinationPage_errorRemoteNameRequired);\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+ if (!Repository.isValidRefName(Constants.R_REMOTES + remoteName)) {\r
+ setErrorMessage(NLS.bind(\r
+ UIText.CloneDestinationPage_errorInvalidRemoteName,\r
+ remoteName));\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+\r
+ setErrorMessage(null);\r
+ setPageComplete(true);\r
+ }\r
+\r
+ void saveSettingsForClonedRepo() {\r
+ clonedDestination = getDestinationFile();\r
+ clonedInitialBranch = getInitialBranch();\r
+ clonedRemote = getRemote();\r
+ }\r
+\r
+ /**\r
+ * @return whether user updated clone settings\r
+ * @since 4.0.0\r
+ */\r
+ public boolean cloneSettingsChanged() {\r
+ boolean cloneSettingsChanged = false;\r
+ if (clonedDestination == null || !clonedDestination.equals(getDestinationFile()) ||\r
+ clonedInitialBranch == null || !clonedInitialBranch.equals(getInitialBranch()) ||\r
+ clonedRemote == null || !clonedRemote.equals(getRemote()))\r
+ cloneSettingsChanged = true;\r
+ return cloneSettingsChanged;\r
+ }\r
+\r
+ private static boolean isEmptyDir(final File dir) {\r
+ if (!dir.exists())\r
+ return true;\r
+ if (!dir.isDirectory())\r
+ return false;\r
+ return dir.listFiles().length == 0;\r
+ }\r
+\r
+ // this is actually just an optimistic heuristic - should be named\r
+ // isThereHopeThatCanCreateSubdir() as probably there is no 100% reliable\r
+ // way to check that in Java for Windows\r
+ private static boolean canCreateSubdir(final File parent) {\r
+ if (parent == null)\r
+ return true;\r
+ if (parent.exists())\r
+ return parent.isDirectory() && parent.canWrite();\r
+ return canCreateSubdir(parent.getParentFile());\r
+ }\r
+\r
+ private void revalidate(RepositorySelection repoSelection, List<Ref> branches, Ref head) {\r
+ if (repoSelection.equals(validatedRepoSelection)\r
+ && branches.equals(validatedSelectedBranches)\r
+ && head.equals(validatedHEAD)) {\r
+ checkPage();\r
+ return;\r
+ }\r
+\r
+ if (!repoSelection.equals(validatedRepoSelection)) {\r
+ validatedRepoSelection = repoSelection;\r
+ // update repo-related selection only if it changed\r
+ final String n = validatedRepoSelection.getURI().getHumanishName();\r
+ setDescription(NLS.bind(UIText.CloneDestinationPage_description, n));\r
+ String defaultRepoDir = RepositoryUtil.getDefaultRepositoryDir();\r
+ File parentDir = new File(defaultRepoDir);\r
+ directoryText.setText(new File(parentDir, n).getAbsolutePath());\r
+ }\r
+\r
+ validatedSelectedBranches = branches;\r
+ validatedHEAD = head;\r
+\r
+ initialBranch.setInput(branches);\r
+ if (head != null && branches.contains(head))\r
+ initialBranch.setSelection(new StructuredSelection(head));\r
+ else if (branches.size() > 0)\r
+ initialBranch\r
+ .setSelection(new StructuredSelection(branches.get(0)));\r
+ checkPage();\r
+ }\r
+\r
+ /**\r
+ * Set whether to show project import options\r
+ * @param show\r
+ * @return this wizard page\r
+ */\r
+ public RtCloneDestinationPage setShowProjectImport(boolean show) {\r
+ showProjectImport = show;\r
+ return this;\r
+ }\r
+}\r
/**
* A wizard which allows to optionally clone a repository and to import projects from a repository.
*/
-public class RtGitImportWizard extends AbstractGitCloneWizard implements IImportWizard {
+public class RtGitImportWizard extends AbstractRtGitCloneWizard implements IImportWizard {
private static final Logger logger = LoggerFactory.getLogger(RtGitImportWizard.class);
break;
}
}
+
+ // Modified
if (project != null) {
try {
RtProjectNature.makeRtProject(project, monitor);
--- /dev/null
+/*******************************************************************************\r
+ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>\r
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>\r
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>\r
+ * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>\r
+ * Copyright (c) 2010, Benjamin Muskalla <bmuskalla@eclipsesource.com>\r
+ * Copyright (c) 2012, IBM Corporation\r
+ *\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *******************************************************************************/\r
+package org.eclipse.egit.ui.internal.clone;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.lang.reflect.InvocationTargetException;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Collections;\r
+import java.util.Comparator;\r
+import java.util.List;\r
+\r
+import org.eclipse.core.runtime.IProgressMonitor;\r
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;\r
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;\r
+import org.eclipse.egit.core.op.ListRemoteOperation;\r
+import org.eclipse.egit.core.securestorage.UserPasswordCredentials;\r
+import org.eclipse.egit.ui.Activator;\r
+import org.eclipse.egit.ui.UIPreferences;\r
+import org.eclipse.egit.ui.internal.UIText;\r
+import org.eclipse.egit.ui.internal.components.CachedCheckboxTreeViewer;\r
+import org.eclipse.egit.ui.internal.components.FilteredCheckboxTree;\r
+import org.eclipse.egit.ui.internal.components.RepositorySelection;\r
+import org.eclipse.egit.ui.internal.credentials.EGitCredentialsProvider;\r
+import org.eclipse.egit.ui.internal.dialogs.SourceBranchFailureDialog;\r
+import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNodeType;\r
+import org.eclipse.jface.dialogs.Dialog;\r
+import org.eclipse.jface.dialogs.IMessageProvider;\r
+import org.eclipse.jface.operation.IRunnableWithProgress;\r
+import org.eclipse.jface.viewers.CheckStateChangedEvent;\r
+import org.eclipse.jface.viewers.ICheckStateListener;\r
+import org.eclipse.jface.viewers.ITreeContentProvider;\r
+import org.eclipse.jface.viewers.LabelProvider;\r
+import org.eclipse.jface.viewers.Viewer;\r
+import org.eclipse.jface.wizard.WizardPage;\r
+import org.eclipse.jgit.api.errors.TransportException;\r
+import org.eclipse.jgit.lib.Constants;\r
+import org.eclipse.jgit.lib.Ref;\r
+import org.eclipse.jgit.lib.Repository;\r
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;\r
+import org.eclipse.jgit.transport.URIish;\r
+import org.eclipse.osgi.util.NLS;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.layout.RowLayout;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.ui.PlatformUI;\r
+import org.eclipse.ui.dialogs.PatternFilter;\r
+import org.eclipse.ui.progress.WorkbenchJob;\r
+\r
+class RtSourceBranchPage extends WizardPage {\r
+\r
+ private RepositorySelection validatedRepoSelection;\r
+\r
+ private Ref head;\r
+\r
+ private final List<Ref> availableRefs = new ArrayList<Ref>();\r
+\r
+ private Label label;\r
+\r
+ private String transportError;\r
+\r
+ private Button selectB;\r
+\r
+ private Button unselectB;\r
+\r
+ private CachedCheckboxTreeViewer refsViewer;\r
+\r
+ private UserPasswordCredentials credentials;\r
+\r
+ private String helpContext = null;\r
+\r
+ RtSourceBranchPage() {\r
+ super(RtSourceBranchPage.class.getName());\r
+ setTitle(UIText.SourceBranchPage_title);\r
+ setDescription(UIText.SourceBranchPage_description);\r
+ }\r
+\r
+ List<Ref> getSelectedBranches() {\r
+ Object[] checkedElements = refsViewer.getCheckedElements();\r
+ Ref[] checkedRefs = new Ref[checkedElements.length];\r
+ System.arraycopy(checkedElements, 0, checkedRefs, 0, checkedElements.length);\r
+ return Arrays.asList(checkedRefs);\r
+ }\r
+\r
+ List<Ref> getAvailableBranches() {\r
+ return availableRefs;\r
+ }\r
+\r
+ Ref getHEAD() {\r
+ return head;\r
+ }\r
+\r
+ boolean isSourceRepoEmpty() {\r
+ return availableRefs.isEmpty();\r
+ }\r
+\r
+ boolean isAllSelected() {\r
+ return availableRefs.size() == refsViewer.getCheckedElements().length;\r
+ }\r
+\r
+ @Override\r
+ public void createControl(final Composite parent) {\r
+ final Composite panel = new Composite(parent, SWT.NULL);\r
+ final GridLayout layout = new GridLayout();\r
+ layout.numColumns = 1;\r
+ panel.setLayout(layout);\r
+\r
+ label = new Label(panel, SWT.NONE);\r
+ label.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));\r
+\r
+ FilteredCheckboxTree fTree = new FilteredCheckboxTree(panel, null,\r
+ SWT.NONE, new PatternFilter()) {\r
+ /*\r
+ * Overridden to check page when refreshing is done.\r
+ */\r
+ @Override\r
+ protected WorkbenchJob doCreateRefreshJob() {\r
+ WorkbenchJob refreshJob = super.doCreateRefreshJob();\r
+ refreshJob.addJobChangeListener(new JobChangeAdapter() {\r
+ @Override\r
+ public void done(IJobChangeEvent event) {\r
+ if (event.getResult().isOK()) {\r
+ getDisplay().asyncExec(new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ checkPage();\r
+ }\r
+ });\r
+ }\r
+ }\r
+ });\r
+ return refreshJob;\r
+ }\r
+ };\r
+ refsViewer = fTree.getCheckboxTreeViewer();\r
+\r
+ ITreeContentProvider provider = new ITreeContentProvider() {\r
+\r
+ @Override\r
+ public void inputChanged(Viewer arg0, Object arg1, Object arg2) {\r
+ // nothing\r
+ }\r
+\r
+ @Override\r
+ public void dispose() {\r
+ // nothing\r
+ }\r
+\r
+ @Override\r
+ public Object[] getElements(Object input) {\r
+ return ((List) input).toArray();\r
+ }\r
+\r
+ @Override\r
+ public boolean hasChildren(Object element) {\r
+ return false;\r
+ }\r
+\r
+ @Override\r
+ public Object getParent(Object element) {\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public Object[] getChildren(Object parentElement) {\r
+ return null;\r
+ }\r
+ };\r
+ refsViewer.setContentProvider(provider);\r
+ refsViewer.setLabelProvider(new LabelProvider() {\r
+ @Override\r
+ public String getText(Object element) {\r
+ if (((Ref) element).getName().startsWith(Constants.R_HEADS))\r
+ return ((Ref) element).getName().substring(Constants.R_HEADS.length());\r
+ return ((Ref) element).getName();\r
+ }\r
+\r
+ @Override\r
+ public Image getImage(Object element) {\r
+ return RepositoryTreeNodeType.REF.getIcon();\r
+ }\r
+ });\r
+\r
+ refsViewer.addCheckStateListener(new ICheckStateListener() {\r
+ @Override\r
+ public void checkStateChanged(CheckStateChangedEvent event) {\r
+ checkPage();\r
+ }\r
+ });\r
+ final Composite bPanel = new Composite(panel, SWT.NONE);\r
+ bPanel.setLayout(new RowLayout());\r
+ selectB = new Button(bPanel, SWT.PUSH);\r
+ selectB.setText(UIText.SourceBranchPage_selectAll);\r
+ selectB.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(final SelectionEvent e) {\r
+ refsViewer.setAllChecked(true);\r
+ checkPage();\r
+ }\r
+ });\r
+ unselectB = new Button(bPanel, SWT.PUSH);\r
+ unselectB.setText(UIText.SourceBranchPage_selectNone);\r
+ unselectB.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(final SelectionEvent e) {\r
+ refsViewer.setAllChecked(false);\r
+ checkPage();\r
+ }\r
+ });\r
+ bPanel.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));\r
+\r
+ Dialog.applyDialogFont(panel);\r
+ setControl(panel);\r
+ checkPage();\r
+ }\r
+\r
+ public void setSelection(RepositorySelection selection) {\r
+ revalidate(selection);\r
+ }\r
+\r
+ public void setCredentials(UserPasswordCredentials credentials) {\r
+ this.credentials = credentials;\r
+ }\r
+\r
+ /**\r
+ * Set the ID for context sensitive help\r
+ * @param id help context\r
+ */\r
+ public void setHelpContext(String id) {\r
+ helpContext = id;\r
+ }\r
+\r
+ @Override\r
+ public void performHelp() {\r
+ PlatformUI.getWorkbench().getHelpSystem().displayHelp(helpContext);\r
+ }\r
+\r
+ /**\r
+ * Check internal state for page completion status. This method should be called only when all necessary data from previous form is available.\r
+ */\r
+ private void checkPage() {\r
+ setMessage(null);\r
+ int checkedElementCount = refsViewer.getCheckedElements().length;\r
+ selectB.setEnabled(checkedElementCount != availableRefs.size());\r
+ unselectB.setEnabled(checkedElementCount != 0);\r
+ if (transportError != null) {\r
+ setErrorMessage(transportError);\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+\r
+ if (getSelectedBranches().isEmpty()) {\r
+ setErrorMessage(UIText.SourceBranchPage_errorBranchRequired);\r
+ setPageComplete(false);\r
+ return;\r
+ }\r
+ setErrorMessage(null);\r
+ setPageComplete(true);\r
+ }\r
+\r
+ private void checkForEmptyRepo() {\r
+ if (isSourceRepoEmpty()) {\r
+ setErrorMessage(null);\r
+ setMessage(UIText.SourceBranchPage_repoEmpty, IMessageProvider.WARNING);\r
+ setPageComplete(true);\r
+ }\r
+ }\r
+\r
+ private void revalidate(final RepositorySelection newRepoSelection) {\r
+ if (newRepoSelection.equals(validatedRepoSelection)) {\r
+ // URI hasn't changed, no need to refill the page with new data\r
+ checkPage();\r
+ return;\r
+ }\r
+\r
+ label.setText(NLS.bind(UIText.SourceBranchPage_branchList,\r
+ newRepoSelection.getURI().toString()));\r
+ label.getParent().layout();\r
+\r
+ validatedRepoSelection = null;\r
+ transportError = null;\r
+ head = null;\r
+ availableRefs.clear();\r
+ refsViewer.setInput(null);\r
+ setPageComplete(false);\r
+ setErrorMessage(null);\r
+ setMessage(null);\r
+ label.getDisplay().asyncExec(new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ revalidateImpl(newRepoSelection);\r
+ }\r
+ });\r
+ }\r
+\r
+ private void revalidateImpl(final RepositorySelection newRepoSelection) {\r
+ if (label.isDisposed() || !isCurrentPage())\r
+ return;\r
+\r
+ final ListRemoteOperation listRemoteOp;\r
+ final URIish uri = newRepoSelection.getURI();\r
+ try {\r
+ final Repository db = FileRepositoryBuilder\r
+ .create(new File("/tmp")); //$NON-NLS-1$\r
+ int timeout = Activator.getDefault().getPreferenceStore().getInt(\r
+ UIPreferences.REMOTE_CONNECTION_TIMEOUT);\r
+ listRemoteOp = new ListRemoteOperation(db, uri, timeout);\r
+ if (credentials != null)\r
+ listRemoteOp\r
+ .setCredentialsProvider(new EGitCredentialsProvider(\r
+ credentials.getUser(), credentials\r
+ .getPassword()));\r
+ getContainer().run(true, true, new IRunnableWithProgress() {\r
+ @Override\r
+ public void run(IProgressMonitor monitor)\r
+ throws InvocationTargetException, InterruptedException {\r
+ listRemoteOp.run(monitor);\r
+ }\r
+ });\r
+ } catch (InvocationTargetException e) {\r
+ Throwable why = e.getCause();\r
+ transportError(why);\r
+ if (showDetailedFailureDialog())\r
+ SourceBranchFailureDialog.show(getShell(), uri);\r
+ return;\r
+ } catch (IOException e) {\r
+ transportError(UIText.SourceBranchPage_cannotCreateTemp);\r
+ return;\r
+ } catch (InterruptedException e) {\r
+ transportError(UIText.SourceBranchPage_remoteListingCancelled);\r
+ return;\r
+ }\r
+\r
+ final Ref idHEAD = listRemoteOp.getRemoteRef(Constants.HEAD);\r
+ head = null;\r
+ boolean headIsMaster = false;\r
+ final String masterBranchRef = Constants.R_HEADS + Constants.MASTER;\r
+ for (final Ref r : listRemoteOp.getRemoteRefs()) {\r
+ final String n = r.getName();\r
+ if (!n.startsWith(Constants.R_HEADS))\r
+ continue;\r
+ availableRefs.add(r);\r
+ if (idHEAD == null || headIsMaster)\r
+ continue;\r
+ if (r.getObjectId().equals(idHEAD.getObjectId())) {\r
+ headIsMaster = masterBranchRef.equals(r.getName());\r
+ if (head == null || headIsMaster)\r
+ head = r;\r
+ }\r
+ }\r
+ Collections.sort(availableRefs, new Comparator<Ref>() {\r
+ @Override\r
+ public int compare(final Ref o1, final Ref o2) {\r
+ return o1.getName().compareTo(o2.getName());\r
+ }\r
+ });\r
+ if (idHEAD != null && head == null) {\r
+ head = idHEAD;\r
+ availableRefs.add(0, idHEAD);\r
+ }\r
+\r
+ validatedRepoSelection = newRepoSelection;\r
+ refsViewer.setInput(availableRefs);\r
+ refsViewer.setAllChecked(true);\r
+ checkPage();\r
+ checkForEmptyRepo();\r
+ }\r
+\r
+ private void transportError(final Throwable why) {\r
+ Activator.logError(why.getMessage(), why);\r
+ Throwable cause = why.getCause();\r
+ if (why instanceof TransportException && cause != null)\r
+ transportError(NLS.bind(getMessage(why), why.getMessage(),\r
+ cause.getMessage()));\r
+ else\r
+ transportError(why.getMessage());\r
+ }\r
+\r
+ private String getMessage(final Throwable why) {\r
+ if (why.getMessage().endsWith("Auth fail")) //$NON-NLS-1$\r
+ return UIText.SourceBranchPage_AuthFailMessage;\r
+ else\r
+ return UIText.SourceBranchPage_CompositeTransportErrorMessage;\r
+ }\r
+\r
+ private void transportError(final String msg) {\r
+ transportError = msg;\r
+ checkPage();\r
+ }\r
+\r
+ private boolean showDetailedFailureDialog() {\r
+ return Activator\r
+ .getDefault()\r
+ .getPreferenceStore()\r
+ .getBoolean(\r
+ UIPreferences.CLONE_WIZARD_SHOW_DETAILED_FAILURE_DIALOG);\r
+ }\r
+\r
+}\r