{"thread":{"id":"16945","subject":"[EGIT PATCH] Add an import wizard for Eclipse projects as part of clone","startedAt":"2008-12-31T10:56:09Z","lastAt":"2009-01-02T06:18:18Z","messageCount":3,"participants":["Robin Rosenberg","Shawn O. Pearce"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"99052","messageId":"1230720969-1735-1-git-send-email-robin.rosenberg@dewire.com","threadId":"16945","inReplyTo":null,"subject":"[EGIT PATCH] Add an import wizard for Eclipse projects as part of clone","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2008-12-31T10:56:09Z","receivedAt":"2008-12-31T10:56:09Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"This adds an optional page for importing Eclipse style projects\nas part of the clone operation.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n org.spearce.egit.ui/META-INF/MANIFEST.MF           |    1 +\n .../ui/internal/clone/CloneDestinationPage.java    |   30 +-\n .../egit/ui/internal/clone/GitCloneWizard.java     |  108 ++-\n .../ui/internal/clone/GitProjectsImportPage.java   |  956 ++++++++++++++++++++\n .../components/RepositorySelectionPage.java        |    7 +\n 5 files changed, 1081 insertions(+), 21 deletions(-)\n create mode 100644 org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitProjectsImportPage.java\n\nThis patch I think, greatly simplifies getting an Eclipse based project\ninto the workbench.\n\nI'm mostly interested in comments on pure bugs. E.g. know it's\nblocking when the user selects to import the projects as part of the\nclone process, I also know I'm reusing internal messages and not supplying\nNLS style constansts for all textx.\n\nHappy New Year!\n\n-- robin\n\n\ndiff --git a/org.spearce.egit.ui/META-INF/MANIFEST.MF b/org.spearce.egit.ui/META-INF/MANIFEST.MF\nindex 092624f..420801b 100644\n--- a/org.spearce.egit.ui/META-INF/MANIFEST.MF\n+++ b/org.spearce.egit.ui/META-INF/MANIFEST.MF\n@@ -19,6 +19,7 @@ Require-Bundle: org.eclipse.core.runtime,\n  org.eclipse.compare,\n  org.spearce.jgit,\n  org.spearce.egit.core,\n+ org.eclipse.ui.ide,\n  org.eclipse.jsch.ui;bundle-version=\"1.1.100\"\n Eclipse-LazyStart: true\n Bundle-RequiredExecutionEnvironment: J2SE-1.5\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/CloneDestinationPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/CloneDestinationPage.java\nindex 5173335..c60dd0c 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/CloneDestinationPage.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/CloneDestinationPage.java\n@@ -57,12 +57,13 @@\n \n \tprivate Text remoteText;\n \n+\tButton showImportWizarad;\n+\n \tCloneDestinationPage(final RepositorySelectionPage sp,\n \t\t\tfinal SourceBranchPage bp) {\n \t\tsuper(CloneDestinationPage.class.getName());\n \t\tsourcePage = sp;\n \t\tbranchPage = bp;\n-\n \t\tsetTitle(UIText.CloneDestinationPage_title);\n \n \t\tfinal SelectionChangeListener listener = new SelectionChangeListener() {\n@@ -82,7 +83,7 @@ public void createControl(final Composite parent) {\n \n \t\tcreateDestinationGroup(panel);\n \t\tcreateConfigGroup(panel);\n-\n+\t\tcreateWorkbenchGroup(panel);\n \t\tsetControl(panel);\n \t\tcheckPage();\n \t}\n@@ -92,6 +93,8 @@ public void setVisible(final boolean visible) {\n \t\tif (visible)\n \t\t\trevalidate();\n \t\tsuper.setVisible(visible);\n+\t\tif (visible)\n+\t\t\tdirectoryText.setFocus();\n \t}\n \n \tprivate void checkPreviousPagesSelections() {\n@@ -165,6 +168,20 @@ public void modifyText(ModifyEvent e) {\n \t\t});\n \t}\n \n+\tprivate void createWorkbenchGroup(Composite parent) {\n+\t\tfinal Group g = createGroup(parent, \"Workspace import\");\n+\t\tnewLabel(g, \"Import projects after clone\");\n+\t\tshowImportWizarad = new Button(g, SWT.CHECK);\n+\t\tshowImportWizarad.setSelection(true);\n+\t\tshowImportWizarad.setLayoutData(createFieldGridData());\n+\t\tshowImportWizarad.addSelectionListener(new SelectionAdapter() {\n+\t\t\t@Override\n+\t\t\tpublic void widgetSelected(SelectionEvent e) {\n+\t\t\t\tcheckPage();\n+\t\t\t}\n+\t\t});\n+\t}\n+\n \tprivate static Group createGroup(final Composite parent, final String text) {\n \t\tfinal Group g = new Group(parent, SWT.NONE);\n \t\tfinal GridLayout layout = new GridLayout();\n@@ -223,8 +240,9 @@ setErrorMessage(NLS.bind(UIText.CloneDestinationPage_fieldRequired,\n \t\t}\n \t\tfinal File absoluteFile = new File(dstpath).getAbsoluteFile();\n \t\tif (!isEmptyDir(absoluteFile)) {\n-\t\t\tsetErrorMessage(NLS.bind(UIText.CloneDestinationPage_errorNotEmptyDir,\n-\t\t\t\t\tabsoluteFile.getPath()));\n+\t\t\tsetErrorMessage(NLS.bind(\n+\t\t\t\t\tUIText.CloneDestinationPage_errorNotEmptyDir, absoluteFile\n+\t\t\t\t\t\t\t.getPath()));\n \t\t\tsetPageComplete(false);\n \t\t\treturn;\n \t\t}\n@@ -316,4 +334,8 @@ private String getSuggestedName() {\n \t\treturn path;\n \t}\n \n+\t@Override\n+\tpublic boolean canFlipToNextPage() {\n+\t\treturn super.canFlipToNextPage() && showImportWizarad.getSelection();\n+\t}\n }\n\\ No newline at end of file\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitCloneWizard.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitCloneWizard.java\nindex a69dc52..01d7374 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitCloneWizard.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitCloneWizard.java\n@@ -18,11 +18,13 @@\n import org.eclipse.core.runtime.Status;\n import org.eclipse.core.runtime.jobs.Job;\n import org.eclipse.jface.dialogs.ErrorDialog;\n+import org.eclipse.jface.dialogs.MessageDialog;\n import org.eclipse.jface.viewers.IStructuredSelection;\n import org.eclipse.jface.wizard.Wizard;\n import org.eclipse.osgi.util.NLS;\n import org.eclipse.ui.IImportWizard;\n import org.eclipse.ui.IWorkbench;\n+import org.eclipse.ui.PlatformUI;\n import org.spearce.egit.core.op.CloneOperation;\n import org.spearce.egit.ui.Activator;\n import org.spearce.egit.ui.UIIcons;\n@@ -41,6 +43,10 @@\n \n \tprivate CloneDestinationPage cloneDestination;\n \n+\tprivate GitProjectsImportPage importProject;\n+\n+\tprivate String alreadyClonedInto;\n+\n \tpublic void init(IWorkbench arg0, IStructuredSelection arg1) {\n \t\tsetWindowTitle(UIText.GitCloneWizard_title);\n \t\tsetDefaultPageImageDescriptor(UIIcons.WIZBAN_IMPORT_REPO);\n@@ -48,6 +54,47 @@ public void init(IWorkbench arg0, IStructuredSelection arg1) {\n \t\tcloneSource = new RepositorySelectionPage(true);\n \t\tvalidSource = new SourceBranchPage(cloneSource);\n \t\tcloneDestination = new CloneDestinationPage(cloneSource, validSource);\n+\t\timportProject = new GitProjectsImportPage() {\n+\t\t\t@Override\n+\t\t\tpublic void setVisible(boolean visible) {\n+\t\t\t\tif (visible) {\n+\t\t\t\t\tif (alreadyClonedInto == null) {\n+\t\t\t\t\t\tperformClone(false);\n+\t\t\t\t\t\talreadyClonedInto = cloneDestination\n+\t\t\t\t\t\t\t\t.getDestinationFile().getAbsolutePath();\n+\t\t\t\t\t}\n+\t\t\t\t\tsetDirectoryPath(alreadyClonedInto);\n+\t\t\t\t\tupdateProjectsList(alreadyClonedInto);\n+\t\t\t\t}\n+\t\t\t\tsuper.setVisible(visible);\n+\t\t\t}\n+\t\t};\n+\t}\n+\n+\t@Override\n+\tpublic boolean performCancel() {\n+\t\tif (alreadyClonedInto != null) {\n+\t\t\tif (MessageDialog\n+\t\t\t\t\t.openQuestion(getShell(), \"Aborting clone.\",\n+\t\t\t\t\t\t\t\"A complete clone was already made. Do you want to delete it?\")) {\n+\t\t\t\tdeleteRecursively(new File(alreadyClonedInto));\n+\t\t\t}\n+\t\t}\n+\t\treturn true;\n+\t}\n+\n+\tprivate void deleteRecursively(File f) {\n+\t\tfor (File i : f.listFiles()) {\n+\t\t\tif (i.isDirectory()) {\n+\t\t\t\tdeleteRecursively(i);\n+\t\t\t} else {\n+\t\t\t\tif (!i.delete()) {\n+\t\t\t\t\ti.deleteOnExit();\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\tif (!f.delete())\n+\t\t\tf.deleteOnExit();\n \t}\n \n \t@Override\n@@ -55,10 +102,24 @@ public void addPages() {\n \t\taddPage(cloneSource);\n \t\taddPage(validSource);\n \t\taddPage(cloneDestination);\n+\t\taddPage(importProject);\n+\t}\n+\n+\t@Override\n+\tpublic boolean canFinish() {\n+\t\treturn cloneDestination.isPageComplete()\n+\t\t\t\t&& !cloneDestination.showImportWizarad.getSelection()\n+\t\t\t\t|| importProject.isPageComplete();\n \t}\n \n \t@Override\n \tpublic boolean performFinish() {\n+\t\tif (!cloneDestination.showImportWizarad.getSelection())\n+\t\t\treturn performClone(true);\n+\t\treturn importProject.createProjects();\n+\t}\n+\n+\tboolean performClone(boolean background) {\n \t\tfinal URIish uri = cloneSource.getSelection().getURI();\n \t\tfinal boolean allSelected = validSource.isAllSelected();\n \t\tfinal Collection<Ref> selectedBranches = validSource\n@@ -80,24 +141,37 @@ public boolean performFinish() {\n \n \t\tfinal CloneOperation op = new CloneOperation(uri, allSelected,\n \t\t\t\tselectedBranches, workdir, branch, remoteName);\n-\t\tfinal Job job = new Job(NLS.bind(UIText.GitCloneWizard_jobName, uri\n-\t\t\t\t.toString())) {\n-\t\t\t@Override\n-\t\t\tprotected IStatus run(final IProgressMonitor monitor) {\n-\t\t\t\ttry {\n-\t\t\t\t\top.run(monitor);\n-\t\t\t\t\treturn Status.OK_STATUS;\n-\t\t\t\t} catch (InterruptedException e) {\n-\t\t\t\t\treturn Status.CANCEL_STATUS;\n-\t\t\t\t} catch (InvocationTargetException e) {\n-\t\t\t\t\tThrowable thr = e.getCause();\n-\t\t\t\t\treturn new Status(IStatus.ERROR, Activator.getPluginId(),\n-\t\t\t\t\t\t\t0, thr.getMessage(), thr);\n+\t\tif (background) {\n+\t\t\tfinal Job job = new Job(NLS.bind(UIText.GitCloneWizard_jobName, uri\n+\t\t\t\t\t.toString())) {\n+\t\t\t\t@Override\n+\t\t\t\tprotected IStatus run(final IProgressMonitor monitor) {\n+\t\t\t\t\ttry {\n+\t\t\t\t\t\top.run(monitor);\n+\t\t\t\t\t\treturn Status.OK_STATUS;\n+\t\t\t\t\t} catch (InterruptedException e) {\n+\t\t\t\t\t\treturn Status.CANCEL_STATUS;\n+\t\t\t\t\t} catch (InvocationTargetException e) {\n+\t\t\t\t\t\tThrowable thr = e.getCause();\n+\t\t\t\t\t\treturn new Status(IStatus.ERROR, Activator\n+\t\t\t\t\t\t\t\t.getPluginId(), 0, thr.getMessage(), thr);\n+\t\t\t\t\t}\n \t\t\t\t}\n+\t\t\t};\n+\t\t\tjob.setUser(true);\n+\t\t\tjob.schedule();\n+\t\t\treturn true;\n+\t\t} else {\n+\t\t\ttry {\n+\t\t\t\tPlatformUI.getWorkbench().getProgressService().run(false, true,\n+\t\t\t\t\t\top);\n+\t\t\t\treturn true;\n+\t\t\t} catch (Exception e) {\n+\t\t\t\tActivator.logError(\"Failed to clone\", e);\n+\t\t\t\tMessageDialog.openError(getShell(), \"Failed clone\", e\n+\t\t\t\t\t\t.toString());\n+\t\t\t\treturn false;\n \t\t\t}\n-\t\t};\n-\t\tjob.setUser(true);\n-\t\tjob.schedule();\n-\t\treturn true;\n+\t\t}\n \t}\n }\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitProjectsImportPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitProjectsImportPage.java\nnew file mode 100644\nindex 0000000..4241ddf\n--- /dev/null\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitProjectsImportPage.java\n@@ -0,0 +1,956 @@\n+package org.spearce.egit.ui.internal.clone;\n+\n+/*******************************************************************************\n+ * Copyright (c) 2004, 2008 IBM Corporation and others.\n+ * All rights reserved. This program and the accompanying materials\n+ * are made available under the terms of the Eclipse Public License v1.0\n+ * which accompanies this distribution, and is available at\n+ * http://www.eclipse.org/legal/epl-v10.html\n+ *\n+ * Contributors:\n+ *     IBM Corporation - initial API and implementation\n+ *     Red Hat, Inc - extensive changes to allow importing of Archive Files\n+ *     Philippe Ombredanne (pombredanne@nexb.com)\n+ *     \t\t- Bug 101180 [Import/Export] Import Existing Project into Workspace default widget is back button , should be text field\n+ *     Martin Oberhuber (martin.oberhuber@windriver.com)\n+ *     \t\t- Bug 187318[Wizards] \"Import Existing Project\" loops forever with cyclic symbolic links\n+ *     Remy Chi Jian Suen  (remy.suen@gmail.com)\n+ *     \t\t- Bug 210568 [Import/Export] [Import/Export] - Refresh button does not update list of projects\n+ *     Robin Rosenberg (robin.rosenberg@dewire.com)\n+ *     \t\t- Copy for use with Git clone\n+ *******************************************************************************/\n+\n+import java.io.File;\n+import java.io.IOException;\n+import java.lang.reflect.InvocationTargetException;\n+import java.util.ArrayList;\n+import java.util.Collection;\n+import java.util.HashSet;\n+import java.util.Iterator;\n+import java.util.List;\n+import java.util.Set;\n+\n+import org.eclipse.core.resources.IProject;\n+import org.eclipse.core.resources.IProjectDescription;\n+import org.eclipse.core.resources.IResource;\n+import org.eclipse.core.resources.IWorkspace;\n+import org.eclipse.core.resources.ResourcesPlugin;\n+import org.eclipse.core.runtime.CoreException;\n+import org.eclipse.core.runtime.IPath;\n+import org.eclipse.core.runtime.IProgressMonitor;\n+import org.eclipse.core.runtime.IStatus;\n+import org.eclipse.core.runtime.OperationCanceledException;\n+import org.eclipse.core.runtime.Path;\n+import org.eclipse.core.runtime.Platform;\n+import org.eclipse.core.runtime.Status;\n+import org.eclipse.core.runtime.SubProgressMonitor;\n+import org.eclipse.jface.dialogs.Dialog;\n+import org.eclipse.jface.dialogs.ErrorDialog;\n+import org.eclipse.jface.dialogs.MessageDialog;\n+import org.eclipse.jface.operation.IRunnableWithProgress;\n+import org.eclipse.jface.viewers.CheckStateChangedEvent;\n+import org.eclipse.jface.viewers.CheckboxTreeViewer;\n+import org.eclipse.jface.viewers.ICheckStateListener;\n+import org.eclipse.jface.viewers.ITreeContentProvider;\n+import org.eclipse.jface.viewers.LabelProvider;\n+import org.eclipse.jface.viewers.Viewer;\n+import org.eclipse.jface.viewers.ViewerComparator;\n+import org.eclipse.jface.wizard.WizardPage;\n+import org.eclipse.osgi.util.NLS;\n+import org.eclipse.swt.SWT;\n+import org.eclipse.swt.events.FocusAdapter;\n+import org.eclipse.swt.events.SelectionAdapter;\n+import org.eclipse.swt.events.SelectionEvent;\n+import org.eclipse.swt.events.TraverseEvent;\n+import org.eclipse.swt.events.TraverseListener;\n+import org.eclipse.swt.layout.GridData;\n+import org.eclipse.swt.layout.GridLayout;\n+import org.eclipse.swt.widgets.Button;\n+import org.eclipse.swt.widgets.Composite;\n+import org.eclipse.swt.widgets.DirectoryDialog;\n+import org.eclipse.swt.widgets.Label;\n+import org.eclipse.swt.widgets.Text;\n+import org.eclipse.ui.actions.WorkspaceModifyOperation;\n+import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;\n+import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;\n+import org.eclipse.ui.internal.ide.StatusUtil;\n+import org.eclipse.ui.internal.wizards.datatransfer.DataTransferMessages;\n+import org.eclipse.ui.internal.wizards.datatransfer.WizardProjectsImportPage;\n+import org.eclipse.ui.statushandlers.StatusManager;\n+import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;\n+import org.spearce.egit.core.op.ConnectProviderOperation;\n+import org.spearce.egit.ui.Activator;\n+\n+/**\n+ * The GitWizardProjectsImportPage is the page that allows the user to import\n+ * projects from a particular location. This is a modified copy of\n+ * {@link WizardProjectsImportPage}\n+ */\n+public class GitProjectsImportPage extends WizardPage {\n+\n+\t/**\n+\t * The name of the folder containing metadata information for the workspace.\n+\t */\n+\tpublic static final String METADATA_FOLDER = \".metadata\"; //$NON-NLS-1$\n+\n+\t/**\n+\t * The import structure provider.\n+\t */\n+\tprivate IImportStructureProvider structureProvider;\n+\n+\tclass ProjectRecord {\n+\t\tFile projectSystemFile;\n+\n+\t\tString projectName;\n+\n+\t\tObject parent;\n+\n+\t\tint level;\n+\n+\t\tIProjectDescription description;\n+\n+\t\t/**\n+\t\t * Create a record for a project based on the info in the file.\n+\t\t *\n+\t\t * @param file\n+\t\t */\n+\t\tProjectRecord(File file) {\n+\t\t\tprojectSystemFile = file;\n+\t\t\tsetProjectName();\n+\t\t}\n+\n+\t\t/**\n+\t\t * @param parent\n+\t\t *            The parent folder of the .project file\n+\t\t * @param level\n+\t\t *            The number of levels deep in the provider the file is\n+\t\t */\n+\t\tProjectRecord(Object parent, int level) {\n+\t\t\tthis.parent = parent;\n+\t\t\tthis.level = level;\n+\t\t\tsetProjectName();\n+\t\t}\n+\n+\t\t/**\n+\t\t * Set the name of the project based on the projectFile.\n+\t\t */\n+\t\tprivate void setProjectName() {\n+\t\t\ttry {\n+\t\t\t\t// If we don't have the project name try again\n+\t\t\t\tif (projectName == null) {\n+\t\t\t\t\tIPath path = new Path(projectSystemFile.getPath());\n+\t\t\t\t\t// if the file is in the default location, use the directory\n+\t\t\t\t\t// name as the project name\n+\t\t\t\t\tif (isDefaultLocation(path)) {\n+\t\t\t\t\t\tprojectName = path.segment(path.segmentCount() - 2);\n+\t\t\t\t\t\tdescription = IDEWorkbenchPlugin.getPluginWorkspace()\n+\t\t\t\t\t\t\t\t.newProjectDescription(projectName);\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tdescription = IDEWorkbenchPlugin.getPluginWorkspace()\n+\t\t\t\t\t\t\t\t.loadProjectDescription(path);\n+\t\t\t\t\t\tprojectName = description.getName();\n+\t\t\t\t\t}\n+\n+\t\t\t\t}\n+\t\t\t} catch (CoreException e) {\n+\t\t\t\t// no good couldn't get the name\n+\t\t\t}\n+\t\t}\n+\n+\t\t/**\n+\t\t * Returns whether the given project description file path is in the\n+\t\t * default location for a project\n+\t\t *\n+\t\t * @param path\n+\t\t *            The path to examine\n+\t\t * @return Whether the given path is the default location for a project\n+\t\t */\n+\t\tprivate boolean isDefaultLocation(IPath path) {\n+\t\t\t// The project description file must at least be within the project,\n+\t\t\t// which is within the workspace location\n+\t\t\tif (path.segmentCount() < 2)\n+\t\t\t\treturn false;\n+\t\t\treturn path.removeLastSegments(2).toFile().equals(\n+\t\t\t\t\tPlatform.getLocation().toFile());\n+\t\t}\n+\n+\t\t/**\n+\t\t * Get the name of the project\n+\t\t *\n+\t\t * @return String\n+\t\t */\n+\t\tpublic String getProjectName() {\n+\t\t\treturn projectName;\n+\t\t}\n+\n+\t\t/**\n+\t\t * Gets the label to be used when rendering this project record in the\n+\t\t * UI.\n+\t\t *\n+\t\t * @return String the label\n+\t\t * @since 3.4\n+\t\t */\n+\t\tpublic String getProjectLabel() {\n+\t\t\tif (description == null)\n+\t\t\t\treturn projectName;\n+\n+\t\t\tString path = projectSystemFile == null ? structureProvider\n+\t\t\t\t\t.getLabel(parent) : projectSystemFile.getParent();\n+\n+\t\t\treturn NLS.bind(\n+\t\t\t\t\tDataTransferMessages.WizardProjectsImportPage_projectLabel,\n+\t\t\t\t\tprojectName, path);\n+\t\t}\n+\t}\n+\n+\tprivate Text directoryPathField;\n+\n+\tprivate CheckboxTreeViewer projectsList;\n+\n+\tprivate ProjectRecord[] selectedProjects = new ProjectRecord[0];\n+\n+\t// Keep track of the directory that we browsed to last time\n+\t// the wizard was invoked.\n+\tprivate static String previouslyBrowsedDirectory = \"\"; //$NON-NLS-1$\n+\n+\tprivate Button browseDirectoriesButton;\n+\n+\tprivate IProject[] wsProjects;\n+\n+\t// The last selected path to minimize searches\n+\tprivate String lastPath;\n+\n+\t// The last time that the file or folder at the selected path was modified\n+\t// to mimize searches\n+\tprivate long lastModified;\n+\n+\tprivate Button shareCheckBox;\n+\n+\tprivate boolean share;\n+\n+\t/**\n+\t * Creates a new project creation wizard page.\n+\t */\n+\tpublic GitProjectsImportPage() {\n+\t\tthis(\"gitWizardExternalProjectsPage\"); //$NON-NLS-1$\n+\t}\n+\n+\t/**\n+\t * Create a new instance of the receiver.\n+\t *\n+\t * @param pageName\n+\t */\n+\tpublic GitProjectsImportPage(String pageName) {\n+\t\tsuper(pageName);\n+\t\tsetPageComplete(false);\n+\t\tsetTitle(DataTransferMessages.WizardProjectsImportPage_ImportProjectsTitle);\n+\t\tsetDescription(DataTransferMessages.WizardProjectsImportPage_ImportProjectsDescription);\n+\t}\n+\n+\t/*\n+\t * (non-Javadoc)\n+\t *\n+\t * @see\n+\t * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets\n+\t * .Composite)\n+\t */\n+\tpublic void createControl(Composite parent) {\n+\n+\t\tinitializeDialogUnits(parent);\n+\n+\t\tComposite workArea = new Composite(parent, SWT.NONE);\n+\t\tsetControl(workArea);\n+\n+\t\tworkArea.setLayout(new GridLayout());\n+\t\tworkArea.setLayoutData(new GridData(GridData.FILL_BOTH\n+\t\t\t\t| GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL));\n+\n+\t\tcreateProjectsRoot(workArea);\n+\t\tcreateProjectsList(workArea);\n+\t\tcreateOptionsArea(workArea);\n+\t\tDialog.applyDialogFont(workArea);\n+\n+\t}\n+\n+\t/**\n+\t * Create the area with the extra options.\n+\t *\n+\t * @param workArea\n+\t */\n+\tprivate void createOptionsArea(Composite workArea) {\n+\t\tComposite optionsGroup = new Composite(workArea, SWT.NONE);\n+\t\toptionsGroup.setLayout(new GridLayout());\n+\t\toptionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));\n+\n+\t\tshareCheckBox = new Button(optionsGroup, SWT.CHECK);\n+\t\tshareCheckBox\n+\t\t\t\t.setText(\"Enable Git Team operations on imported projects\");\n+\t\tshareCheckBox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));\n+\t\tshareCheckBox.setSelection(share = true);\n+\t\tshareCheckBox.addSelectionListener(new SelectionAdapter() {\n+\t\t\tpublic void widgetSelected(SelectionEvent e) {\n+\t\t\t\tshare = shareCheckBox.getSelection();\n+\t\t\t}\n+\t\t});\n+\t}\n+\n+\t/**\n+\t * Create the checkbox list for the found projects.\n+\t *\n+\t * @param workArea\n+\t */\n+\tprivate void createProjectsList(Composite workArea) {\n+\n+\t\tLabel title = new Label(workArea, SWT.NONE);\n+\t\ttitle\n+\t\t\t\t.setText(DataTransferMessages.WizardProjectsImportPage_ProjectsListTitle);\n+\n+\t\tComposite listComposite = new Composite(workArea, SWT.NONE);\n+\t\tGridLayout layout = new GridLayout();\n+\t\tlayout.numColumns = 2;\n+\t\tlayout.marginWidth = 0;\n+\t\tlayout.makeColumnsEqualWidth = false;\n+\t\tlistComposite.setLayout(layout);\n+\n+\t\tlistComposite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL\n+\t\t\t\t| GridData.GRAB_VERTICAL | GridData.FILL_BOTH));\n+\n+\t\tprojectsList = new CheckboxTreeViewer(listComposite, SWT.BORDER);\n+\t\tGridData listData = new GridData(GridData.GRAB_HORIZONTAL\n+\t\t\t\t| GridData.GRAB_VERTICAL | GridData.FILL_BOTH);\n+\t\tprojectsList.getControl().setLayoutData(listData);\n+\n+\t\tprojectsList.setContentProvider(new ITreeContentProvider() {\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java\n+\t\t\t * .lang.Object)\n+\t\t\t */\n+\t\t\tpublic Object[] getChildren(Object parentElement) {\n+\t\t\t\treturn null;\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.IStructuredContentProvider#getElements\n+\t\t\t * (java.lang.Object)\n+\t\t\t */\n+\t\t\tpublic Object[] getElements(Object inputElement) {\n+\t\t\t\treturn getValidProjects();\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java\n+\t\t\t * .lang.Object)\n+\t\t\t */\n+\t\t\tpublic boolean hasChildren(Object element) {\n+\t\t\t\treturn false;\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.ITreeContentProvider#getParent(java\n+\t\t\t * .lang.Object)\n+\t\t\t */\n+\t\t\tpublic Object getParent(Object element) {\n+\t\t\t\treturn null;\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see org.eclipse.jface.viewers.IContentProvider#dispose()\n+\t\t\t */\n+\t\t\tpublic void dispose() {\n+\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse\n+\t\t\t * .jface.viewers.Viewer, java.lang.Object, java.lang.Object)\n+\t\t\t */\n+\t\t\tpublic void inputChanged(Viewer viewer, Object oldInput,\n+\t\t\t\t\tObject newInput) {\n+\t\t\t}\n+\n+\t\t});\n+\n+\t\tprojectsList.setLabelProvider(new LabelProvider() {\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)\n+\t\t\t */\n+\t\t\tpublic String getText(Object element) {\n+\t\t\t\treturn ((ProjectRecord) element).getProjectLabel();\n+\t\t\t}\n+\t\t});\n+\n+\t\tprojectsList.addCheckStateListener(new ICheckStateListener() {\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged\n+\t\t\t * (org.eclipse.jface.viewers.CheckStateChangedEvent)\n+\t\t\t */\n+\t\t\tpublic void checkStateChanged(CheckStateChangedEvent event) {\n+\t\t\t\tsetPageComplete(projectsList.getCheckedElements().length > 0);\n+\t\t\t}\n+\t\t});\n+\n+\t\tprojectsList.setInput(this);\n+\t\tprojectsList.setComparator(new ViewerComparator());\n+\t\tcreateSelectionButtons(listComposite);\n+\t}\n+\n+\t/**\n+\t * Create the selection buttons in the listComposite.\n+\t *\n+\t * @param listComposite\n+\t */\n+\tprivate void createSelectionButtons(Composite listComposite) {\n+\t\tComposite buttonsComposite = new Composite(listComposite, SWT.NONE);\n+\t\tGridLayout layout = new GridLayout();\n+\t\tlayout.marginWidth = 0;\n+\t\tlayout.marginHeight = 0;\n+\t\tbuttonsComposite.setLayout(layout);\n+\n+\t\tbuttonsComposite.setLayoutData(new GridData(\n+\t\t\t\tGridData.VERTICAL_ALIGN_BEGINNING));\n+\n+\t\tButton selectAll = new Button(buttonsComposite, SWT.PUSH);\n+\t\tselectAll.setText(DataTransferMessages.DataTransfer_selectAll);\n+\t\tselectAll.addSelectionListener(new SelectionAdapter() {\n+\t\t\tpublic void widgetSelected(SelectionEvent e) {\n+\t\t\t\tprojectsList.setCheckedElements(selectedProjects);\n+\t\t\t\tsetPageComplete(projectsList.getCheckedElements().length > 0);\n+\t\t\t}\n+\t\t});\n+\t\tDialog.applyDialogFont(selectAll);\n+\t\tsetButtonLayoutData(selectAll);\n+\n+\t\tButton deselectAll = new Button(buttonsComposite, SWT.PUSH);\n+\t\tdeselectAll.setText(DataTransferMessages.DataTransfer_deselectAll);\n+\t\tdeselectAll.addSelectionListener(new SelectionAdapter() {\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse\n+\t\t\t * .swt.events.SelectionEvent)\n+\t\t\t */\n+\t\t\tpublic void widgetSelected(SelectionEvent e) {\n+\n+\t\t\t\tprojectsList.setCheckedElements(new Object[0]);\n+\t\t\t\tsetPageComplete(false);\n+\t\t\t}\n+\t\t});\n+\t\tDialog.applyDialogFont(deselectAll);\n+\t\tsetButtonLayoutData(deselectAll);\n+\n+\t\tButton refresh = new Button(buttonsComposite, SWT.PUSH);\n+\t\trefresh.setText(DataTransferMessages.DataTransfer_refresh);\n+\t\trefresh.addSelectionListener(new SelectionAdapter() {\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse\n+\t\t\t * .swt.events.SelectionEvent)\n+\t\t\t */\n+\t\t\tpublic void widgetSelected(SelectionEvent e) {\n+\t\t\t\tupdateProjectsList(directoryPathField.getText().trim());\n+\t\t\t}\n+\t\t});\n+\t\tDialog.applyDialogFont(refresh);\n+\t\tsetButtonLayoutData(refresh);\n+\t}\n+\n+\t/**\n+\t * Create the area where you select the root directory for the projects.\n+\t *\n+\t * @param workArea\n+\t *            Composite\n+\t */\n+\tprivate void createProjectsRoot(Composite workArea) {\n+\n+\t\t// project specification group\n+\t\tComposite projectGroup = new Composite(workArea, SWT.NONE);\n+\t\tGridLayout layout = new GridLayout();\n+\t\tlayout.numColumns = 3;\n+\t\tlayout.makeColumnsEqualWidth = false;\n+\t\tlayout.marginWidth = 0;\n+\t\tprojectGroup.setLayout(layout);\n+\t\tprojectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));\n+\n+\t\t// project location entry field\n+\t\tthis.directoryPathField = new Text(projectGroup, SWT.BORDER);\n+\n+\t\tthis.directoryPathField.setLayoutData(new GridData(\n+\t\t\t\tGridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));\n+\n+\t\t// browse button\n+\t\tbrowseDirectoriesButton = new Button(projectGroup, SWT.PUSH);\n+\t\tbrowseDirectoriesButton\n+\t\t\t\t.setText(DataTransferMessages.DataTransfer_browse);\n+\t\tsetButtonLayoutData(browseDirectoriesButton);\n+\n+\t\tbrowseDirectoriesButton.addSelectionListener(new SelectionAdapter() {\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see org.eclipse.swt.events.SelectionAdapter#widgetS\n+\t\t\t * elected(org.eclipse.swt.events.SelectionEvent)\n+\t\t\t */\n+\t\t\tpublic void widgetSelected(SelectionEvent e) {\n+\t\t\t\thandleLocationDirectoryButtonPressed();\n+\t\t\t}\n+\n+\t\t});\n+\n+\t\tdirectoryPathField.addTraverseListener(new TraverseListener() {\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.swt.events.TraverseListener#keyTraversed(org.eclipse\n+\t\t\t * .swt.events.TraverseEvent)\n+\t\t\t */\n+\t\t\tpublic void keyTraversed(TraverseEvent e) {\n+\t\t\t\tif (e.detail == SWT.TRAVERSE_RETURN) {\n+\t\t\t\t\te.doit = false;\n+\t\t\t\t\tupdateProjectsList(directoryPathField.getText().trim());\n+\t\t\t\t}\n+\t\t\t}\n+\n+\t\t});\n+\n+\t\tdirectoryPathField.addFocusListener(new FocusAdapter() {\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt\n+\t\t\t * .events.FocusEvent)\n+\t\t\t */\n+\t\t\tpublic void focusLost(org.eclipse.swt.events.FocusEvent e) {\n+\t\t\t\tupdateProjectsList(directoryPathField.getText().trim());\n+\t\t\t}\n+\n+\t\t});\n+\n+\t}\n+\n+\t/*\n+\t * (non-Javadoc) Method declared on IDialogPage. Set the focus on path\n+\t * fields when page becomes visible.\n+\t */\n+\tpublic void setVisible(boolean visible) {\n+\t\tsuper.setVisible(visible);\n+\t\tthis.directoryPathField.setFocus();\n+\t}\n+\n+\t/**\n+\t * Update the list of projects based on path.\n+\t *\n+\t * @param path\n+\t */\n+\tvoid updateProjectsList(final String path) {\n+\t\t// on an empty path empty selectedProjects\n+\t\tif (path == null || path.length() == 0) {\n+\t\t\tsetMessage(DataTransferMessages.WizardProjectsImportPage_ImportProjectsDescription);\n+\t\t\tselectedProjects = new ProjectRecord[0];\n+\t\t\tprojectsList.refresh(true);\n+\t\t\tprojectsList.setCheckedElements(selectedProjects);\n+\t\t\tsetPageComplete(projectsList.getCheckedElements().length > 0);\n+\t\t\tlastPath = path;\n+\t\t\treturn;\n+\t\t}\n+\n+\t\tfinal File directory = new File(path);\n+\t\tlong modified = directory.lastModified();\n+\t\tif (path.equals(lastPath) && lastModified == modified) {\n+\t\t\t// since the file/folder was not modified and the path did not\n+\t\t\t// change, no refreshing is required\n+\t\t\treturn;\n+\t\t}\n+\n+\t\tlastPath = path;\n+\t\tlastModified = modified;\n+\n+\t\ttry {\n+\t\t\tgetContainer().run(true, true, new IRunnableWithProgress() {\n+\n+\t\t\t\t/*\n+\t\t\t\t * (non-Javadoc)\n+\t\t\t\t *\n+\t\t\t\t * @see\n+\t\t\t\t * org.eclipse.jface.operation.IRunnableWithProgress#run(org\n+\t\t\t\t * .eclipse.core.runtime.IProgressMonitor)\n+\t\t\t\t */\n+\t\t\t\tpublic void run(IProgressMonitor monitor) {\n+\n+\t\t\t\t\tmonitor\n+\t\t\t\t\t\t\t.beginTask(\n+\t\t\t\t\t\t\t\t\tDataTransferMessages.WizardProjectsImportPage_SearchingMessage,\n+\t\t\t\t\t\t\t\t\t100);\n+\t\t\t\t\tselectedProjects = new ProjectRecord[0];\n+\t\t\t\t\tCollection files = new ArrayList();\n+\t\t\t\t\tmonitor.worked(10);\n+\t\t\t\t\tif (directory.isDirectory()) {\n+\n+\t\t\t\t\t\tif (!collectProjectFilesFromDirectory(files, directory,\n+\t\t\t\t\t\t\t\tnull, monitor)) {\n+\t\t\t\t\t\t\treturn;\n+\t\t\t\t\t\t}\n+\t\t\t\t\t\tIterator filesIterator = files.iterator();\n+\t\t\t\t\t\tselectedProjects = new ProjectRecord[files.size()];\n+\t\t\t\t\t\tint index = 0;\n+\t\t\t\t\t\tmonitor.worked(50);\n+\t\t\t\t\t\tmonitor\n+\t\t\t\t\t\t\t\t.subTask(DataTransferMessages.WizardProjectsImportPage_ProcessingMessage);\n+\t\t\t\t\t\twhile (filesIterator.hasNext()) {\n+\t\t\t\t\t\t\tFile file = (File) filesIterator.next();\n+\t\t\t\t\t\t\tselectedProjects[index] = new ProjectRecord(file);\n+\t\t\t\t\t\t\tindex++;\n+\t\t\t\t\t\t}\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tmonitor.worked(60);\n+\t\t\t\t\t}\n+\t\t\t\t\tmonitor.done();\n+\t\t\t\t}\n+\n+\t\t\t});\n+\t\t} catch (InvocationTargetException e) {\n+\t\t\tIDEWorkbenchPlugin.log(e.getMessage(), e);\n+\t\t} catch (InterruptedException e) {\n+\t\t\t// Nothing to do if the user interrupts.\n+\t\t}\n+\n+\t\tprojectsList.refresh(true);\n+\t\tprojectsList.setCheckedElements(getValidProjects());\n+\t\tif (getValidProjects().length < selectedProjects.length) {\n+\t\t\tsetMessage(\n+\t\t\t\t\tDataTransferMessages.WizardProjectsImportPage_projectsInWorkspace,\n+\t\t\t\t\tWARNING);\n+\t\t} else {\n+\t\t\tsetMessage(DataTransferMessages.WizardProjectsImportPage_ImportProjectsDescription);\n+\t\t}\n+\t\tsetPageComplete(projectsList.getCheckedElements().length > 0);\n+\t}\n+\n+\t/**\n+\t * Display an error dialog with the specified message.\n+\t *\n+\t * @param message\n+\t *            the error message\n+\t */\n+\tprotected void displayErrorDialog(String message) {\n+\t\tMessageDialog.openError(getContainer().getShell(),\n+\t\t\t\tgetErrorDialogTitle(), message);\n+\t}\n+\n+\t/**\n+\t * @return the title for an error dialog. Subclasses should override.\n+\t */\n+\tprotected String getErrorDialogTitle() {\n+\t\treturn IDEWorkbenchMessages.WizardExportPage_internalErrorTitle;\n+\t}\n+\n+\t/**\n+\t * Collect the list of .project files that are under directory into files.\n+\t *\n+\t * @param files\n+\t * @param directory\n+\t * @param directoriesVisited\n+\t *            Set of canonical paths of directories, used as recursion guard\n+\t * @param monitor\n+\t *            The monitor to report to\n+\t * @return boolean <code>true</code> if the operation was completed.\n+\t */\n+\tprivate boolean collectProjectFilesFromDirectory(Collection files,\n+\t\t\tFile directory, Set directoriesVisited, IProgressMonitor monitor) {\n+\n+\t\tif (monitor.isCanceled()) {\n+\t\t\treturn false;\n+\t\t}\n+\t\tmonitor.subTask(NLS.bind(\n+\t\t\t\tDataTransferMessages.WizardProjectsImportPage_CheckingMessage,\n+\t\t\t\tdirectory.getPath()));\n+\t\tFile[] contents = directory.listFiles();\n+\t\tif (contents == null)\n+\t\t\treturn false;\n+\n+\t\t// Initialize recursion guard for recursive symbolic links\n+\t\tif (directoriesVisited == null) {\n+\t\t\tdirectoriesVisited = new HashSet();\n+\t\t\ttry {\n+\t\t\t\tdirectoriesVisited.add(directory.getCanonicalPath());\n+\t\t\t} catch (IOException exception) {\n+\t\t\t\tStatusManager.getManager().handle(\n+\t\t\t\t\t\tStatusUtil.newStatus(IStatus.ERROR, exception\n+\t\t\t\t\t\t\t\t.getLocalizedMessage(), exception));\n+\t\t\t}\n+\t\t}\n+\n+\t\t// first look for project description files\n+\t\tfinal String dotProject = IProjectDescription.DESCRIPTION_FILE_NAME;\n+\t\tfor (int i = 0; i < contents.length; i++) {\n+\t\t\tFile file = contents[i];\n+\t\t\tif (file.isFile() && file.getName().equals(dotProject)) {\n+\t\t\t\tfiles.add(file);\n+\t\t\t\t// don't search sub-directories since we can't have nested\n+\t\t\t\t// projects\n+\t\t\t\treturn true;\n+\t\t\t}\n+\t\t}\n+\t\t// no project description found, so recurse into sub-directories\n+\t\tfor (int i = 0; i < contents.length; i++) {\n+\t\t\tif (contents[i].isDirectory()) {\n+\t\t\t\tif (!contents[i].getName().equals(METADATA_FOLDER)) {\n+\t\t\t\t\ttry {\n+\t\t\t\t\t\tString canonicalPath = contents[i].getCanonicalPath();\n+\t\t\t\t\t\tif (!directoriesVisited.add(canonicalPath)) {\n+\t\t\t\t\t\t\t// already been here --> do not recurse\n+\t\t\t\t\t\t\tcontinue;\n+\t\t\t\t\t\t}\n+\t\t\t\t\t} catch (IOException exception) {\n+\t\t\t\t\t\tStatusManager.getManager().handle(\n+\t\t\t\t\t\t\t\tStatusUtil.newStatus(IStatus.ERROR, exception\n+\t\t\t\t\t\t\t\t\t\t.getLocalizedMessage(), exception));\n+\n+\t\t\t\t\t}\n+\t\t\t\t\tcollectProjectFilesFromDirectory(files, contents[i],\n+\t\t\t\t\t\t\tdirectoriesVisited, monitor);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\treturn true;\n+\t}\n+\n+\t/**\n+\t * The browse button has been selected. Select the location.\n+\t */\n+\tprotected void handleLocationDirectoryButtonPressed() {\n+\n+\t\tDirectoryDialog dialog = new DirectoryDialog(directoryPathField\n+\t\t\t\t.getShell());\n+\t\tdialog\n+\t\t\t\t.setMessage(DataTransferMessages.WizardProjectsImportPage_SelectDialogTitle);\n+\n+\t\tString dirName = directoryPathField.getText().trim();\n+\t\tif (dirName.length() == 0) {\n+\t\t\tdirName = previouslyBrowsedDirectory;\n+\t\t}\n+\n+\t\tif (dirName.length() == 0) {\n+\t\t\tdialog.setFilterPath(IDEWorkbenchPlugin.getPluginWorkspace()\n+\t\t\t\t\t.getRoot().getLocation().toOSString());\n+\t\t} else {\n+\t\t\tFile path = new File(dirName);\n+\t\t\tif (path.exists()) {\n+\t\t\t\tdialog.setFilterPath(new Path(dirName).toOSString());\n+\t\t\t}\n+\t\t}\n+\n+\t\tString selectedDirectory = dialog.open();\n+\t\tif (selectedDirectory != null) {\n+\t\t\tpreviouslyBrowsedDirectory = selectedDirectory;\n+\t\t\tdirectoryPathField.setText(previouslyBrowsedDirectory);\n+\t\t\tupdateProjectsList(selectedDirectory);\n+\t\t}\n+\n+\t}\n+\n+\tvoid setDirectoryPath(String path) {\n+\t\tdirectoryPathField.setText(path);\n+\t}\n+\n+\t/**\n+\t * Create the selected projects\n+\t *\n+\t * @return boolean <code>true</code> if all project creations were\n+\t *         successful.\n+\t */\n+\tboolean createProjects() {\n+\t\tfinal Object[] selected = projectsList.getCheckedElements();\n+\t\tWorkspaceModifyOperation op = new WorkspaceModifyOperation() {\n+\t\t\tprotected void execute(IProgressMonitor monitor)\n+\t\t\t\t\tthrows InvocationTargetException, InterruptedException {\n+\t\t\t\ttry {\n+\t\t\t\t\tmonitor.beginTask(\"\", selected.length); //$NON-NLS-1$\n+\t\t\t\t\tif (monitor.isCanceled()) {\n+\t\t\t\t\t\tthrow new OperationCanceledException();\n+\t\t\t\t\t}\n+\t\t\t\t\tfor (int i = 0; i < selected.length; i++) {\n+\t\t\t\t\t\tcreateExistingProject((ProjectRecord) selected[i],\n+\t\t\t\t\t\t\t\tnew SubProgressMonitor(monitor, 1));\n+\t\t\t\t\t}\n+\t\t\t\t} finally {\n+\t\t\t\t\tmonitor.done();\n+\t\t\t\t}\n+\t\t\t}\n+\t\t};\n+\t\t// run the new project creation operation\n+\t\ttry {\n+\t\t\tgetContainer().run(true, true, op);\n+\t\t} catch (InterruptedException e) {\n+\t\t\treturn false;\n+\t\t} catch (InvocationTargetException e) {\n+\t\t\t// one of the steps resulted in a core exception\n+\t\t\tThrowable t = e.getTargetException();\n+\t\t\tString message = DataTransferMessages.WizardExternalProjectImportPage_errorMessage;\n+\t\t\tIStatus status;\n+\t\t\tif (t instanceof CoreException) {\n+\t\t\t\tstatus = ((CoreException) t).getStatus();\n+\t\t\t} else {\n+\t\t\t\tstatus = new Status(IStatus.ERROR,\n+\t\t\t\t\t\tIDEWorkbenchPlugin.IDE_WORKBENCH, 1, message, t);\n+\t\t\t}\n+\t\t\tActivator.logError(message, t);\n+\t\t\tErrorDialog.openError(getShell(), message, null, status);\n+\t\t\treturn false;\n+\t\t}\n+\t\treturn true;\n+\t}\n+\n+\t/**\n+\t * Create the project described in record. If it is successful return true.\n+\t *\n+\t * @param record\n+\t * @param monitor\n+\t * @return boolean <code>true</code> if successful\n+\t * @throws InvocationTargetException\n+\t * @throws InterruptedException\n+\t */\n+\tprivate boolean createExistingProject(final ProjectRecord record,\n+\t\t\tIProgressMonitor monitor) throws InvocationTargetException,\n+\t\t\tInterruptedException {\n+\t\tString projectName = record.getProjectName();\n+\t\tfinal IWorkspace workspace = ResourcesPlugin.getWorkspace();\n+\t\tfinal IProject project = workspace.getRoot().getProject(projectName);\n+\t\tif (record.description == null) {\n+\t\t\t// error case\n+\t\t\trecord.description = workspace.newProjectDescription(projectName);\n+\t\t\tIPath locationPath = new Path(record.projectSystemFile\n+\t\t\t\t\t.getAbsolutePath());\n+\n+\t\t\t// If it is under the root use the default location\n+\t\t\tif (Platform.getLocation().isPrefixOf(locationPath)) {\n+\t\t\t\trecord.description.setLocation(null);\n+\t\t\t} else {\n+\t\t\t\trecord.description.setLocation(locationPath);\n+\t\t\t}\n+\t\t} else {\n+\t\t\trecord.description.setName(projectName);\n+\t\t}\n+\n+\t\ttry {\n+\t\t\tmonitor\n+\t\t\t\t\t.beginTask(\n+\t\t\t\t\t\t\tDataTransferMessages.WizardProjectsImportPage_CreateProjectsTask,\n+\t\t\t\t\t\t\t100);\n+\t\t\tproject.create(record.description, new SubProgressMonitor(monitor,\n+\t\t\t\t\t30));\n+\t\t\tint openTicks = share ? 50 : 70;\n+\t\t\tproject.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(\n+\t\t\t\t\tmonitor, openTicks));\n+\t\t\tif (share) {\n+\t\t\t\tConnectProviderOperation connectProviderOperation = new ConnectProviderOperation(\n+\t\t\t\t\t\tproject, null);\n+\t\t\t\tconnectProviderOperation\n+\t\t\t\t\t\t.run(new SubProgressMonitor(monitor, 20));\n+\t\t\t}\n+\t\t} catch (CoreException e) {\n+\t\t\tthrow new InvocationTargetException(e);\n+\t\t} finally {\n+\t\t\tmonitor.done();\n+\t\t}\n+\n+\t\treturn true;\n+\t}\n+\n+\t/**\n+\t * Method used for test suite.\n+\t *\n+\t * @return CheckboxTreeViewer the viewer containing all the projects found\n+\t */\n+\tpublic CheckboxTreeViewer getProjectsList() {\n+\t\treturn projectsList;\n+\t}\n+\n+\t/**\n+\t * Retrieve all the projects in the current workspace.\n+\t *\n+\t * @return IProject[] array of IProject in the current workspace\n+\t */\n+\tprivate IProject[] getProjectsInWorkspace() {\n+\t\tif (wsProjects == null) {\n+\t\t\twsProjects = IDEWorkbenchPlugin.getPluginWorkspace().getRoot()\n+\t\t\t\t\t.getProjects();\n+\t\t}\n+\t\treturn wsProjects;\n+\t}\n+\n+\t/**\n+\t * Get the array of valid project records that can be imported from the\n+\t * source workspace or archive, selected by the user. If a project with the\n+\t * same name exists in both the source workspace and the current workspace,\n+\t * it will not appear in the list of projects to import and thus cannot be\n+\t * selected for import.\n+\t *\n+\t * Method declared public for test suite.\n+\t *\n+\t * @return ProjectRecord[] array of projects that can be imported into the\n+\t *         workspace\n+\t */\n+\tpublic ProjectRecord[] getValidProjects() {\n+\t\tList validProjects = new ArrayList();\n+\t\tfor (int i = 0; i < selectedProjects.length; i++) {\n+\t\t\tif (!isProjectInWorkspace(selectedProjects[i].getProjectName())) {\n+\t\t\t\tvalidProjects.add(selectedProjects[i]);\n+\t\t\t}\n+\t\t}\n+\t\treturn (ProjectRecord[]) validProjects\n+\t\t\t\t.toArray(new ProjectRecord[validProjects.size()]);\n+\t}\n+\n+\t/**\n+\t * Determine if the project with the given name is in the current workspace.\n+\t *\n+\t * @param projectName\n+\t *            String the project name to check\n+\t * @return boolean true if the project with the given name is in this\n+\t *         workspace\n+\t */\n+\tprivate boolean isProjectInWorkspace(String projectName) {\n+\t\tif (projectName == null) {\n+\t\t\treturn false;\n+\t\t}\n+\t\tIProject[] workspaceProjects = getProjectsInWorkspace();\n+\t\tfor (int i = 0; i < workspaceProjects.length; i++) {\n+\t\t\tif (projectName.equals(workspaceProjects[i].getName())) {\n+\t\t\t\treturn true;\n+\t\t\t}\n+\t\t}\n+\t\treturn false;\n+\t}\n+\n+}\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/components/RepositorySelectionPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/components/RepositorySelectionPage.java\nindex 86cf6ec..f656518 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/components/RepositorySelectionPage.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/components/RepositorySelectionPage.java\n@@ -660,4 +660,11 @@ private void updateAuthGroup() {\n \t\t\tbreak;\n \t\t}\n \t}\n+\n+\t@Override\n+\tpublic void setVisible(boolean visible) {\n+\t\tsuper.setVisible(visible);\n+\t\tif (visible)\n+\t\t\turiText.setFocus();\n+\t}\n }\n-- \n1.6.1.rc3.56.gd0306\n"},{"id":"99064","messageId":"20081231155444.GH29071@spearce.org","threadId":"16945","inReplyTo":"1230720969-1735-1-git-send-email-robin.rosenberg@dewire.com","subject":"Re: [EGIT PATCH] Add an import wizard for Eclipse projects as part of clone","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-12-31T15:54:44Z","receivedAt":"2008-12-31T15:54:44Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Robin Rosenberg <robin.rosenberg@dewire.com> wrote:\n> This adds an optional page for importing Eclipse style projects\n> as part of the clone operation.\n> \n> This patch I think, greatly simplifies getting an Eclipse based project\n> into the workbench.\n\nYes, yes it does!\n \n> I'm mostly interested in comments on pure bugs. E.g. know it's\n> blocking when the user selects to import the projects as part of the\n> clone process, I also know I'm reusing internal messages and not supplying\n> NLS style constansts for all textx.\n\nI noticed you mispelled \"showImportWizard\" as \"showImportWizarad\",\nbut otherwise it looks reasonable to me.  I'd like to see the NLS\nstuff extracted out before we apply the patch though.\n\nThe blocking part is annoying, but there isn't really a better\nway to do it.  What would be worse is going into the background,\nthen popping open a modal dialog when it completes, as it would\nreally disrupts the user.  So just don't clone massive projects\nand expect to use your workbench at the same time.  :-)\n\n-- \nShawn.\n"},{"id":"99146","messageId":"1230877098-9913-1-git-send-email-robin.rosenberg@dewire.com","threadId":"16945","inReplyTo":"20081231155444.GH29071@spearce.org","subject":"[EGIT PATCH] Add an import wizard for Eclipse projects as part of clone","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg@dewire.com","sentAt":"2009-01-02T06:18:18Z","receivedAt":"2009-01-02T06:18:18Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"This adds an optional page for importing Eclipse style projects\nas part of the clone operation. The import page is a stripped\ndown version of the project import wizard that comes with\neclipse with the added ability to connect the projects to\nthe Git team provider.\n\nSigned-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>\n---\n org.spearce.egit.ui/META-INF/MANIFEST.MF           |    1 +\n .../src/org/spearce/egit/ui/UIText.java            |   42 +\n .../ui/internal/clone/CloneDestinationPage.java    |   36 +-\n .../egit/ui/internal/clone/GitCloneWizard.java     |  106 +++-\n .../ui/internal/clone/GitProjectsImportPage.java   |  793 ++++++++++++++++++++\n .../components/RepositorySelectionPage.java        |    9 +-\n .../src/org/spearce/egit/ui/uitext.properties      |   15 +\n 7 files changed, 979 insertions(+), 23 deletions(-)\n create mode 100644 org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitProjectsImportPage.java\n\ndiff --git a/org.spearce.egit.ui/META-INF/MANIFEST.MF b/org.spearce.egit.ui/META-INF/MANIFEST.MF\nindex 092624f..420801b 100644\n--- a/org.spearce.egit.ui/META-INF/MANIFEST.MF\n+++ b/org.spearce.egit.ui/META-INF/MANIFEST.MF\n@@ -19,6 +19,7 @@ Require-Bundle: org.eclipse.core.runtime,\n  org.eclipse.compare,\n  org.spearce.jgit,\n  org.spearce.egit.core,\n+ org.eclipse.ui.ide,\n  org.eclipse.jsch.ui;bundle-version=\"1.1.100\"\n Eclipse-LazyStart: true\n Bundle-RequiredExecutionEnvironment: J2SE-1.5\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java\nindex b09cc10..124d7a0 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java\n@@ -17,6 +17,48 @@\n  */\n public class UIText extends NLS {\n \t/** */\n+\tpublic static String WizardProjectsImportPage_ImportProjectsTitle;\n+\n+\t/** */\n+\tpublic static String WizardProjectsImportPage_ImportProjectsDescription;\n+\n+\t/** */\n+\tpublic static String WizardProjectsImportPage_ProjectsListTitle;\n+\n+\t/** */\n+\tpublic static String WizardProjectsImportPage_selectAll;\n+\n+\t/** */\n+\tpublic static String WizardProjectsImportPage_deselectAll;\n+\n+\t/** */\n+\tpublic static String WizardProjectsImportPage_projectLabel;\n+\n+\t/** */\n+\tpublic static String WizardProjectsImportPage_SearchingMessage;\n+\n+\t/** */\n+\tpublic static String WizardProjectsImportPage_ProcessingMessage;\n+\n+\t/** */\n+\tpublic static String WizardProjectsImportPage_projectsInWorkspace;\n+\n+\t/** */\n+\tpublic static String WizardProjectsImportPage_CheckingMessage;\n+\n+\t/** */\n+\tpublic static String WizardProjectsImportPage_SelectDialogTitle;\n+\n+\t/** */\n+\tpublic static String WizardProjectImportPage_errorMessage;\n+\n+\t/** */\n+\tpublic static String WizardProjectsImportPage_CreateProjectsTask;\n+\n+\t/** */\n+\tpublic static String WizardProjectsImportPage_enableGit;\n+\n+\t/** */\n \tpublic static String SharingWizard_windowTitle;\n \n \t/** */\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/CloneDestinationPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/CloneDestinationPage.java\nindex 5173335..d017b60 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/CloneDestinationPage.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/CloneDestinationPage.java\n@@ -2,6 +2,7 @@\n  * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>\n  * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>\n  * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>\n+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>\n  *\n  * All rights reserved. This program and the accompanying materials\n  * are made available under the terms of the Eclipse Public License v1.0\n@@ -57,12 +58,15 @@\n \n \tprivate Text remoteText;\n \n+\tButton showImportWizard;\n+\n+\tString alreadyClonedInto;\n+\n \tCloneDestinationPage(final RepositorySelectionPage sp,\n \t\t\tfinal SourceBranchPage bp) {\n \t\tsuper(CloneDestinationPage.class.getName());\n \t\tsourcePage = sp;\n \t\tbranchPage = bp;\n-\n \t\tsetTitle(UIText.CloneDestinationPage_title);\n \n \t\tfinal SelectionChangeListener listener = new SelectionChangeListener() {\n@@ -82,7 +86,7 @@ public void createControl(final Composite parent) {\n \n \t\tcreateDestinationGroup(panel);\n \t\tcreateConfigGroup(panel);\n-\n+\t\tcreateWorkbenchGroup(panel);\n \t\tsetControl(panel);\n \t\tcheckPage();\n \t}\n@@ -92,6 +96,8 @@ public void setVisible(final boolean visible) {\n \t\tif (visible)\n \t\t\trevalidate();\n \t\tsuper.setVisible(visible);\n+\t\tif (visible)\n+\t\t\tdirectoryText.setFocus();\n \t}\n \n \tprivate void checkPreviousPagesSelections() {\n@@ -165,6 +171,20 @@ public void modifyText(ModifyEvent e) {\n \t\t});\n \t}\n \n+\tprivate void createWorkbenchGroup(Composite parent) {\n+\t\tfinal Group g = createGroup(parent, \"Workspace import\");\n+\t\tnewLabel(g, \"Import projects after clone\");\n+\t\tshowImportWizard = new Button(g, SWT.CHECK);\n+\t\tshowImportWizard.setSelection(true);\n+\t\tshowImportWizard.setLayoutData(createFieldGridData());\n+\t\tshowImportWizard.addSelectionListener(new SelectionAdapter() {\n+\t\t\t@Override\n+\t\t\tpublic void widgetSelected(SelectionEvent e) {\n+\t\t\t\tcheckPage();\n+\t\t\t}\n+\t\t});\n+\t}\n+\n \tprivate static Group createGroup(final Composite parent, final String text) {\n \t\tfinal Group g = new Group(parent, SWT.NONE);\n \t\tfinal GridLayout layout = new GridLayout();\n@@ -222,9 +242,11 @@ setErrorMessage(NLS.bind(UIText.CloneDestinationPage_fieldRequired,\n \t\t\treturn;\n \t\t}\n \t\tfinal File absoluteFile = new File(dstpath).getAbsoluteFile();\n-\t\tif (!isEmptyDir(absoluteFile)) {\n-\t\t\tsetErrorMessage(NLS.bind(UIText.CloneDestinationPage_errorNotEmptyDir,\n-\t\t\t\t\tabsoluteFile.getPath()));\n+\t\tif (!absoluteFile.getAbsolutePath().equals(alreadyClonedInto)\n+\t\t\t\t&& !isEmptyDir(absoluteFile)) {\n+\t\t\tsetErrorMessage(NLS.bind(\n+\t\t\t\t\tUIText.CloneDestinationPage_errorNotEmptyDir, absoluteFile\n+\t\t\t\t\t\t\t.getPath()));\n \t\t\tsetPageComplete(false);\n \t\t\treturn;\n \t\t}\n@@ -316,4 +338,8 @@ private String getSuggestedName() {\n \t\treturn path;\n \t}\n \n+\t@Override\n+\tpublic boolean canFlipToNextPage() {\n+\t\treturn super.canFlipToNextPage() && showImportWizard.getSelection();\n+\t}\n }\n\\ No newline at end of file\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitCloneWizard.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitCloneWizard.java\nindex a69dc52..114467f 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitCloneWizard.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitCloneWizard.java\n@@ -2,6 +2,7 @@\n  * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>\n  * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>\n  * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>\n+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>\n  *\n  * All rights reserved. This program and the accompanying materials\n  * are made available under the terms of the Eclipse Public License v1.0\n@@ -18,11 +19,13 @@\n import org.eclipse.core.runtime.Status;\n import org.eclipse.core.runtime.jobs.Job;\n import org.eclipse.jface.dialogs.ErrorDialog;\n+import org.eclipse.jface.dialogs.MessageDialog;\n import org.eclipse.jface.viewers.IStructuredSelection;\n import org.eclipse.jface.wizard.Wizard;\n import org.eclipse.osgi.util.NLS;\n import org.eclipse.ui.IImportWizard;\n import org.eclipse.ui.IWorkbench;\n+import org.eclipse.ui.PlatformUI;\n import org.spearce.egit.core.op.CloneOperation;\n import org.spearce.egit.ui.Activator;\n import org.spearce.egit.ui.UIIcons;\n@@ -41,6 +44,8 @@\n \n \tprivate CloneDestinationPage cloneDestination;\n \n+\tprivate GitProjectsImportPage importProject;\n+\n \tpublic void init(IWorkbench arg0, IStructuredSelection arg1) {\n \t\tsetWindowTitle(UIText.GitCloneWizard_title);\n \t\tsetDefaultPageImageDescriptor(UIIcons.WIZBAN_IMPORT_REPO);\n@@ -48,6 +53,46 @@ public void init(IWorkbench arg0, IStructuredSelection arg1) {\n \t\tcloneSource = new RepositorySelectionPage(true);\n \t\tvalidSource = new SourceBranchPage(cloneSource);\n \t\tcloneDestination = new CloneDestinationPage(cloneSource, validSource);\n+\t\timportProject = new GitProjectsImportPage() {\n+\t\t\t@Override\n+\t\t\tpublic void setVisible(boolean visible) {\n+\t\t\t\tif (visible) {\n+\t\t\t\t\tif (cloneDestination.alreadyClonedInto == null) {\n+\t\t\t\t\t\tperformClone(false);\n+\t\t\t\t\t\tcloneDestination.alreadyClonedInto = cloneDestination\n+\t\t\t\t\t\t\t\t.getDestinationFile().getAbsolutePath();\n+\t\t\t\t\t}\n+\t\t\t\t\tsetProjectsList(cloneDestination.alreadyClonedInto);\n+\t\t\t\t}\n+\t\t\t\tsuper.setVisible(visible);\n+\t\t\t}\n+\t\t};\n+\t}\n+\n+\t@Override\n+\tpublic boolean performCancel() {\n+\t\tif (cloneDestination.alreadyClonedInto != null) {\n+\t\t\tif (MessageDialog\n+\t\t\t\t\t.openQuestion(getShell(), \"Aborting clone.\",\n+\t\t\t\t\t\t\t\"A complete clone was already made. Do you want to delete it?\")) {\n+\t\t\t\tdeleteRecursively(new File(cloneDestination.alreadyClonedInto));\n+\t\t\t}\n+\t\t}\n+\t\treturn true;\n+\t}\n+\n+\tprivate void deleteRecursively(File f) {\n+\t\tfor (File i : f.listFiles()) {\n+\t\t\tif (i.isDirectory()) {\n+\t\t\t\tdeleteRecursively(i);\n+\t\t\t} else {\n+\t\t\t\tif (!i.delete()) {\n+\t\t\t\t\ti.deleteOnExit();\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\tif (!f.delete())\n+\t\t\tf.deleteOnExit();\n \t}\n \n \t@Override\n@@ -55,10 +100,24 @@ public void addPages() {\n \t\taddPage(cloneSource);\n \t\taddPage(validSource);\n \t\taddPage(cloneDestination);\n+\t\taddPage(importProject);\n+\t}\n+\n+\t@Override\n+\tpublic boolean canFinish() {\n+\t\treturn cloneDestination.isPageComplete()\n+\t\t\t\t&& !cloneDestination.showImportWizard.getSelection()\n+\t\t\t\t|| importProject.isPageComplete();\n \t}\n \n \t@Override\n \tpublic boolean performFinish() {\n+\t\tif (!cloneDestination.showImportWizard.getSelection())\n+\t\t\treturn performClone(true);\n+\t\treturn importProject.createProjects();\n+\t}\n+\n+\tboolean performClone(boolean background) {\n \t\tfinal URIish uri = cloneSource.getSelection().getURI();\n \t\tfinal boolean allSelected = validSource.isAllSelected();\n \t\tfinal Collection<Ref> selectedBranches = validSource\n@@ -80,24 +139,37 @@ public boolean performFinish() {\n \n \t\tfinal CloneOperation op = new CloneOperation(uri, allSelected,\n \t\t\t\tselectedBranches, workdir, branch, remoteName);\n-\t\tfinal Job job = new Job(NLS.bind(UIText.GitCloneWizard_jobName, uri\n-\t\t\t\t.toString())) {\n-\t\t\t@Override\n-\t\t\tprotected IStatus run(final IProgressMonitor monitor) {\n-\t\t\t\ttry {\n-\t\t\t\t\top.run(monitor);\n-\t\t\t\t\treturn Status.OK_STATUS;\n-\t\t\t\t} catch (InterruptedException e) {\n-\t\t\t\t\treturn Status.CANCEL_STATUS;\n-\t\t\t\t} catch (InvocationTargetException e) {\n-\t\t\t\t\tThrowable thr = e.getCause();\n-\t\t\t\t\treturn new Status(IStatus.ERROR, Activator.getPluginId(),\n-\t\t\t\t\t\t\t0, thr.getMessage(), thr);\n+\t\tif (background) {\n+\t\t\tfinal Job job = new Job(NLS.bind(UIText.GitCloneWizard_jobName, uri\n+\t\t\t\t\t.toString())) {\n+\t\t\t\t@Override\n+\t\t\t\tprotected IStatus run(final IProgressMonitor monitor) {\n+\t\t\t\t\ttry {\n+\t\t\t\t\t\top.run(monitor);\n+\t\t\t\t\t\treturn Status.OK_STATUS;\n+\t\t\t\t\t} catch (InterruptedException e) {\n+\t\t\t\t\t\treturn Status.CANCEL_STATUS;\n+\t\t\t\t\t} catch (InvocationTargetException e) {\n+\t\t\t\t\t\tThrowable thr = e.getCause();\n+\t\t\t\t\t\treturn new Status(IStatus.ERROR, Activator\n+\t\t\t\t\t\t\t\t.getPluginId(), 0, thr.getMessage(), thr);\n+\t\t\t\t\t}\n \t\t\t\t}\n+\t\t\t};\n+\t\t\tjob.setUser(true);\n+\t\t\tjob.schedule();\n+\t\t\treturn true;\n+\t\t} else {\n+\t\t\ttry {\n+\t\t\t\tPlatformUI.getWorkbench().getProgressService().run(false, true,\n+\t\t\t\t\t\top);\n+\t\t\t\treturn true;\n+\t\t\t} catch (Exception e) {\n+\t\t\t\tActivator.logError(\"Failed to clone\", e);\n+\t\t\t\tMessageDialog.openError(getShell(), \"Failed clone\", e\n+\t\t\t\t\t\t.toString());\n+\t\t\t\treturn false;\n \t\t\t}\n-\t\t};\n-\t\tjob.setUser(true);\n-\t\tjob.schedule();\n-\t\treturn true;\n+\t\t}\n \t}\n }\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitProjectsImportPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitProjectsImportPage.java\nnew file mode 100644\nindex 0000000..ece585a\n--- /dev/null\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitProjectsImportPage.java\n@@ -0,0 +1,793 @@\n+package org.spearce.egit.ui.internal.clone;\n+\n+/*******************************************************************************\n+ * Copyright (c) 2004, 2008 IBM Corporation and others.\n+ * Copyright (C) 2007, Martin Oberhuber (martin.oberhuber@windriver.com)\n+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>\n+ *\n+ * All rights reserved. This program and the accompanying materials\n+ * are made available under the terms of the Eclipse Public License v1.0\n+ * See LICENSE for the full license text, also available.\n+ *******************************************************************************/\n+\n+import java.io.File;\n+import java.io.IOException;\n+import java.lang.reflect.InvocationTargetException;\n+import java.util.ArrayList;\n+import java.util.Collection;\n+import java.util.HashSet;\n+import java.util.Iterator;\n+import java.util.List;\n+import java.util.Set;\n+\n+import org.eclipse.core.resources.IProject;\n+import org.eclipse.core.resources.IProjectDescription;\n+import org.eclipse.core.resources.IResource;\n+import org.eclipse.core.resources.IWorkspace;\n+import org.eclipse.core.resources.ResourcesPlugin;\n+import org.eclipse.core.runtime.CoreException;\n+import org.eclipse.core.runtime.IPath;\n+import org.eclipse.core.runtime.IProgressMonitor;\n+import org.eclipse.core.runtime.IStatus;\n+import org.eclipse.core.runtime.OperationCanceledException;\n+import org.eclipse.core.runtime.Path;\n+import org.eclipse.core.runtime.Platform;\n+import org.eclipse.core.runtime.Status;\n+import org.eclipse.core.runtime.SubProgressMonitor;\n+import org.eclipse.jface.dialogs.Dialog;\n+import org.eclipse.jface.dialogs.ErrorDialog;\n+import org.eclipse.jface.operation.IRunnableWithProgress;\n+import org.eclipse.jface.viewers.CheckStateChangedEvent;\n+import org.eclipse.jface.viewers.CheckboxTreeViewer;\n+import org.eclipse.jface.viewers.ICheckStateListener;\n+import org.eclipse.jface.viewers.ITreeContentProvider;\n+import org.eclipse.jface.viewers.LabelProvider;\n+import org.eclipse.jface.viewers.Viewer;\n+import org.eclipse.jface.viewers.ViewerComparator;\n+import org.eclipse.jface.wizard.WizardPage;\n+import org.eclipse.osgi.util.NLS;\n+import org.eclipse.swt.SWT;\n+import org.eclipse.swt.events.SelectionAdapter;\n+import org.eclipse.swt.events.SelectionEvent;\n+import org.eclipse.swt.layout.GridData;\n+import org.eclipse.swt.layout.GridLayout;\n+import org.eclipse.swt.widgets.Button;\n+import org.eclipse.swt.widgets.Composite;\n+import org.eclipse.swt.widgets.Label;\n+import org.eclipse.ui.actions.WorkspaceModifyOperation;\n+import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;\n+import org.eclipse.ui.internal.ide.StatusUtil;\n+import org.eclipse.ui.internal.wizards.datatransfer.WizardProjectsImportPage;\n+import org.eclipse.ui.statushandlers.StatusManager;\n+import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;\n+import org.spearce.egit.core.op.ConnectProviderOperation;\n+import org.spearce.egit.ui.Activator;\n+import org.spearce.egit.ui.UIText;\n+\n+/**\n+ * The GitWizardProjectsImportPage is the page that allows the user to import\n+ * projects from a particular location. This is a modified copy of\n+ * {@link WizardProjectsImportPage}\n+ */\n+public class GitProjectsImportPage extends WizardPage {\n+\n+\t/**\n+\t * The name of the folder containing metadata information for the workspace.\n+\t */\n+\tpublic static final String METADATA_FOLDER = \".metadata\"; //$NON-NLS-1$\n+\n+\t/**\n+\t * The import structure provider.\n+\t */\n+\tprivate IImportStructureProvider structureProvider;\n+\n+\tclass ProjectRecord {\n+\t\tFile projectSystemFile;\n+\n+\t\tString projectName;\n+\n+\t\tObject parent;\n+\n+\t\tint level;\n+\n+\t\tIProjectDescription description;\n+\n+\t\t/**\n+\t\t * Create a record for a project based on the info in the file.\n+\t\t *\n+\t\t * @param file\n+\t\t */\n+\t\tProjectRecord(File file) {\n+\t\t\tprojectSystemFile = file;\n+\t\t\tsetProjectName();\n+\t\t}\n+\n+\t\t/**\n+\t\t * @param parent\n+\t\t *            The parent folder of the .project file\n+\t\t * @param level\n+\t\t *            The number of levels deep in the provider the file is\n+\t\t */\n+\t\tProjectRecord(Object parent, int level) {\n+\t\t\tthis.parent = parent;\n+\t\t\tthis.level = level;\n+\t\t\tsetProjectName();\n+\t\t}\n+\n+\t\t/**\n+\t\t * Set the name of the project based on the projectFile.\n+\t\t */\n+\t\tprivate void setProjectName() {\n+\t\t\ttry {\n+\t\t\t\t// If we don't have the project name try again\n+\t\t\t\tif (projectName == null) {\n+\t\t\t\t\tIPath path = new Path(projectSystemFile.getPath());\n+\t\t\t\t\t// if the file is in the default location, use the directory\n+\t\t\t\t\t// name as the project name\n+\t\t\t\t\tif (isDefaultLocation(path)) {\n+\t\t\t\t\t\tprojectName = path.segment(path.segmentCount() - 2);\n+\t\t\t\t\t\tdescription = IDEWorkbenchPlugin.getPluginWorkspace()\n+\t\t\t\t\t\t\t\t.newProjectDescription(projectName);\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tdescription = IDEWorkbenchPlugin.getPluginWorkspace()\n+\t\t\t\t\t\t\t\t.loadProjectDescription(path);\n+\t\t\t\t\t\tprojectName = description.getName();\n+\t\t\t\t\t}\n+\n+\t\t\t\t}\n+\t\t\t} catch (CoreException e) {\n+\t\t\t\t// no good couldn't get the name\n+\t\t\t}\n+\t\t}\n+\n+\t\t/**\n+\t\t * Returns whether the given project description file path is in the\n+\t\t * default location for a project\n+\t\t *\n+\t\t * @param path\n+\t\t *            The path to examine\n+\t\t * @return Whether the given path is the default location for a project\n+\t\t */\n+\t\tprivate boolean isDefaultLocation(IPath path) {\n+\t\t\t// The project description file must at least be within the project,\n+\t\t\t// which is within the workspace location\n+\t\t\tif (path.segmentCount() < 2)\n+\t\t\t\treturn false;\n+\t\t\treturn path.removeLastSegments(2).toFile().equals(\n+\t\t\t\t\tPlatform.getLocation().toFile());\n+\t\t}\n+\n+\t\t/**\n+\t\t * Get the name of the project\n+\t\t *\n+\t\t * @return String\n+\t\t */\n+\t\tpublic String getProjectName() {\n+\t\t\treturn projectName;\n+\t\t}\n+\n+\t\t/**\n+\t\t * Gets the label to be used when rendering this project record in the\n+\t\t * UI.\n+\t\t *\n+\t\t * @return String the label\n+\t\t * @since 3.4\n+\t\t */\n+\t\tpublic String getProjectLabel() {\n+\t\t\tif (description == null)\n+\t\t\t\treturn projectName;\n+\n+\t\t\tString path = projectSystemFile == null ? structureProvider\n+\t\t\t\t\t.getLabel(parent) : projectSystemFile.getParent();\n+\n+\t\t\treturn NLS.bind(UIText.WizardProjectsImportPage_projectLabel,\n+\t\t\t\t\tprojectName, path);\n+\t\t}\n+\t}\n+\n+\tprivate CheckboxTreeViewer projectsList;\n+\n+\tprivate ProjectRecord[] selectedProjects = new ProjectRecord[0];\n+\n+\tprivate IProject[] wsProjects;\n+\n+\t// The last selected path to minimize searches\n+\tprivate String lastPath;\n+\n+\t// The last time that the file or folder at the selected path was modified\n+\t// to mimize searches\n+\tprivate long lastModified;\n+\n+\tprivate Button shareCheckBox;\n+\n+\tprivate boolean share;\n+\n+\t/**\n+\t * Creates a new project creation wizard page.\n+\t */\n+\tpublic GitProjectsImportPage() {\n+\t\tthis(\"gitWizardExternalProjectsPage\"); //$NON-NLS-1$\n+\t}\n+\n+\t/**\n+\t * Create a new instance of the receiver.\n+\t *\n+\t * @param pageName\n+\t */\n+\tpublic GitProjectsImportPage(String pageName) {\n+\t\tsuper(pageName);\n+\t\tsetPageComplete(false);\n+\t\tsetTitle(UIText.WizardProjectsImportPage_ImportProjectsTitle);\n+\t\tsetDescription(UIText.WizardProjectsImportPage_ImportProjectsDescription);\n+\t}\n+\n+\t/*\n+\t * (non-Javadoc)\n+\t *\n+\t * @see\n+\t * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets\n+\t * .Composite)\n+\t */\n+\tpublic void createControl(Composite parent) {\n+\n+\t\tinitializeDialogUnits(parent);\n+\n+\t\tComposite workArea = new Composite(parent, SWT.NONE);\n+\t\tsetControl(workArea);\n+\n+\t\tworkArea.setLayout(new GridLayout());\n+\t\tworkArea.setLayoutData(new GridData(GridData.FILL_BOTH\n+\t\t\t\t| GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL));\n+\n+\t\tcreateProjectsRoot(workArea);\n+\t\tcreateProjectsList(workArea);\n+\t\tcreateOptionsArea(workArea);\n+\t\tDialog.applyDialogFont(workArea);\n+\n+\t}\n+\n+\t/**\n+\t * Create the area with the extra options.\n+\t *\n+\t * @param workArea\n+\t */\n+\tprivate void createOptionsArea(Composite workArea) {\n+\t\tComposite optionsGroup = new Composite(workArea, SWT.NONE);\n+\t\toptionsGroup.setLayout(new GridLayout());\n+\t\toptionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));\n+\n+\t\tshareCheckBox = new Button(optionsGroup, SWT.CHECK);\n+\t\tshareCheckBox.setText(UIText.WizardProjectsImportPage_enableGit);\n+\t\tshareCheckBox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));\n+\t\tshareCheckBox.setSelection(share = true);\n+\t\tshareCheckBox.addSelectionListener(new SelectionAdapter() {\n+\t\t\tpublic void widgetSelected(SelectionEvent e) {\n+\t\t\t\tshare = shareCheckBox.getSelection();\n+\t\t\t}\n+\t\t});\n+\t}\n+\n+\t/**\n+\t * Create the checkbox list for the found projects.\n+\t *\n+\t * @param workArea\n+\t */\n+\tprivate void createProjectsList(Composite workArea) {\n+\n+\t\tLabel title = new Label(workArea, SWT.NONE);\n+\t\ttitle.setText(UIText.WizardProjectsImportPage_ProjectsListTitle);\n+\n+\t\tComposite listComposite = new Composite(workArea, SWT.NONE);\n+\t\tGridLayout layout = new GridLayout();\n+\t\tlayout.numColumns = 2;\n+\t\tlayout.marginWidth = 0;\n+\t\tlayout.makeColumnsEqualWidth = false;\n+\t\tlistComposite.setLayout(layout);\n+\n+\t\tlistComposite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL\n+\t\t\t\t| GridData.GRAB_VERTICAL | GridData.FILL_BOTH));\n+\n+\t\tprojectsList = new CheckboxTreeViewer(listComposite, SWT.BORDER);\n+\t\tGridData listData = new GridData(GridData.GRAB_HORIZONTAL\n+\t\t\t\t| GridData.GRAB_VERTICAL | GridData.FILL_BOTH);\n+\t\tprojectsList.getControl().setLayoutData(listData);\n+\n+\t\tprojectsList.setContentProvider(new ITreeContentProvider() {\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java\n+\t\t\t * .lang.Object)\n+\t\t\t */\n+\t\t\tpublic Object[] getChildren(Object parentElement) {\n+\t\t\t\treturn null;\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.IStructuredContentProvider#getElements\n+\t\t\t * (java.lang.Object)\n+\t\t\t */\n+\t\t\tpublic Object[] getElements(Object inputElement) {\n+\t\t\t\treturn getValidProjects();\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java\n+\t\t\t * .lang.Object)\n+\t\t\t */\n+\t\t\tpublic boolean hasChildren(Object element) {\n+\t\t\t\treturn false;\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.ITreeContentProvider#getParent(java\n+\t\t\t * .lang.Object)\n+\t\t\t */\n+\t\t\tpublic Object getParent(Object element) {\n+\t\t\t\treturn null;\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see org.eclipse.jface.viewers.IContentProvider#dispose()\n+\t\t\t */\n+\t\t\tpublic void dispose() {\n+\n+\t\t\t}\n+\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse\n+\t\t\t * .jface.viewers.Viewer, java.lang.Object, java.lang.Object)\n+\t\t\t */\n+\t\t\tpublic void inputChanged(Viewer viewer, Object oldInput,\n+\t\t\t\t\tObject newInput) {\n+\t\t\t}\n+\n+\t\t});\n+\n+\t\tprojectsList.setLabelProvider(new LabelProvider() {\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)\n+\t\t\t */\n+\t\t\tpublic String getText(Object element) {\n+\t\t\t\treturn ((ProjectRecord) element).getProjectLabel();\n+\t\t\t}\n+\t\t});\n+\n+\t\tprojectsList.addCheckStateListener(new ICheckStateListener() {\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged\n+\t\t\t * (org.eclipse.jface.viewers.CheckStateChangedEvent)\n+\t\t\t */\n+\t\t\tpublic void checkStateChanged(CheckStateChangedEvent event) {\n+\t\t\t\tsetPageComplete(projectsList.getCheckedElements().length > 0);\n+\t\t\t}\n+\t\t});\n+\n+\t\tprojectsList.setInput(this);\n+\t\tprojectsList.setComparator(new ViewerComparator());\n+\t\tcreateSelectionButtons(listComposite);\n+\t}\n+\n+\t/**\n+\t * Create the selection buttons in the listComposite.\n+\t *\n+\t * @param listComposite\n+\t */\n+\tprivate void createSelectionButtons(Composite listComposite) {\n+\t\tComposite buttonsComposite = new Composite(listComposite, SWT.NONE);\n+\t\tGridLayout layout = new GridLayout();\n+\t\tlayout.marginWidth = 0;\n+\t\tlayout.marginHeight = 0;\n+\t\tbuttonsComposite.setLayout(layout);\n+\n+\t\tbuttonsComposite.setLayoutData(new GridData(\n+\t\t\t\tGridData.VERTICAL_ALIGN_BEGINNING));\n+\n+\t\tButton selectAll = new Button(buttonsComposite, SWT.PUSH);\n+\t\tselectAll.setText(UIText.WizardProjectsImportPage_selectAll);\n+\t\tselectAll.addSelectionListener(new SelectionAdapter() {\n+\t\t\tpublic void widgetSelected(SelectionEvent e) {\n+\t\t\t\tprojectsList.setCheckedElements(selectedProjects);\n+\t\t\t\tsetPageComplete(projectsList.getCheckedElements().length > 0);\n+\t\t\t}\n+\t\t});\n+\t\tDialog.applyDialogFont(selectAll);\n+\t\tsetButtonLayoutData(selectAll);\n+\n+\t\tButton deselectAll = new Button(buttonsComposite, SWT.PUSH);\n+\t\tdeselectAll.setText(UIText.WizardProjectsImportPage_deselectAll);\n+\t\tdeselectAll.addSelectionListener(new SelectionAdapter() {\n+\t\t\t/*\n+\t\t\t * (non-Javadoc)\n+\t\t\t *\n+\t\t\t * @see\n+\t\t\t * org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse\n+\t\t\t * .swt.events.SelectionEvent)\n+\t\t\t */\n+\t\t\tpublic void widgetSelected(SelectionEvent e) {\n+\n+\t\t\t\tprojectsList.setCheckedElements(new Object[0]);\n+\t\t\t\tsetPageComplete(false);\n+\t\t\t}\n+\t\t});\n+\t\tDialog.applyDialogFont(deselectAll);\n+\t\tsetButtonLayoutData(deselectAll);\n+\n+\t}\n+\n+\t/**\n+\t * Create the area where you select the root directory for the projects.\n+\t *\n+\t * @param workArea\n+\t *            Composite\n+\t */\n+\tprivate void createProjectsRoot(Composite workArea) {\n+\n+\t\t// project specification group\n+\t\tComposite projectGroup = new Composite(workArea, SWT.NONE);\n+\t\tGridLayout layout = new GridLayout();\n+\t\tlayout.numColumns = 3;\n+\t\tlayout.makeColumnsEqualWidth = false;\n+\t\tlayout.marginWidth = 0;\n+\t\tprojectGroup.setLayout(layout);\n+\t\tprojectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));\n+\n+\t}\n+\n+\t/*\n+\t * (non-Javadoc) Method declared on IDialogPage. Set the focus on path\n+\t * fields when page becomes visible.\n+\t */\n+\tpublic void setVisible(boolean visible) {\n+\t\tsuper.setVisible(visible);\n+\t}\n+\n+\t/**\n+\t * Update the list of projects based on path.\n+\t *\n+\t * @param path\n+\t */\n+\tvoid setProjectsList(final String path) {\n+\t\t// on an empty path empty selectedProjects\n+\t\tif (path == null || path.length() == 0) {\n+\t\t\tsetMessage(UIText.WizardProjectsImportPage_ImportProjectsDescription);\n+\t\t\tselectedProjects = new ProjectRecord[0];\n+\t\t\tprojectsList.refresh(true);\n+\t\t\tprojectsList.setCheckedElements(selectedProjects);\n+\t\t\tsetPageComplete(projectsList.getCheckedElements().length > 0);\n+\t\t\tlastPath = path;\n+\t\t\treturn;\n+\t\t}\n+\n+\t\tfinal File directory = new File(path);\n+\t\tlong modified = directory.lastModified();\n+\t\tif (path.equals(lastPath) && lastModified == modified) {\n+\t\t\t// since the file/folder was not modified and the path did not\n+\t\t\t// change, no refreshing is required\n+\t\t\treturn;\n+\t\t}\n+\n+\t\tlastPath = path;\n+\t\tlastModified = modified;\n+\n+\t\ttry {\n+\t\t\tgetContainer().run(true, true, new IRunnableWithProgress() {\n+\n+\t\t\t\t/*\n+\t\t\t\t * (non-Javadoc)\n+\t\t\t\t *\n+\t\t\t\t * @see\n+\t\t\t\t * org.eclipse.jface.operation.IRunnableWithProgress#run(org\n+\t\t\t\t * .eclipse.core.runtime.IProgressMonitor)\n+\t\t\t\t */\n+\t\t\t\tpublic void run(IProgressMonitor monitor) {\n+\n+\t\t\t\t\tmonitor.beginTask(\n+\t\t\t\t\t\t\tUIText.WizardProjectsImportPage_SearchingMessage,\n+\t\t\t\t\t\t\t100);\n+\t\t\t\t\tselectedProjects = new ProjectRecord[0];\n+\t\t\t\t\tCollection files = new ArrayList();\n+\t\t\t\t\tmonitor.worked(10);\n+\t\t\t\t\tif (directory.isDirectory()) {\n+\n+\t\t\t\t\t\tif (!collectProjectFilesFromDirectory(files, directory,\n+\t\t\t\t\t\t\t\tnull, monitor)) {\n+\t\t\t\t\t\t\treturn;\n+\t\t\t\t\t\t}\n+\t\t\t\t\t\tIterator filesIterator = files.iterator();\n+\t\t\t\t\t\tselectedProjects = new ProjectRecord[files.size()];\n+\t\t\t\t\t\tint index = 0;\n+\t\t\t\t\t\tmonitor.worked(50);\n+\t\t\t\t\t\tmonitor\n+\t\t\t\t\t\t\t\t.subTask(UIText.WizardProjectsImportPage_ProcessingMessage);\n+\t\t\t\t\t\twhile (filesIterator.hasNext()) {\n+\t\t\t\t\t\t\tFile file = (File) filesIterator.next();\n+\t\t\t\t\t\t\tselectedProjects[index] = new ProjectRecord(file);\n+\t\t\t\t\t\t\tindex++;\n+\t\t\t\t\t\t}\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tmonitor.worked(60);\n+\t\t\t\t\t}\n+\t\t\t\t\tmonitor.done();\n+\t\t\t\t}\n+\n+\t\t\t});\n+\t\t} catch (InvocationTargetException e) {\n+\t\t\tIDEWorkbenchPlugin.log(e.getMessage(), e);\n+\t\t} catch (InterruptedException e) {\n+\t\t\t// Nothing to do if the user interrupts.\n+\t\t}\n+\n+\t\tprojectsList.refresh(true);\n+\t\tprojectsList.setCheckedElements(getValidProjects());\n+\t\tif (getValidProjects().length < selectedProjects.length) {\n+\t\t\tsetMessage(UIText.WizardProjectsImportPage_projectsInWorkspace,\n+\t\t\t\t\tWARNING);\n+\t\t} else {\n+\t\t\tsetMessage(UIText.WizardProjectsImportPage_ImportProjectsDescription);\n+\t\t}\n+\t\tsetPageComplete(projectsList.getCheckedElements().length > 0);\n+\t}\n+\n+\t/**\n+\t * Collect the list of .project files that are under directory into files.\n+\t *\n+\t * @param files\n+\t * @param directory\n+\t * @param directoriesVisited\n+\t *            Set of canonical paths of directories, used as recursion guard\n+\t * @param monitor\n+\t *            The monitor to report to\n+\t * @return boolean <code>true</code> if the operation was completed.\n+\t */\n+\tprivate boolean collectProjectFilesFromDirectory(Collection files,\n+\t\t\tFile directory, Set directoriesVisited, IProgressMonitor monitor) {\n+\n+\t\tif (monitor.isCanceled()) {\n+\t\t\treturn false;\n+\t\t}\n+\t\tmonitor.subTask(NLS.bind(\n+\t\t\t\tUIText.WizardProjectsImportPage_CheckingMessage, directory\n+\t\t\t\t\t\t.getPath()));\n+\t\tFile[] contents = directory.listFiles();\n+\t\tif (contents == null)\n+\t\t\treturn false;\n+\n+\t\t// Initialize recursion guard for recursive symbolic links\n+\t\tif (directoriesVisited == null) {\n+\t\t\tdirectoriesVisited = new HashSet();\n+\t\t\ttry {\n+\t\t\t\tdirectoriesVisited.add(directory.getCanonicalPath());\n+\t\t\t} catch (IOException exception) {\n+\t\t\t\tStatusManager.getManager().handle(\n+\t\t\t\t\t\tStatusUtil.newStatus(IStatus.ERROR, exception\n+\t\t\t\t\t\t\t\t.getLocalizedMessage(), exception));\n+\t\t\t}\n+\t\t}\n+\n+\t\t// first look for project description files\n+\t\tfinal String dotProject = IProjectDescription.DESCRIPTION_FILE_NAME;\n+\t\tfor (int i = 0; i < contents.length; i++) {\n+\t\t\tFile file = contents[i];\n+\t\t\tif (file.isFile() && file.getName().equals(dotProject)) {\n+\t\t\t\tfiles.add(file);\n+\t\t\t\t// don't search sub-directories since we can't have nested\n+\t\t\t\t// projects\n+\t\t\t\treturn true;\n+\t\t\t}\n+\t\t}\n+\t\t// no project description found, so recurse into sub-directories\n+\t\tfor (int i = 0; i < contents.length; i++) {\n+\t\t\tif (contents[i].isDirectory()) {\n+\t\t\t\tif (!contents[i].getName().equals(METADATA_FOLDER)) {\n+\t\t\t\t\ttry {\n+\t\t\t\t\t\tString canonicalPath = contents[i].getCanonicalPath();\n+\t\t\t\t\t\tif (!directoriesVisited.add(canonicalPath)) {\n+\t\t\t\t\t\t\t// already been here --> do not recurse\n+\t\t\t\t\t\t\tcontinue;\n+\t\t\t\t\t\t}\n+\t\t\t\t\t} catch (IOException exception) {\n+\t\t\t\t\t\tStatusManager.getManager().handle(\n+\t\t\t\t\t\t\t\tStatusUtil.newStatus(IStatus.ERROR, exception\n+\t\t\t\t\t\t\t\t\t\t.getLocalizedMessage(), exception));\n+\n+\t\t\t\t\t}\n+\t\t\t\t\tcollectProjectFilesFromDirectory(files, contents[i],\n+\t\t\t\t\t\t\tdirectoriesVisited, monitor);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t\treturn true;\n+\t}\n+\n+\t/**\n+\t * Create the selected projects\n+\t *\n+\t * @return boolean <code>true</code> if all project creations were\n+\t *         successful.\n+\t */\n+\tboolean createProjects() {\n+\t\tfinal Object[] selected = projectsList.getCheckedElements();\n+\t\tWorkspaceModifyOperation op = new WorkspaceModifyOperation() {\n+\t\t\tprotected void execute(IProgressMonitor monitor)\n+\t\t\t\t\tthrows InvocationTargetException, InterruptedException {\n+\t\t\t\ttry {\n+\t\t\t\t\tmonitor.beginTask(\"\", selected.length); //$NON-NLS-1$\n+\t\t\t\t\tif (monitor.isCanceled()) {\n+\t\t\t\t\t\tthrow new OperationCanceledException();\n+\t\t\t\t\t}\n+\t\t\t\t\tfor (int i = 0; i < selected.length; i++) {\n+\t\t\t\t\t\tcreateExistingProject((ProjectRecord) selected[i],\n+\t\t\t\t\t\t\t\tnew SubProgressMonitor(monitor, 1));\n+\t\t\t\t\t}\n+\t\t\t\t} finally {\n+\t\t\t\t\tmonitor.done();\n+\t\t\t\t}\n+\t\t\t}\n+\t\t};\n+\t\t// run the new project creation operation\n+\t\ttry {\n+\t\t\tgetContainer().run(true, true, op);\n+\t\t} catch (InterruptedException e) {\n+\t\t\treturn false;\n+\t\t} catch (InvocationTargetException e) {\n+\t\t\t// one of the steps resulted in a core exception\n+\t\t\tThrowable t = e.getTargetException();\n+\t\t\tString message = UIText.WizardProjectImportPage_errorMessage;\n+\t\t\tIStatus status;\n+\t\t\tif (t instanceof CoreException) {\n+\t\t\t\tstatus = ((CoreException) t).getStatus();\n+\t\t\t} else {\n+\t\t\t\tstatus = new Status(IStatus.ERROR,\n+\t\t\t\t\t\tIDEWorkbenchPlugin.IDE_WORKBENCH, 1, message, t);\n+\t\t\t}\n+\t\t\tActivator.logError(message, t);\n+\t\t\tErrorDialog.openError(getShell(), message, null, status);\n+\t\t\treturn false;\n+\t\t}\n+\t\treturn true;\n+\t}\n+\n+\t/**\n+\t * Create the project described in record. If it is successful return true.\n+\t *\n+\t * @param record\n+\t * @param monitor\n+\t * @return boolean <code>true</code> if successful\n+\t * @throws InvocationTargetException\n+\t * @throws InterruptedException\n+\t */\n+\tprivate boolean createExistingProject(final ProjectRecord record,\n+\t\t\tIProgressMonitor monitor) throws InvocationTargetException,\n+\t\t\tInterruptedException {\n+\t\tString projectName = record.getProjectName();\n+\t\tfinal IWorkspace workspace = ResourcesPlugin.getWorkspace();\n+\t\tfinal IProject project = workspace.getRoot().getProject(projectName);\n+\t\tif (record.description == null) {\n+\t\t\t// error case\n+\t\t\trecord.description = workspace.newProjectDescription(projectName);\n+\t\t\tIPath locationPath = new Path(record.projectSystemFile\n+\t\t\t\t\t.getAbsolutePath());\n+\n+\t\t\t// If it is under the root use the default location\n+\t\t\tif (Platform.getLocation().isPrefixOf(locationPath)) {\n+\t\t\t\trecord.description.setLocation(null);\n+\t\t\t} else {\n+\t\t\t\trecord.description.setLocation(locationPath);\n+\t\t\t}\n+\t\t} else {\n+\t\t\trecord.description.setName(projectName);\n+\t\t}\n+\n+\t\ttry {\n+\t\t\tmonitor.beginTask(\n+\t\t\t\t\tUIText.WizardProjectsImportPage_CreateProjectsTask, 100);\n+\t\t\tproject.create(record.description, new SubProgressMonitor(monitor,\n+\t\t\t\t\t30));\n+\t\t\tint openTicks = share ? 50 : 70;\n+\t\t\tproject.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(\n+\t\t\t\t\tmonitor, openTicks));\n+\t\t\tif (share) {\n+\t\t\t\tConnectProviderOperation connectProviderOperation = new ConnectProviderOperation(\n+\t\t\t\t\t\tproject, null);\n+\t\t\t\tconnectProviderOperation\n+\t\t\t\t\t\t.run(new SubProgressMonitor(monitor, 20));\n+\t\t\t}\n+\t\t} catch (CoreException e) {\n+\t\t\tthrow new InvocationTargetException(e);\n+\t\t} finally {\n+\t\t\tmonitor.done();\n+\t\t}\n+\n+\t\treturn true;\n+\t}\n+\n+\t/**\n+\t * Method used for test suite.\n+\t *\n+\t * @return CheckboxTreeViewer the viewer containing all the projects found\n+\t */\n+\tpublic CheckboxTreeViewer getProjectsList() {\n+\t\treturn projectsList;\n+\t}\n+\n+\t/**\n+\t * Retrieve all the projects in the current workspace.\n+\t *\n+\t * @return IProject[] array of IProject in the current workspace\n+\t */\n+\tprivate IProject[] getProjectsInWorkspace() {\n+\t\tif (wsProjects == null) {\n+\t\t\twsProjects = IDEWorkbenchPlugin.getPluginWorkspace().getRoot()\n+\t\t\t\t\t.getProjects();\n+\t\t}\n+\t\treturn wsProjects;\n+\t}\n+\n+\t/**\n+\t * Get the array of valid project records that can be imported from the\n+\t * source workspace or archive, selected by the user. If a project with the\n+\t * same name exists in both the source workspace and the current workspace,\n+\t * it will not appear in the list of projects to import and thus cannot be\n+\t * selected for import.\n+\t *\n+\t * Method declared public for test suite.\n+\t *\n+\t * @return ProjectRecord[] array of projects that can be imported into the\n+\t *         workspace\n+\t */\n+\tpublic ProjectRecord[] getValidProjects() {\n+\t\tList validProjects = new ArrayList();\n+\t\tfor (int i = 0; i < selectedProjects.length; i++) {\n+\t\t\tif (!isProjectInWorkspace(selectedProjects[i].getProjectName())) {\n+\t\t\t\tvalidProjects.add(selectedProjects[i]);\n+\t\t\t}\n+\t\t}\n+\t\treturn (ProjectRecord[]) validProjects\n+\t\t\t\t.toArray(new ProjectRecord[validProjects.size()]);\n+\t}\n+\n+\t/**\n+\t * Determine if the project with the given name is in the current workspace.\n+\t *\n+\t * @param projectName\n+\t *            String the project name to check\n+\t * @return boolean true if the project with the given name is in this\n+\t *         workspace\n+\t */\n+\tprivate boolean isProjectInWorkspace(String projectName) {\n+\t\tif (projectName == null) {\n+\t\t\treturn false;\n+\t\t}\n+\t\tIProject[] workspaceProjects = getProjectsInWorkspace();\n+\t\tfor (int i = 0; i < workspaceProjects.length; i++) {\n+\t\t\tif (projectName.equals(workspaceProjects[i].getName())) {\n+\t\t\t\treturn true;\n+\t\t\t}\n+\t\t}\n+\t\treturn false;\n+\t}\n+\n+}\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/components/RepositorySelectionPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/components/RepositorySelectionPage.java\nindex 86cf6ec..4f02c95 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/components/RepositorySelectionPage.java\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/components/RepositorySelectionPage.java\n@@ -1,5 +1,5 @@\n /*******************************************************************************\n- * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>\n+ * Copyright (C) 2007, 2008, Robin Rosenberg <robin.rosenberg@dewire.com>\n  * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>\n  * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>\n  * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>\n@@ -660,4 +660,11 @@ private void updateAuthGroup() {\n \t\t\tbreak;\n \t\t}\n \t}\n+\n+\t@Override\n+\tpublic void setVisible(boolean visible) {\n+\t\tsuper.setVisible(visible);\n+\t\tif (visible)\n+\t\t\turiText.setFocus();\n+\t}\n }\ndiff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties b/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties\nindex 22e29c2..98ce80f 100644\n--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties\n+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties\n@@ -15,6 +15,21 @@\n ##  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301\n ##\n \n+WizardProjectsImportPage_projectLabel={0} ({1})\n+WizardProjectsImportPage_ImportProjectsTitle=Import Projects\n+WizardProjectsImportPage_ImportProjectsDescription=Import projects from cloned repository into workbench\n+WizardProjectsImportPage_ProjectsListTitle=&Projects\n+WizardProjectsImportPage_selectAll = &Select All\n+WizardProjectsImportPage_deselectAll = &Deselect All\n+WizardProjectsImportPage_SearchingMessage = Searching for projects\n+WizardProjectsImportPage_ProcessingMessage = Processing results\n+WizardProjectsImportPage_projectsInWorkspace = Some projects were hidden because they exist in the workspace directory\n+WizardProjectsImportPage_CheckingMessage = Checking: {0}\n+WizardProjectsImportPage_SelectDialogTitle = Select root directory of the projects to import\n+WizardProjectImportPage_errorMessage = Creation Problems\n+WizardProjectsImportPage_CreateProjectsTask = Creating Projects\n+WizardProjectsImportPage_enableGit = Enable Git Team operations on imported projects\n+\n SharingWizard_windowTitle=Configure Git Repository\n SharingWizard_failed=Failed to initialize Git team provider.\n \n-- \n1.6.1.rc3.56.gd0306\n"}]}