Remove trailing whitespace across EGit
[egit.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / internal / clone / CloneDestinationPage.java
blob71572f38f154cefc06b1d63ff3c755ee438b95b2
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.util.List;
17 import org.eclipse.core.resources.ResourcesPlugin;
18 import org.eclipse.egit.ui.UIText;
19 import org.eclipse.egit.ui.internal.components.RepositorySelection;
20 import org.eclipse.egit.ui.internal.components.RepositorySelectionPage;
21 import org.eclipse.egit.ui.internal.components.SelectionChangeListener;
22 import org.eclipse.jface.wizard.WizardPage;
23 import org.eclipse.osgi.util.NLS;
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.events.ModifyEvent;
26 import org.eclipse.swt.events.ModifyListener;
27 import org.eclipse.swt.events.SelectionAdapter;
28 import org.eclipse.swt.events.SelectionEvent;
29 import org.eclipse.swt.layout.GridData;
30 import org.eclipse.swt.layout.GridLayout;
31 import org.eclipse.swt.widgets.Button;
32 import org.eclipse.swt.widgets.Combo;
33 import org.eclipse.swt.widgets.Composite;
34 import org.eclipse.swt.widgets.FileDialog;
35 import org.eclipse.swt.widgets.Group;
36 import org.eclipse.swt.widgets.Label;
37 import org.eclipse.swt.widgets.Text;
38 import org.eclipse.jgit.lib.Constants;
39 import org.eclipse.jgit.lib.Ref;
41 /**
42 * Wizard page that allows the user entering the location of a repository to be
43 * cloned.
45 class CloneDestinationPage extends WizardPage {
46 private final RepositorySelectionPage sourcePage;
48 private final SourceBranchPage branchPage;
50 private RepositorySelection validatedRepoSelection;
52 private List<Ref> validatedSelectedBranches;
54 private Ref validatedHEAD;
56 private Combo initialBranch;
58 private Text directoryText;
60 private Text remoteText;
62 Button showImportWizard;
64 String alreadyClonedInto;
66 CloneDestinationPage(final RepositorySelectionPage sp,
67 final SourceBranchPage bp) {
68 super(CloneDestinationPage.class.getName());
69 sourcePage = sp;
70 branchPage = bp;
71 setTitle(UIText.CloneDestinationPage_title);
73 final SelectionChangeListener listener = new SelectionChangeListener() {
74 public void selectionChanged() {
75 checkPreviousPagesSelections();
78 sourcePage.addSelectionListener(listener);
79 branchPage.addSelectionListener(listener);
82 public void createControl(final Composite parent) {
83 final Composite panel = new Composite(parent, SWT.NULL);
84 final GridLayout layout = new GridLayout();
85 layout.numColumns = 1;
86 panel.setLayout(layout);
88 createDestinationGroup(panel);
89 createConfigGroup(panel);
90 createWorkbenchGroup(panel);
91 setControl(panel);
92 checkPage();
95 @Override
96 public void setVisible(final boolean visible) {
97 if (visible)
98 revalidate();
99 super.setVisible(visible);
100 if (visible)
101 directoryText.setFocus();
104 private void checkPreviousPagesSelections() {
105 if (!sourcePage.selectionEquals(validatedRepoSelection)
106 || !branchPage.selectionEquals(validatedSelectedBranches,
107 validatedHEAD))
108 setPageComplete(false);
109 else
110 checkPage();
113 private void createDestinationGroup(final Composite parent) {
114 final Group g = createGroup(parent,
115 UIText.CloneDestinationPage_groupDestination);
117 newLabel(g, UIText.CloneDestinationPage_promptDirectory + ":"); //$NON-NLS-1$
118 final Composite p = new Composite(g, SWT.NONE);
119 final GridLayout grid = new GridLayout();
120 grid.numColumns = 2;
121 p.setLayout(grid);
122 p.setLayoutData(createFieldGridData());
123 directoryText = new Text(p, SWT.BORDER);
124 directoryText.setLayoutData(createFieldGridData());
125 directoryText.addModifyListener(new ModifyListener() {
126 public void modifyText(final ModifyEvent e) {
127 checkPage();
130 final Button b = new Button(p, SWT.PUSH);
131 b.setText(UIText.CloneDestinationPage_browseButton);
132 b.addSelectionListener(new SelectionAdapter() {
133 public void widgetSelected(final SelectionEvent e) {
134 final FileDialog d;
136 d = new FileDialog(getShell(), SWT.APPLICATION_MODAL | SWT.SAVE);
137 if (directoryText.getText().length() > 0) {
138 final File file = new File(directoryText.getText())
139 .getAbsoluteFile();
140 d.setFilterPath(file.getParent());
141 d.setFileName(file.getName());
143 final String r = d.open();
144 if (r != null)
145 directoryText.setText(r);
149 newLabel(g, UIText.CloneDestinationPage_promptInitialBranch + ":"); //$NON-NLS-1$
150 initialBranch = new Combo(g, SWT.DROP_DOWN | SWT.READ_ONLY);
151 initialBranch.setLayoutData(createFieldGridData());
152 initialBranch.addSelectionListener(new SelectionAdapter() {
153 @Override
154 public void widgetSelected(final SelectionEvent e) {
155 checkPage();
160 private void createConfigGroup(final Composite parent) {
161 final Group g = createGroup(parent,
162 UIText.CloneDestinationPage_groupConfiguration);
164 newLabel(g, UIText.CloneDestinationPage_promptRemoteName + ":"); //$NON-NLS-1$
165 remoteText = new Text(g, SWT.BORDER);
166 remoteText.setText("origin"); //$NON-NLS-1$
167 remoteText.setLayoutData(createFieldGridData());
168 remoteText.addModifyListener(new ModifyListener() {
169 public void modifyText(ModifyEvent e) {
170 checkPage();
175 private void createWorkbenchGroup(Composite parent) {
176 final Group g = createGroup(parent, UIText.CloneDestinationPage_workspaceImport);
177 showImportWizard = new Button(g, SWT.CHECK);
178 showImportWizard.setSelection(true);
179 showImportWizard.setText(UIText.CloneDestinationPage_importProjectsAfterClone);
180 showImportWizard.setLayoutData(createFieldGridData());
181 showImportWizard.addSelectionListener(new SelectionAdapter() {
182 @Override
183 public void widgetSelected(SelectionEvent e) {
184 checkPage();
189 private static Group createGroup(final Composite parent, final String text) {
190 final Group g = new Group(parent, SWT.NONE);
191 final GridLayout layout = new GridLayout();
192 layout.numColumns = 2;
193 g.setLayout(layout);
194 g.setText(text);
195 final GridData gd = new GridData();
196 gd.grabExcessHorizontalSpace = true;
197 gd.horizontalAlignment = SWT.FILL;
198 g.setLayoutData(gd);
199 return g;
202 private static void newLabel(final Group g, final String text) {
203 new Label(g, SWT.NULL).setText(text);
206 private static GridData createFieldGridData() {
207 return new GridData(SWT.FILL, SWT.DEFAULT, true, false);
211 * @return location the user wants to store this repository.
213 public File getDestinationFile() {
214 return new File(directoryText.getText());
218 * @return initial branch selected (includes refs/heads prefix).
220 public String getInitialBranch() {
221 final int ix = initialBranch.getSelectionIndex();
222 if (ix < 0)
223 return Constants.R_HEADS + Constants.MASTER;
224 return Constants.R_HEADS + initialBranch.getItem(ix);
228 * @return remote name
230 public String getRemote() {
231 return remoteText.getText();
235 * Check internal state for page completion status.
237 private void checkPage() {
238 final String dstpath = directoryText.getText();
239 if (dstpath.length() == 0) {
240 setErrorMessage(NLS.bind(UIText.CloneDestinationPage_fieldRequired,
241 UIText.CloneDestinationPage_promptDirectory));
242 setPageComplete(false);
243 return;
245 final File absoluteFile = new File(dstpath).getAbsoluteFile();
246 if (!absoluteFile.getAbsolutePath().equals(alreadyClonedInto)
247 && !isEmptyDir(absoluteFile)) {
248 setErrorMessage(NLS.bind(
249 UIText.CloneDestinationPage_errorNotEmptyDir, absoluteFile
250 .getPath()));
251 setPageComplete(false);
252 return;
255 if (!canCreateSubdir(absoluteFile.getParentFile())) {
256 setErrorMessage(NLS.bind(UIText.GitCloneWizard_errorCannotCreate,
257 absoluteFile.getPath()));
258 setPageComplete(false);
259 return;
261 if (initialBranch.getSelectionIndex() < 0) {
262 setErrorMessage(NLS.bind(UIText.CloneDestinationPage_fieldRequired,
263 UIText.CloneDestinationPage_promptInitialBranch));
264 setPageComplete(false);
265 return;
267 if (remoteText.getText().length() == 0) {
268 setErrorMessage(NLS.bind(UIText.CloneDestinationPage_fieldRequired,
269 UIText.CloneDestinationPage_promptRemoteName));
270 setPageComplete(false);
271 return;
274 setErrorMessage(null);
275 setPageComplete(true);
278 private static boolean isEmptyDir(final File dir) {
279 if (!dir.exists())
280 return true;
281 if (!dir.isDirectory())
282 return false;
283 return dir.listFiles().length == 0;
286 // this is actually just an optimistic heuristic - should be named
287 // isThereHopeThatCanCreateSubdir() as probably there is no 100% reliable
288 // way to check that in Java for Windows
289 private static boolean canCreateSubdir(final File parent) {
290 if (parent == null)
291 return true;
292 if (parent.exists())
293 return parent.isDirectory() && parent.canWrite();
294 return canCreateSubdir(parent.getParentFile());
297 private void revalidate() {
298 if (sourcePage.selectionEquals(validatedRepoSelection)
299 && branchPage.selectionEquals(validatedSelectedBranches,
300 validatedHEAD)) {
301 checkPage();
302 return;
305 if (!sourcePage.selectionEquals(validatedRepoSelection)) {
306 validatedRepoSelection = sourcePage.getSelection();
307 // update repo-related selection only if it changed
308 final String n = getSuggestedName();
309 setDescription(NLS.bind(UIText.CloneDestinationPage_description, n));
310 directoryText.setText(new File(ResourcesPlugin.getWorkspace()
311 .getRoot().getRawLocation().toFile(), n).getAbsolutePath());
314 validatedSelectedBranches = branchPage.getSelectedBranches();
315 validatedHEAD = branchPage.getHEAD();
317 initialBranch.removeAll();
318 final Ref head = branchPage.getHEAD();
319 int newix = 0;
320 for (final Ref r : branchPage.getSelectedBranches()) {
321 String name = r.getName();
322 if (name.startsWith(Constants.R_HEADS))
323 name = name.substring((Constants.R_HEADS).length());
324 if (head != null && head.getName().equals(r.getName()))
325 newix = initialBranch.getItemCount();
326 initialBranch.add(name);
328 initialBranch.select(newix);
329 checkPage();
332 private String getSuggestedName() {
333 String path = validatedRepoSelection.getURI().getPath();
334 int s = path.lastIndexOf('/');
335 if (s != -1)
336 path = path.substring(s + 1);
337 if (path.endsWith(".git")) //$NON-NLS-1$
338 path = path.substring(0, path.length() - 4);
339 return path;
342 @Override
343 public boolean canFlipToNextPage() {
344 return super.canFlipToNextPage() && showImportWizard.getSelection();