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
.dialogs
.Dialog
;
23 import org
.eclipse
.jface
.wizard
.WizardPage
;
24 import org
.eclipse
.jgit
.lib
.Constants
;
25 import org
.eclipse
.jgit
.lib
.Ref
;
26 import org
.eclipse
.osgi
.util
.NLS
;
27 import org
.eclipse
.swt
.SWT
;
28 import org
.eclipse
.swt
.events
.ModifyEvent
;
29 import org
.eclipse
.swt
.events
.ModifyListener
;
30 import org
.eclipse
.swt
.events
.SelectionAdapter
;
31 import org
.eclipse
.swt
.events
.SelectionEvent
;
32 import org
.eclipse
.swt
.layout
.GridData
;
33 import org
.eclipse
.swt
.layout
.GridLayout
;
34 import org
.eclipse
.swt
.widgets
.Button
;
35 import org
.eclipse
.swt
.widgets
.Combo
;
36 import org
.eclipse
.swt
.widgets
.Composite
;
37 import org
.eclipse
.swt
.widgets
.FileDialog
;
38 import org
.eclipse
.swt
.widgets
.Group
;
39 import org
.eclipse
.swt
.widgets
.Label
;
40 import org
.eclipse
.swt
.widgets
.Text
;
43 * Wizard page that allows the user entering the location of a repository to be
46 class CloneDestinationPage
extends WizardPage
{
47 private final RepositorySelectionPage sourcePage
;
49 private final SourceBranchPage branchPage
;
51 private RepositorySelection validatedRepoSelection
;
53 private List
<Ref
> validatedSelectedBranches
;
55 private Ref validatedHEAD
;
57 private Combo initialBranch
;
59 private Text directoryText
;
61 private Text remoteText
;
63 CloneDestinationPage(final RepositorySelectionPage sp
,
64 final SourceBranchPage bp
) {
65 super(CloneDestinationPage
.class.getName());
68 setTitle(UIText
.CloneDestinationPage_title
);
70 final SelectionChangeListener listener
= new SelectionChangeListener() {
71 public void selectionChanged() {
72 checkPreviousPagesSelections();
75 sourcePage
.addSelectionListener(listener
);
76 branchPage
.addSelectionListener(listener
);
79 public void createControl(final Composite parent
) {
80 final Composite panel
= new Composite(parent
, SWT
.NULL
);
81 final GridLayout layout
= new GridLayout();
82 layout
.numColumns
= 1;
83 panel
.setLayout(layout
);
85 createDestinationGroup(panel
);
86 createConfigGroup(panel
);
87 Dialog
.applyDialogFont(panel
);
93 public void setVisible(final boolean visible
) {
95 if (branchPage
.isSourceRepoEmpty()) {
96 initialBranch
.setEnabled(false);
100 super.setVisible(visible
);
102 directoryText
.setFocus();
105 private void checkPreviousPagesSelections() {
106 if (!sourcePage
.selectionEquals(validatedRepoSelection
)
107 || !branchPage
.selectionEquals(validatedSelectedBranches
,
109 setPageComplete(false);
114 private void createDestinationGroup(final Composite parent
) {
115 final Group g
= createGroup(parent
,
116 UIText
.CloneDestinationPage_groupDestination
);
118 newLabel(g
, UIText
.CloneDestinationPage_promptDirectory
+ ":"); //$NON-NLS-1$
119 final Composite p
= new Composite(g
, SWT
.NONE
);
120 final GridLayout grid
= new GridLayout();
123 p
.setLayoutData(createFieldGridData());
124 directoryText
= new Text(p
, SWT
.BORDER
);
125 directoryText
.setLayoutData(createFieldGridData());
126 directoryText
.addModifyListener(new ModifyListener() {
127 public void modifyText(final ModifyEvent e
) {
131 final Button b
= new Button(p
, SWT
.PUSH
);
132 b
.setText(UIText
.CloneDestinationPage_browseButton
);
133 b
.addSelectionListener(new SelectionAdapter() {
134 public void widgetSelected(final SelectionEvent e
) {
137 d
= new FileDialog(getShell(), SWT
.APPLICATION_MODAL
| SWT
.SAVE
);
138 if (directoryText
.getText().length() > 0) {
139 final File file
= new File(directoryText
.getText())
141 d
.setFilterPath(file
.getParent());
142 d
.setFileName(file
.getName());
144 final String r
= d
.open();
146 directoryText
.setText(r
);
150 newLabel(g
, UIText
.CloneDestinationPage_promptInitialBranch
+ ":"); //$NON-NLS-1$
151 initialBranch
= new Combo(g
, SWT
.DROP_DOWN
| SWT
.READ_ONLY
);
152 initialBranch
.setLayoutData(createFieldGridData());
153 initialBranch
.addSelectionListener(new SelectionAdapter() {
155 public void widgetSelected(final SelectionEvent e
) {
161 private void createConfigGroup(final Composite parent
) {
162 final Group g
= createGroup(parent
,
163 UIText
.CloneDestinationPage_groupConfiguration
);
165 newLabel(g
, UIText
.CloneDestinationPage_promptRemoteName
+ ":"); //$NON-NLS-1$
166 remoteText
= new Text(g
, SWT
.BORDER
);
167 remoteText
.setText(Constants
.DEFAULT_REMOTE_NAME
);
168 remoteText
.setLayoutData(createFieldGridData());
169 remoteText
.addModifyListener(new ModifyListener() {
170 public void modifyText(ModifyEvent e
) {
176 private static Group
createGroup(final Composite parent
, final String text
) {
177 final Group g
= new Group(parent
, SWT
.NONE
);
178 final GridLayout layout
= new GridLayout();
179 layout
.numColumns
= 2;
182 final GridData gd
= new GridData();
183 gd
.grabExcessHorizontalSpace
= true;
184 gd
.horizontalAlignment
= SWT
.FILL
;
189 private static void newLabel(final Group g
, final String text
) {
190 new Label(g
, SWT
.NULL
).setText(text
);
193 private static GridData
createFieldGridData() {
194 return new GridData(SWT
.FILL
, SWT
.DEFAULT
, true, false);
198 * @return location the user wants to store this repository.
200 public File
getDestinationFile() {
201 return new File(directoryText
.getText());
205 * @return initial branch selected (includes refs/heads prefix).
207 public String
getInitialBranch() {
208 final int ix
= initialBranch
.getSelectionIndex();
210 return Constants
.R_HEADS
+ Constants
.MASTER
;
211 return Constants
.R_HEADS
+ initialBranch
.getItem(ix
);
215 * @return remote name
217 public String
getRemote() {
218 return remoteText
.getText();
222 * Check internal state for page completion status.
224 private void checkPage() {
225 final String dstpath
= directoryText
.getText();
226 if (dstpath
.length() == 0) {
227 setErrorMessage(NLS
.bind(UIText
.CloneDestinationPage_fieldRequired
,
228 UIText
.CloneDestinationPage_promptDirectory
));
229 setPageComplete(false);
232 final File absoluteFile
= new File(dstpath
).getAbsoluteFile();
233 if (!isEmptyDir(absoluteFile
)) {
234 setErrorMessage(NLS
.bind(
235 UIText
.CloneDestinationPage_errorNotEmptyDir
, absoluteFile
237 setPageComplete(false);
241 if (!canCreateSubdir(absoluteFile
.getParentFile())) {
242 setErrorMessage(NLS
.bind(UIText
.GitCloneWizard_errorCannotCreate
,
243 absoluteFile
.getPath()));
244 setPageComplete(false);
247 if (!branchPage
.isSourceRepoEmpty()
248 && initialBranch
.getSelectionIndex() < 0) {
249 setErrorMessage(NLS
.bind(UIText
.CloneDestinationPage_fieldRequired
,
250 UIText
.CloneDestinationPage_promptInitialBranch
));
251 setPageComplete(false);
254 if (remoteText
.getText().length() == 0) {
255 setErrorMessage(NLS
.bind(UIText
.CloneDestinationPage_fieldRequired
,
256 UIText
.CloneDestinationPage_promptRemoteName
));
257 setPageComplete(false);
261 setErrorMessage(null);
262 setPageComplete(true);
265 private static boolean isEmptyDir(final File dir
) {
268 if (!dir
.isDirectory())
270 return dir
.listFiles().length
== 0;
273 // this is actually just an optimistic heuristic - should be named
274 // isThereHopeThatCanCreateSubdir() as probably there is no 100% reliable
275 // way to check that in Java for Windows
276 private static boolean canCreateSubdir(final File parent
) {
280 return parent
.isDirectory() && parent
.canWrite();
281 return canCreateSubdir(parent
.getParentFile());
284 private void revalidate() {
285 if (sourcePage
.selectionEquals(validatedRepoSelection
)
286 && branchPage
.selectionEquals(validatedSelectedBranches
,
292 if (!sourcePage
.selectionEquals(validatedRepoSelection
)) {
293 validatedRepoSelection
= sourcePage
.getSelection();
294 // update repo-related selection only if it changed
295 final String n
= validatedRepoSelection
.getURI().getHumanishName();
296 setDescription(NLS
.bind(UIText
.CloneDestinationPage_description
, n
));
297 directoryText
.setText(new File(ResourcesPlugin
.getWorkspace()
298 .getRoot().getRawLocation().toFile(), n
).getAbsolutePath());
301 validatedSelectedBranches
= branchPage
.getSelectedBranches();
302 validatedHEAD
= branchPage
.getHEAD();
304 initialBranch
.removeAll();
305 final Ref head
= branchPage
.getHEAD();
307 for (final Ref r
: branchPage
.getSelectedBranches()) {
308 String name
= r
.getName();
309 if (name
.startsWith(Constants
.R_HEADS
))
310 name
= name
.substring((Constants
.R_HEADS
).length());
311 if (head
!= null && head
.getName().equals(r
.getName()))
312 newix
= initialBranch
.getItemCount();
313 initialBranch
.add(name
);
315 initialBranch
.select(newix
);