From: Robin Rosenberg <robin.rosenberg@dewire.com>
To: spearce@spearce.org
Cc: git@vger.kernel.org, Robin Rosenberg <robin.rosenberg@dewire.com>
Subject: [EGIT PATCH] Add an import wizard for Eclipse projects as part of clone
Date: Fri, 2 Jan 2009 07:18:18 +0100 [thread overview]
Message-ID: <1230877098-9913-1-git-send-email-robin.rosenberg@dewire.com> (raw)
In-Reply-To: <20081231155444.GH29071@spearce.org>
This adds an optional page for importing Eclipse style projects
as part of the clone operation. The import page is a stripped
down version of the project import wizard that comes with
eclipse with the added ability to connect the projects to
the Git team provider.
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
org.spearce.egit.ui/META-INF/MANIFEST.MF | 1 +
.../src/org/spearce/egit/ui/UIText.java | 42 +
.../ui/internal/clone/CloneDestinationPage.java | 36 +-
.../egit/ui/internal/clone/GitCloneWizard.java | 106 +++-
.../ui/internal/clone/GitProjectsImportPage.java | 793 ++++++++++++++++++++
.../components/RepositorySelectionPage.java | 9 +-
.../src/org/spearce/egit/ui/uitext.properties | 15 +
7 files changed, 979 insertions(+), 23 deletions(-)
create mode 100644 org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitProjectsImportPage.java
diff --git a/org.spearce.egit.ui/META-INF/MANIFEST.MF b/org.spearce.egit.ui/META-INF/MANIFEST.MF
index 092624f..420801b 100644
--- a/org.spearce.egit.ui/META-INF/MANIFEST.MF
+++ b/org.spearce.egit.ui/META-INF/MANIFEST.MF
@@ -19,6 +19,7 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.compare,
org.spearce.jgit,
org.spearce.egit.core,
+ org.eclipse.ui.ide,
org.eclipse.jsch.ui;bundle-version="1.1.100"
Eclipse-LazyStart: true
Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --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
index b09cc10..124d7a0 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java
@@ -17,6 +17,48 @@
*/
public class UIText extends NLS {
/** */
+ public static String WizardProjectsImportPage_ImportProjectsTitle;
+
+ /** */
+ public static String WizardProjectsImportPage_ImportProjectsDescription;
+
+ /** */
+ public static String WizardProjectsImportPage_ProjectsListTitle;
+
+ /** */
+ public static String WizardProjectsImportPage_selectAll;
+
+ /** */
+ public static String WizardProjectsImportPage_deselectAll;
+
+ /** */
+ public static String WizardProjectsImportPage_projectLabel;
+
+ /** */
+ public static String WizardProjectsImportPage_SearchingMessage;
+
+ /** */
+ public static String WizardProjectsImportPage_ProcessingMessage;
+
+ /** */
+ public static String WizardProjectsImportPage_projectsInWorkspace;
+
+ /** */
+ public static String WizardProjectsImportPage_CheckingMessage;
+
+ /** */
+ public static String WizardProjectsImportPage_SelectDialogTitle;
+
+ /** */
+ public static String WizardProjectImportPage_errorMessage;
+
+ /** */
+ public static String WizardProjectsImportPage_CreateProjectsTask;
+
+ /** */
+ public static String WizardProjectsImportPage_enableGit;
+
+ /** */
public static String SharingWizard_windowTitle;
/** */
diff --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
index 5173335..d017b60 100644
--- 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
@@ -2,6 +2,7 @@
* Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
* Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -57,12 +58,15 @@
private Text remoteText;
+ Button showImportWizard;
+
+ String alreadyClonedInto;
+
CloneDestinationPage(final RepositorySelectionPage sp,
final SourceBranchPage bp) {
super(CloneDestinationPage.class.getName());
sourcePage = sp;
branchPage = bp;
-
setTitle(UIText.CloneDestinationPage_title);
final SelectionChangeListener listener = new SelectionChangeListener() {
@@ -82,7 +86,7 @@ public void createControl(final Composite parent) {
createDestinationGroup(panel);
createConfigGroup(panel);
-
+ createWorkbenchGroup(panel);
setControl(panel);
checkPage();
}
@@ -92,6 +96,8 @@ public void setVisible(final boolean visible) {
if (visible)
revalidate();
super.setVisible(visible);
+ if (visible)
+ directoryText.setFocus();
}
private void checkPreviousPagesSelections() {
@@ -165,6 +171,20 @@ public void modifyText(ModifyEvent e) {
});
}
+ private void createWorkbenchGroup(Composite parent) {
+ final Group g = createGroup(parent, "Workspace import");
+ newLabel(g, "Import projects after clone");
+ showImportWizard = new Button(g, SWT.CHECK);
+ showImportWizard.setSelection(true);
+ showImportWizard.setLayoutData(createFieldGridData());
+ showImportWizard.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ checkPage();
+ }
+ });
+ }
+
private static Group createGroup(final Composite parent, final String text) {
final Group g = new Group(parent, SWT.NONE);
final GridLayout layout = new GridLayout();
@@ -222,9 +242,11 @@ setErrorMessage(NLS.bind(UIText.CloneDestinationPage_fieldRequired,
return;
}
final File absoluteFile = new File(dstpath).getAbsoluteFile();
- if (!isEmptyDir(absoluteFile)) {
- setErrorMessage(NLS.bind(UIText.CloneDestinationPage_errorNotEmptyDir,
- absoluteFile.getPath()));
+ if (!absoluteFile.getAbsolutePath().equals(alreadyClonedInto)
+ && !isEmptyDir(absoluteFile)) {
+ setErrorMessage(NLS.bind(
+ UIText.CloneDestinationPage_errorNotEmptyDir, absoluteFile
+ .getPath()));
setPageComplete(false);
return;
}
@@ -316,4 +338,8 @@ private String getSuggestedName() {
return path;
}
+ @Override
+ public boolean canFlipToNextPage() {
+ return super.canFlipToNextPage() && showImportWizard.getSelection();
+ }
}
\ No newline at end of file
diff --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
index a69dc52..114467f 100644
--- 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
@@ -2,6 +2,7 @@
* Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
* Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -18,11 +19,13 @@
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.IImportWizard;
import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
import org.spearce.egit.core.op.CloneOperation;
import org.spearce.egit.ui.Activator;
import org.spearce.egit.ui.UIIcons;
@@ -41,6 +44,8 @@
private CloneDestinationPage cloneDestination;
+ private GitProjectsImportPage importProject;
+
public void init(IWorkbench arg0, IStructuredSelection arg1) {
setWindowTitle(UIText.GitCloneWizard_title);
setDefaultPageImageDescriptor(UIIcons.WIZBAN_IMPORT_REPO);
@@ -48,6 +53,46 @@ public void init(IWorkbench arg0, IStructuredSelection arg1) {
cloneSource = new RepositorySelectionPage(true);
validSource = new SourceBranchPage(cloneSource);
cloneDestination = new CloneDestinationPage(cloneSource, validSource);
+ importProject = new GitProjectsImportPage() {
+ @Override
+ public void setVisible(boolean visible) {
+ if (visible) {
+ if (cloneDestination.alreadyClonedInto == null) {
+ performClone(false);
+ cloneDestination.alreadyClonedInto = cloneDestination
+ .getDestinationFile().getAbsolutePath();
+ }
+ setProjectsList(cloneDestination.alreadyClonedInto);
+ }
+ super.setVisible(visible);
+ }
+ };
+ }
+
+ @Override
+ public boolean performCancel() {
+ if (cloneDestination.alreadyClonedInto != null) {
+ if (MessageDialog
+ .openQuestion(getShell(), "Aborting clone.",
+ "A complete clone was already made. Do you want to delete it?")) {
+ deleteRecursively(new File(cloneDestination.alreadyClonedInto));
+ }
+ }
+ return true;
+ }
+
+ private void deleteRecursively(File f) {
+ for (File i : f.listFiles()) {
+ if (i.isDirectory()) {
+ deleteRecursively(i);
+ } else {
+ if (!i.delete()) {
+ i.deleteOnExit();
+ }
+ }
+ }
+ if (!f.delete())
+ f.deleteOnExit();
}
@Override
@@ -55,10 +100,24 @@ public void addPages() {
addPage(cloneSource);
addPage(validSource);
addPage(cloneDestination);
+ addPage(importProject);
+ }
+
+ @Override
+ public boolean canFinish() {
+ return cloneDestination.isPageComplete()
+ && !cloneDestination.showImportWizard.getSelection()
+ || importProject.isPageComplete();
}
@Override
public boolean performFinish() {
+ if (!cloneDestination.showImportWizard.getSelection())
+ return performClone(true);
+ return importProject.createProjects();
+ }
+
+ boolean performClone(boolean background) {
final URIish uri = cloneSource.getSelection().getURI();
final boolean allSelected = validSource.isAllSelected();
final Collection<Ref> selectedBranches = validSource
@@ -80,24 +139,37 @@ public boolean performFinish() {
final CloneOperation op = new CloneOperation(uri, allSelected,
selectedBranches, workdir, branch, remoteName);
- final Job job = new Job(NLS.bind(UIText.GitCloneWizard_jobName, uri
- .toString())) {
- @Override
- protected IStatus run(final IProgressMonitor monitor) {
- try {
- op.run(monitor);
- return Status.OK_STATUS;
- } catch (InterruptedException e) {
- return Status.CANCEL_STATUS;
- } catch (InvocationTargetException e) {
- Throwable thr = e.getCause();
- return new Status(IStatus.ERROR, Activator.getPluginId(),
- 0, thr.getMessage(), thr);
+ if (background) {
+ final Job job = new Job(NLS.bind(UIText.GitCloneWizard_jobName, uri
+ .toString())) {
+ @Override
+ protected IStatus run(final IProgressMonitor monitor) {
+ try {
+ op.run(monitor);
+ return Status.OK_STATUS;
+ } catch (InterruptedException e) {
+ return Status.CANCEL_STATUS;
+ } catch (InvocationTargetException e) {
+ Throwable thr = e.getCause();
+ return new Status(IStatus.ERROR, Activator
+ .getPluginId(), 0, thr.getMessage(), thr);
+ }
}
+ };
+ job.setUser(true);
+ job.schedule();
+ return true;
+ } else {
+ try {
+ PlatformUI.getWorkbench().getProgressService().run(false, true,
+ op);
+ return true;
+ } catch (Exception e) {
+ Activator.logError("Failed to clone", e);
+ MessageDialog.openError(getShell(), "Failed clone", e
+ .toString());
+ return false;
}
- };
- job.setUser(true);
- job.schedule();
- return true;
+ }
}
}
diff --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
new file mode 100644
index 0000000..ece585a
--- /dev/null
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitProjectsImportPage.java
@@ -0,0 +1,793 @@
+package org.spearce.egit.ui.internal.clone;
+
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * Copyright (C) 2007, Martin Oberhuber (martin.oberhuber@windriver.com)
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * See LICENSE for the full license text, also available.
+ *******************************************************************************/
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerComparator;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.actions.WorkspaceModifyOperation;
+import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
+import org.eclipse.ui.internal.ide.StatusUtil;
+import org.eclipse.ui.internal.wizards.datatransfer.WizardProjectsImportPage;
+import org.eclipse.ui.statushandlers.StatusManager;
+import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
+import org.spearce.egit.core.op.ConnectProviderOperation;
+import org.spearce.egit.ui.Activator;
+import org.spearce.egit.ui.UIText;
+
+/**
+ * The GitWizardProjectsImportPage is the page that allows the user to import
+ * projects from a particular location. This is a modified copy of
+ * {@link WizardProjectsImportPage}
+ */
+public class GitProjectsImportPage extends WizardPage {
+
+ /**
+ * The name of the folder containing metadata information for the workspace.
+ */
+ public static final String METADATA_FOLDER = ".metadata"; //$NON-NLS-1$
+
+ /**
+ * The import structure provider.
+ */
+ private IImportStructureProvider structureProvider;
+
+ class ProjectRecord {
+ File projectSystemFile;
+
+ String projectName;
+
+ Object parent;
+
+ int level;
+
+ IProjectDescription description;
+
+ /**
+ * Create a record for a project based on the info in the file.
+ *
+ * @param file
+ */
+ ProjectRecord(File file) {
+ projectSystemFile = file;
+ setProjectName();
+ }
+
+ /**
+ * @param parent
+ * The parent folder of the .project file
+ * @param level
+ * The number of levels deep in the provider the file is
+ */
+ ProjectRecord(Object parent, int level) {
+ this.parent = parent;
+ this.level = level;
+ setProjectName();
+ }
+
+ /**
+ * Set the name of the project based on the projectFile.
+ */
+ private void setProjectName() {
+ try {
+ // If we don't have the project name try again
+ if (projectName == null) {
+ IPath path = new Path(projectSystemFile.getPath());
+ // if the file is in the default location, use the directory
+ // name as the project name
+ if (isDefaultLocation(path)) {
+ projectName = path.segment(path.segmentCount() - 2);
+ description = IDEWorkbenchPlugin.getPluginWorkspace()
+ .newProjectDescription(projectName);
+ } else {
+ description = IDEWorkbenchPlugin.getPluginWorkspace()
+ .loadProjectDescription(path);
+ projectName = description.getName();
+ }
+
+ }
+ } catch (CoreException e) {
+ // no good couldn't get the name
+ }
+ }
+
+ /**
+ * Returns whether the given project description file path is in the
+ * default location for a project
+ *
+ * @param path
+ * The path to examine
+ * @return Whether the given path is the default location for a project
+ */
+ private boolean isDefaultLocation(IPath path) {
+ // The project description file must at least be within the project,
+ // which is within the workspace location
+ if (path.segmentCount() < 2)
+ return false;
+ return path.removeLastSegments(2).toFile().equals(
+ Platform.getLocation().toFile());
+ }
+
+ /**
+ * Get the name of the project
+ *
+ * @return String
+ */
+ public String getProjectName() {
+ return projectName;
+ }
+
+ /**
+ * Gets the label to be used when rendering this project record in the
+ * UI.
+ *
+ * @return String the label
+ * @since 3.4
+ */
+ public String getProjectLabel() {
+ if (description == null)
+ return projectName;
+
+ String path = projectSystemFile == null ? structureProvider
+ .getLabel(parent) : projectSystemFile.getParent();
+
+ return NLS.bind(UIText.WizardProjectsImportPage_projectLabel,
+ projectName, path);
+ }
+ }
+
+ private CheckboxTreeViewer projectsList;
+
+ private ProjectRecord[] selectedProjects = new ProjectRecord[0];
+
+ private IProject[] wsProjects;
+
+ // The last selected path to minimize searches
+ private String lastPath;
+
+ // The last time that the file or folder at the selected path was modified
+ // to mimize searches
+ private long lastModified;
+
+ private Button shareCheckBox;
+
+ private boolean share;
+
+ /**
+ * Creates a new project creation wizard page.
+ */
+ public GitProjectsImportPage() {
+ this("gitWizardExternalProjectsPage"); //$NON-NLS-1$
+ }
+
+ /**
+ * Create a new instance of the receiver.
+ *
+ * @param pageName
+ */
+ public GitProjectsImportPage(String pageName) {
+ super(pageName);
+ setPageComplete(false);
+ setTitle(UIText.WizardProjectsImportPage_ImportProjectsTitle);
+ setDescription(UIText.WizardProjectsImportPage_ImportProjectsDescription);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets
+ * .Composite)
+ */
+ public void createControl(Composite parent) {
+
+ initializeDialogUnits(parent);
+
+ Composite workArea = new Composite(parent, SWT.NONE);
+ setControl(workArea);
+
+ workArea.setLayout(new GridLayout());
+ workArea.setLayoutData(new GridData(GridData.FILL_BOTH
+ | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL));
+
+ createProjectsRoot(workArea);
+ createProjectsList(workArea);
+ createOptionsArea(workArea);
+ Dialog.applyDialogFont(workArea);
+
+ }
+
+ /**
+ * Create the area with the extra options.
+ *
+ * @param workArea
+ */
+ private void createOptionsArea(Composite workArea) {
+ Composite optionsGroup = new Composite(workArea, SWT.NONE);
+ optionsGroup.setLayout(new GridLayout());
+ optionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ shareCheckBox = new Button(optionsGroup, SWT.CHECK);
+ shareCheckBox.setText(UIText.WizardProjectsImportPage_enableGit);
+ shareCheckBox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ shareCheckBox.setSelection(share = true);
+ shareCheckBox.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ share = shareCheckBox.getSelection();
+ }
+ });
+ }
+
+ /**
+ * Create the checkbox list for the found projects.
+ *
+ * @param workArea
+ */
+ private void createProjectsList(Composite workArea) {
+
+ Label title = new Label(workArea, SWT.NONE);
+ title.setText(UIText.WizardProjectsImportPage_ProjectsListTitle);
+
+ Composite listComposite = new Composite(workArea, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ layout.marginWidth = 0;
+ layout.makeColumnsEqualWidth = false;
+ listComposite.setLayout(layout);
+
+ listComposite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
+ | GridData.GRAB_VERTICAL | GridData.FILL_BOTH));
+
+ projectsList = new CheckboxTreeViewer(listComposite, SWT.BORDER);
+ GridData listData = new GridData(GridData.GRAB_HORIZONTAL
+ | GridData.GRAB_VERTICAL | GridData.FILL_BOTH);
+ projectsList.getControl().setLayoutData(listData);
+
+ projectsList.setContentProvider(new ITreeContentProvider() {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java
+ * .lang.Object)
+ */
+ public Object[] getChildren(Object parentElement) {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.IStructuredContentProvider#getElements
+ * (java.lang.Object)
+ */
+ public Object[] getElements(Object inputElement) {
+ return getValidProjects();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java
+ * .lang.Object)
+ */
+ public boolean hasChildren(Object element) {
+ return false;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.ITreeContentProvider#getParent(java
+ * .lang.Object)
+ */
+ public Object getParent(Object element) {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.viewers.IContentProvider#dispose()
+ */
+ public void dispose() {
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse
+ * .jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+ */
+ public void inputChanged(Viewer viewer, Object oldInput,
+ Object newInput) {
+ }
+
+ });
+
+ projectsList.setLabelProvider(new LabelProvider() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
+ */
+ public String getText(Object element) {
+ return ((ProjectRecord) element).getProjectLabel();
+ }
+ });
+
+ projectsList.addCheckStateListener(new ICheckStateListener() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.viewers.ICheckStateListener#checkStateChanged
+ * (org.eclipse.jface.viewers.CheckStateChangedEvent)
+ */
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ setPageComplete(projectsList.getCheckedElements().length > 0);
+ }
+ });
+
+ projectsList.setInput(this);
+ projectsList.setComparator(new ViewerComparator());
+ createSelectionButtons(listComposite);
+ }
+
+ /**
+ * Create the selection buttons in the listComposite.
+ *
+ * @param listComposite
+ */
+ private void createSelectionButtons(Composite listComposite) {
+ Composite buttonsComposite = new Composite(listComposite, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ buttonsComposite.setLayout(layout);
+
+ buttonsComposite.setLayoutData(new GridData(
+ GridData.VERTICAL_ALIGN_BEGINNING));
+
+ Button selectAll = new Button(buttonsComposite, SWT.PUSH);
+ selectAll.setText(UIText.WizardProjectsImportPage_selectAll);
+ selectAll.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ projectsList.setCheckedElements(selectedProjects);
+ setPageComplete(projectsList.getCheckedElements().length > 0);
+ }
+ });
+ Dialog.applyDialogFont(selectAll);
+ setButtonLayoutData(selectAll);
+
+ Button deselectAll = new Button(buttonsComposite, SWT.PUSH);
+ deselectAll.setText(UIText.WizardProjectsImportPage_deselectAll);
+ deselectAll.addSelectionListener(new SelectionAdapter() {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse
+ * .swt.events.SelectionEvent)
+ */
+ public void widgetSelected(SelectionEvent e) {
+
+ projectsList.setCheckedElements(new Object[0]);
+ setPageComplete(false);
+ }
+ });
+ Dialog.applyDialogFont(deselectAll);
+ setButtonLayoutData(deselectAll);
+
+ }
+
+ /**
+ * Create the area where you select the root directory for the projects.
+ *
+ * @param workArea
+ * Composite
+ */
+ private void createProjectsRoot(Composite workArea) {
+
+ // project specification group
+ Composite projectGroup = new Composite(workArea, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ layout.makeColumnsEqualWidth = false;
+ layout.marginWidth = 0;
+ projectGroup.setLayout(layout);
+ projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IDialogPage. Set the focus on path
+ * fields when page becomes visible.
+ */
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ }
+
+ /**
+ * Update the list of projects based on path.
+ *
+ * @param path
+ */
+ void setProjectsList(final String path) {
+ // on an empty path empty selectedProjects
+ if (path == null || path.length() == 0) {
+ setMessage(UIText.WizardProjectsImportPage_ImportProjectsDescription);
+ selectedProjects = new ProjectRecord[0];
+ projectsList.refresh(true);
+ projectsList.setCheckedElements(selectedProjects);
+ setPageComplete(projectsList.getCheckedElements().length > 0);
+ lastPath = path;
+ return;
+ }
+
+ final File directory = new File(path);
+ long modified = directory.lastModified();
+ if (path.equals(lastPath) && lastModified == modified) {
+ // since the file/folder was not modified and the path did not
+ // change, no refreshing is required
+ return;
+ }
+
+ lastPath = path;
+ lastModified = modified;
+
+ try {
+ getContainer().run(true, true, new IRunnableWithProgress() {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.jface.operation.IRunnableWithProgress#run(org
+ * .eclipse.core.runtime.IProgressMonitor)
+ */
+ public void run(IProgressMonitor monitor) {
+
+ monitor.beginTask(
+ UIText.WizardProjectsImportPage_SearchingMessage,
+ 100);
+ selectedProjects = new ProjectRecord[0];
+ Collection files = new ArrayList();
+ monitor.worked(10);
+ if (directory.isDirectory()) {
+
+ if (!collectProjectFilesFromDirectory(files, directory,
+ null, monitor)) {
+ return;
+ }
+ Iterator filesIterator = files.iterator();
+ selectedProjects = new ProjectRecord[files.size()];
+ int index = 0;
+ monitor.worked(50);
+ monitor
+ .subTask(UIText.WizardProjectsImportPage_ProcessingMessage);
+ while (filesIterator.hasNext()) {
+ File file = (File) filesIterator.next();
+ selectedProjects[index] = new ProjectRecord(file);
+ index++;
+ }
+ } else {
+ monitor.worked(60);
+ }
+ monitor.done();
+ }
+
+ });
+ } catch (InvocationTargetException e) {
+ IDEWorkbenchPlugin.log(e.getMessage(), e);
+ } catch (InterruptedException e) {
+ // Nothing to do if the user interrupts.
+ }
+
+ projectsList.refresh(true);
+ projectsList.setCheckedElements(getValidProjects());
+ if (getValidProjects().length < selectedProjects.length) {
+ setMessage(UIText.WizardProjectsImportPage_projectsInWorkspace,
+ WARNING);
+ } else {
+ setMessage(UIText.WizardProjectsImportPage_ImportProjectsDescription);
+ }
+ setPageComplete(projectsList.getCheckedElements().length > 0);
+ }
+
+ /**
+ * Collect the list of .project files that are under directory into files.
+ *
+ * @param files
+ * @param directory
+ * @param directoriesVisited
+ * Set of canonical paths of directories, used as recursion guard
+ * @param monitor
+ * The monitor to report to
+ * @return boolean <code>true</code> if the operation was completed.
+ */
+ private boolean collectProjectFilesFromDirectory(Collection files,
+ File directory, Set directoriesVisited, IProgressMonitor monitor) {
+
+ if (monitor.isCanceled()) {
+ return false;
+ }
+ monitor.subTask(NLS.bind(
+ UIText.WizardProjectsImportPage_CheckingMessage, directory
+ .getPath()));
+ File[] contents = directory.listFiles();
+ if (contents == null)
+ return false;
+
+ // Initialize recursion guard for recursive symbolic links
+ if (directoriesVisited == null) {
+ directoriesVisited = new HashSet();
+ try {
+ directoriesVisited.add(directory.getCanonicalPath());
+ } catch (IOException exception) {
+ StatusManager.getManager().handle(
+ StatusUtil.newStatus(IStatus.ERROR, exception
+ .getLocalizedMessage(), exception));
+ }
+ }
+
+ // first look for project description files
+ final String dotProject = IProjectDescription.DESCRIPTION_FILE_NAME;
+ for (int i = 0; i < contents.length; i++) {
+ File file = contents[i];
+ if (file.isFile() && file.getName().equals(dotProject)) {
+ files.add(file);
+ // don't search sub-directories since we can't have nested
+ // projects
+ return true;
+ }
+ }
+ // no project description found, so recurse into sub-directories
+ for (int i = 0; i < contents.length; i++) {
+ if (contents[i].isDirectory()) {
+ if (!contents[i].getName().equals(METADATA_FOLDER)) {
+ try {
+ String canonicalPath = contents[i].getCanonicalPath();
+ if (!directoriesVisited.add(canonicalPath)) {
+ // already been here --> do not recurse
+ continue;
+ }
+ } catch (IOException exception) {
+ StatusManager.getManager().handle(
+ StatusUtil.newStatus(IStatus.ERROR, exception
+ .getLocalizedMessage(), exception));
+
+ }
+ collectProjectFilesFromDirectory(files, contents[i],
+ directoriesVisited, monitor);
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Create the selected projects
+ *
+ * @return boolean <code>true</code> if all project creations were
+ * successful.
+ */
+ boolean createProjects() {
+ final Object[] selected = projectsList.getCheckedElements();
+ WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
+ protected void execute(IProgressMonitor monitor)
+ throws InvocationTargetException, InterruptedException {
+ try {
+ monitor.beginTask("", selected.length); //$NON-NLS-1$
+ if (monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ for (int i = 0; i < selected.length; i++) {
+ createExistingProject((ProjectRecord) selected[i],
+ new SubProgressMonitor(monitor, 1));
+ }
+ } finally {
+ monitor.done();
+ }
+ }
+ };
+ // run the new project creation operation
+ try {
+ getContainer().run(true, true, op);
+ } catch (InterruptedException e) {
+ return false;
+ } catch (InvocationTargetException e) {
+ // one of the steps resulted in a core exception
+ Throwable t = e.getTargetException();
+ String message = UIText.WizardProjectImportPage_errorMessage;
+ IStatus status;
+ if (t instanceof CoreException) {
+ status = ((CoreException) t).getStatus();
+ } else {
+ status = new Status(IStatus.ERROR,
+ IDEWorkbenchPlugin.IDE_WORKBENCH, 1, message, t);
+ }
+ Activator.logError(message, t);
+ ErrorDialog.openError(getShell(), message, null, status);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Create the project described in record. If it is successful return true.
+ *
+ * @param record
+ * @param monitor
+ * @return boolean <code>true</code> if successful
+ * @throws InvocationTargetException
+ * @throws InterruptedException
+ */
+ private boolean createExistingProject(final ProjectRecord record,
+ IProgressMonitor monitor) throws InvocationTargetException,
+ InterruptedException {
+ String projectName = record.getProjectName();
+ final IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ final IProject project = workspace.getRoot().getProject(projectName);
+ if (record.description == null) {
+ // error case
+ record.description = workspace.newProjectDescription(projectName);
+ IPath locationPath = new Path(record.projectSystemFile
+ .getAbsolutePath());
+
+ // If it is under the root use the default location
+ if (Platform.getLocation().isPrefixOf(locationPath)) {
+ record.description.setLocation(null);
+ } else {
+ record.description.setLocation(locationPath);
+ }
+ } else {
+ record.description.setName(projectName);
+ }
+
+ try {
+ monitor.beginTask(
+ UIText.WizardProjectsImportPage_CreateProjectsTask, 100);
+ project.create(record.description, new SubProgressMonitor(monitor,
+ 30));
+ int openTicks = share ? 50 : 70;
+ project.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(
+ monitor, openTicks));
+ if (share) {
+ ConnectProviderOperation connectProviderOperation = new ConnectProviderOperation(
+ project, null);
+ connectProviderOperation
+ .run(new SubProgressMonitor(monitor, 20));
+ }
+ } catch (CoreException e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+
+ return true;
+ }
+
+ /**
+ * Method used for test suite.
+ *
+ * @return CheckboxTreeViewer the viewer containing all the projects found
+ */
+ public CheckboxTreeViewer getProjectsList() {
+ return projectsList;
+ }
+
+ /**
+ * Retrieve all the projects in the current workspace.
+ *
+ * @return IProject[] array of IProject in the current workspace
+ */
+ private IProject[] getProjectsInWorkspace() {
+ if (wsProjects == null) {
+ wsProjects = IDEWorkbenchPlugin.getPluginWorkspace().getRoot()
+ .getProjects();
+ }
+ return wsProjects;
+ }
+
+ /**
+ * Get the array of valid project records that can be imported from the
+ * source workspace or archive, selected by the user. If a project with the
+ * same name exists in both the source workspace and the current workspace,
+ * it will not appear in the list of projects to import and thus cannot be
+ * selected for import.
+ *
+ * Method declared public for test suite.
+ *
+ * @return ProjectRecord[] array of projects that can be imported into the
+ * workspace
+ */
+ public ProjectRecord[] getValidProjects() {
+ List validProjects = new ArrayList();
+ for (int i = 0; i < selectedProjects.length; i++) {
+ if (!isProjectInWorkspace(selectedProjects[i].getProjectName())) {
+ validProjects.add(selectedProjects[i]);
+ }
+ }
+ return (ProjectRecord[]) validProjects
+ .toArray(new ProjectRecord[validProjects.size()]);
+ }
+
+ /**
+ * Determine if the project with the given name is in the current workspace.
+ *
+ * @param projectName
+ * String the project name to check
+ * @return boolean true if the project with the given name is in this
+ * workspace
+ */
+ private boolean isProjectInWorkspace(String projectName) {
+ if (projectName == null) {
+ return false;
+ }
+ IProject[] workspaceProjects = getProjectsInWorkspace();
+ for (int i = 0; i < workspaceProjects.length; i++) {
+ if (projectName.equals(workspaceProjects[i].getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --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
index 86cf6ec..4f02c95 100644
--- 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2007, 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
* Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
* Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
@@ -660,4 +660,11 @@ private void updateAuthGroup() {
break;
}
}
+
+ @Override
+ public void setVisible(boolean visible) {
+ super.setVisible(visible);
+ if (visible)
+ uriText.setFocus();
+ }
}
diff --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
index 22e29c2..98ce80f 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties
@@ -15,6 +15,21 @@
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
##
+WizardProjectsImportPage_projectLabel={0} ({1})
+WizardProjectsImportPage_ImportProjectsTitle=Import Projects
+WizardProjectsImportPage_ImportProjectsDescription=Import projects from cloned repository into workbench
+WizardProjectsImportPage_ProjectsListTitle=&Projects
+WizardProjectsImportPage_selectAll = &Select All
+WizardProjectsImportPage_deselectAll = &Deselect All
+WizardProjectsImportPage_SearchingMessage = Searching for projects
+WizardProjectsImportPage_ProcessingMessage = Processing results
+WizardProjectsImportPage_projectsInWorkspace = Some projects were hidden because they exist in the workspace directory
+WizardProjectsImportPage_CheckingMessage = Checking: {0}
+WizardProjectsImportPage_SelectDialogTitle = Select root directory of the projects to import
+WizardProjectImportPage_errorMessage = Creation Problems
+WizardProjectsImportPage_CreateProjectsTask = Creating Projects
+WizardProjectsImportPage_enableGit = Enable Git Team operations on imported projects
+
SharingWizard_windowTitle=Configure Git Repository
SharingWizard_failed=Failed to initialize Git team provider.
--
1.6.1.rc3.56.gd0306
prev parent reply other threads:[~2009-01-02 6:20 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-12-31 10:56 [EGIT PATCH] Add an import wizard for Eclipse projects as part of clone Robin Rosenberg
2008-12-31 15:54 ` Shawn O. Pearce
2009-01-02 6:18 ` Robin Rosenberg [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1230877098-9913-1-git-send-email-robin.rosenberg@dewire.com \
--to=robin.rosenberg@dewire.com \
--cc=git@vger.kernel.org \
--cc=spearce@spearce.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).