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
;
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
;
42 * Wizard page that allows the user entering the location of a repository to be
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());
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
);
96 public void setVisible(final boolean visible
) {
99 super.setVisible(visible
);
101 directoryText
.setFocus();
104 private void checkPreviousPagesSelections() {
105 if (!sourcePage
.selectionEquals(validatedRepoSelection
)
106 || !branchPage
.selectionEquals(validatedSelectedBranches
,
108 setPageComplete(false);
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();
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
) {
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
) {
136 d
= new FileDialog(getShell(), SWT
.APPLICATION_MODAL
| SWT
.SAVE
);
137 if (directoryText
.getText().length() > 0) {
138 final File file
= new File(directoryText
.getText())
140 d
.setFilterPath(file
.getParent());
141 d
.setFileName(file
.getName());
143 final String r
= d
.open();
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() {
154 public void widgetSelected(final SelectionEvent e
) {
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
) {
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() {
183 public void widgetSelected(SelectionEvent e
) {
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;
195 final GridData gd
= new GridData();
196 gd
.grabExcessHorizontalSpace
= true;
197 gd
.horizontalAlignment
= SWT
.FILL
;
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();
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);
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
251 setPageComplete(false);
255 if (!canCreateSubdir(absoluteFile
.getParentFile())) {
256 setErrorMessage(NLS
.bind(UIText
.GitCloneWizard_errorCannotCreate
,
257 absoluteFile
.getPath()));
258 setPageComplete(false);
261 if (initialBranch
.getSelectionIndex() < 0) {
262 setErrorMessage(NLS
.bind(UIText
.CloneDestinationPage_fieldRequired
,
263 UIText
.CloneDestinationPage_promptInitialBranch
));
264 setPageComplete(false);
267 if (remoteText
.getText().length() == 0) {
268 setErrorMessage(NLS
.bind(UIText
.CloneDestinationPage_fieldRequired
,
269 UIText
.CloneDestinationPage_promptRemoteName
));
270 setPageComplete(false);
274 setErrorMessage(null);
275 setPageComplete(true);
278 private static boolean isEmptyDir(final File dir
) {
281 if (!dir
.isDirectory())
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
) {
293 return parent
.isDirectory() && parent
.canWrite();
294 return canCreateSubdir(parent
.getParentFile());
297 private void revalidate() {
298 if (sourcePage
.selectionEquals(validatedRepoSelection
)
299 && branchPage
.selectionEquals(validatedSelectedBranches
,
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();
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
);
332 private String
getSuggestedName() {
333 String path
= validatedRepoSelection
.getURI().getPath();
334 int s
= path
.lastIndexOf('/');
336 path
= path
.substring(s
+ 1);
337 if (path
.endsWith(".git")) //$NON-NLS-1$
338 path
= path
.substring(0, path
.length() - 4);
343 public boolean canFlipToNextPage() {
344 return super.canFlipToNextPage() && showImportWizard
.getSelection();