Enable import of empty Git repositories
[egit.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / internal / clone / GitCloneWizard.java
blob4b15c40d7ee863848fcfaad022eeaa104809282f
1 /*******************************************************************************
2 * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
3 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
4 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
5 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
7 * All rights reserved. This program and the accompanying materials
8 * are made available under the terms of the Eclipse Public License v1.0
9 * which accompanies this distribution, and is available at
10 * http://www.eclipse.org/legal/epl-v10.html
11 *******************************************************************************/
12 package org.eclipse.egit.ui.internal.clone;
14 import java.io.File;
15 import java.lang.reflect.InvocationTargetException;
16 import java.util.Collection;
17 import java.util.Collections;
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.core.runtime.IStatus;
21 import org.eclipse.core.runtime.Status;
22 import org.eclipse.core.runtime.jobs.Job;
23 import org.eclipse.egit.core.op.CloneOperation;
24 import org.eclipse.egit.ui.Activator;
25 import org.eclipse.egit.ui.UIIcons;
26 import org.eclipse.egit.ui.UIText;
27 import org.eclipse.egit.ui.internal.components.RepositorySelectionPage;
28 import org.eclipse.egit.ui.internal.repository.RepositoriesView;
29 import org.eclipse.jface.dialogs.ErrorDialog;
30 import org.eclipse.jface.dialogs.MessageDialog;
31 import org.eclipse.jface.operation.IRunnableWithProgress;
32 import org.eclipse.jface.viewers.IStructuredSelection;
33 import org.eclipse.jface.wizard.Wizard;
34 import org.eclipse.jgit.lib.Ref;
35 import org.eclipse.jgit.transport.URIish;
36 import org.eclipse.osgi.util.NLS;
37 import org.eclipse.ui.IImportWizard;
38 import org.eclipse.ui.IViewPart;
39 import org.eclipse.ui.IWorkbench;
40 import org.eclipse.ui.PlatformUI;
42 /**
43 * Import Git Repository Wizard. A front end to a git clone operation.
45 public class GitCloneWizard extends Wizard implements IImportWizard {
46 private RepositorySelectionPage cloneSource;
48 private SourceBranchPage validSource;
50 private CloneDestinationPage cloneDestination;
52 private GitProjectsImportPage importProject;
54 public void init(IWorkbench arg0, IStructuredSelection arg1) {
55 setWindowTitle(UIText.GitCloneWizard_title);
56 setDefaultPageImageDescriptor(UIIcons.WIZBAN_IMPORT_REPO);
57 setNeedsProgressMonitor(true);
58 cloneSource = new RepositorySelectionPage(true, null);
59 validSource = new SourceBranchPage(cloneSource);
60 cloneDestination = new CloneDestinationPage(cloneSource, validSource);
61 importProject = new GitProjectsImportPage() {
62 @Override
63 public void setVisible(boolean visible) {
64 if (visible) {
65 if (cloneDestination.alreadyClonedInto == null) {
66 if (performClone(false))
67 cloneDestination.alreadyClonedInto = cloneDestination
68 .getDestinationFile().getAbsolutePath();
70 setProjectsList(cloneDestination.alreadyClonedInto);
72 super.setVisible(visible);
77 @Override
78 public boolean performCancel() {
79 if (cloneDestination.alreadyClonedInto != null) {
80 if (MessageDialog
81 .openQuestion(getShell(), UIText.GitCloneWizard_abortingCloneTitle,
82 UIText.GitCloneWizard_abortingCloneMsg)) {
83 deleteRecursively(new File(cloneDestination.alreadyClonedInto));
86 return true;
89 private void deleteRecursively(File f) {
90 for (File i : f.listFiles()) {
91 if (i.isDirectory()) {
92 deleteRecursively(i);
93 } else {
94 if (!i.delete()) {
95 i.deleteOnExit();
99 if (!f.delete())
100 f.deleteOnExit();
103 @Override
104 public void addPages() {
105 addPage(cloneSource);
106 addPage(validSource);
107 addPage(cloneDestination);
108 addPage(importProject);
111 @Override
112 public boolean canFinish() {
113 return cloneDestination.isPageComplete()
114 && !cloneDestination.showImportWizard.getSelection()
115 || importProject.isPageComplete();
118 @Override
119 public boolean performFinish() {
120 if (!cloneDestination.showImportWizard.getSelection())
121 return performClone(true);
122 return importProject.createProjects();
125 boolean performClone(boolean background) {
126 final URIish uri = cloneSource.getSelection().getURI();
127 final boolean allSelected;
128 final Collection<Ref> selectedBranches;
129 if (validSource.isSourceRepoEmpty()) {
130 // fetch all branches of empty repo
131 allSelected = true;
132 selectedBranches = Collections.emptyList();
133 } else {
134 allSelected = validSource.isAllSelected();
135 selectedBranches = validSource.getSelectedBranches();
137 final File workdir = cloneDestination.getDestinationFile();
138 final String branch = cloneDestination.getInitialBranch();
139 final String remoteName = cloneDestination.getRemote();
141 workdir.mkdirs();
142 if (!workdir.isDirectory()) {
143 final String errorMessage = NLS.bind(
144 UIText.GitCloneWizard_errorCannotCreate, workdir.getPath());
145 ErrorDialog.openError(getShell(), getWindowTitle(),
146 UIText.GitCloneWizard_failed, new Status(IStatus.ERROR,
147 Activator.getPluginId(), 0, errorMessage, null));
148 // let's give user a chance to fix this minor problem
149 return false;
152 final RepositoriesView view;
153 IViewPart vp = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
154 .getActivePage().findView(RepositoriesView.VIEW_ID);
155 if (vp != null) {
156 view = (RepositoriesView) vp;
157 } else {
158 view = null;
161 final CloneOperation op = new CloneOperation(uri, allSelected,
162 selectedBranches, workdir, branch, remoteName);
163 importProject.setGitDir(op.getGitDir());
164 if (background) {
165 final Job job = new Job(NLS.bind(UIText.GitCloneWizard_jobName, uri
166 .toString())) {
167 @Override
168 protected IStatus run(final IProgressMonitor monitor) {
169 try {
170 op.run(monitor);
171 RepositorySelectionPage.saveUriInPrefs(uri.toString());
172 RepositoriesView.addDir(op.getGitDir());
173 if (view != null)
174 view.scheduleRefresh();
176 return Status.OK_STATUS;
177 } catch (InterruptedException e) {
178 return Status.CANCEL_STATUS;
179 } catch (InvocationTargetException e) {
180 Throwable thr = e.getCause();
181 return new Status(IStatus.ERROR, Activator
182 .getPluginId(), 0, thr.getMessage(), thr);
187 job.setUser(true);
188 job.schedule();
189 return true;
190 } else {
191 try {
192 // Perform clone in ModalContext thread with progress
193 // reporting on the wizard.
194 getContainer().run(true, true, new IRunnableWithProgress() {
195 public void run(IProgressMonitor monitor)
196 throws InvocationTargetException,
197 InterruptedException {
198 op.run(monitor);
201 RepositorySelectionPage.saveUriInPrefs(uri.toString());
202 RepositoriesView.addDir(op.getGitDir());
203 if (view != null)
204 view.scheduleRefresh();
205 return true;
206 } catch (InterruptedException e) {
207 MessageDialog.openInformation(getShell(),
208 UIText.GitCloneWizard_CloneFailedHeading,
209 UIText.GitCloneWizard_CloneCanceledMessage);
210 return false;
211 } catch (Exception e) {
212 Activator.handleError(UIText.GitCloneWizard_CloneFailedHeading,
213 e, true);
214 return false;