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
.jgit
.lib
.Constants
;
24 import org
.eclipse
.jgit
.lib
.Ref
;
25 import org
.eclipse
.osgi
.util
.NLS
;
26 import org
.eclipse
.swt
.SWT
;
27 import org
.eclipse
.swt
.events
.ModifyEvent
;
28 import org
.eclipse
.swt
.events
.ModifyListener
;
29 import org
.eclipse
.swt
.events
.SelectionAdapter
;
30 import org
.eclipse
.swt
.events
.SelectionEvent
;
31 import org
.eclipse
.swt
.layout
.GridData
;
32 import org
.eclipse
.swt
.layout
.GridLayout
;
33 import org
.eclipse
.swt
.widgets
.Button
;
34 import org
.eclipse
.swt
.widgets
.Combo
;
35 import org
.eclipse
.swt
.widgets
.Composite
;
36 import org
.eclipse
.swt
.widgets
.FileDialog
;
37 import org
.eclipse
.swt
.widgets
.Group
;
38 import org
.eclipse
.swt
.widgets
.Label
;
39 import org
.eclipse
.swt
.widgets
.Text
;
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 CloneDestinationPage(final RepositorySelectionPage sp
,
63 final SourceBranchPage bp
) {
64 super(CloneDestinationPage
.class.getName());
67 setTitle(UIText
.CloneDestinationPage_title
);
69 final SelectionChangeListener listener
= new SelectionChangeListener() {
70 public void selectionChanged() {
71 checkPreviousPagesSelections();
74 sourcePage
.addSelectionListener(listener
);
75 branchPage
.addSelectionListener(listener
);
78 public void createControl(final Composite parent
) {
79 final Composite panel
= new Composite(parent
, SWT
.NULL
);
80 final GridLayout layout
= new GridLayout();
81 layout
.numColumns
= 1;
82 panel
.setLayout(layout
);
84 createDestinationGroup(panel
);
85 createConfigGroup(panel
);
91 public void setVisible(final boolean visible
) {
93 if (branchPage
.isSourceRepoEmpty()) {
94 initialBranch
.setEnabled(false);
98 super.setVisible(visible
);
100 directoryText
.setFocus();
103 private void checkPreviousPagesSelections() {
104 if (!sourcePage
.selectionEquals(validatedRepoSelection
)
105 || !branchPage
.selectionEquals(validatedSelectedBranches
,
107 setPageComplete(false);
112 private void createDestinationGroup(final Composite parent
) {
113 final Group g
= createGroup(parent
,
114 UIText
.CloneDestinationPage_groupDestination
);
116 newLabel(g
, UIText
.CloneDestinationPage_promptDirectory
+ ":"); //$NON-NLS-1$
117 final Composite p
= new Composite(g
, SWT
.NONE
);
118 final GridLayout grid
= new GridLayout();
121 p
.setLayoutData(createFieldGridData());
122 directoryText
= new Text(p
, SWT
.BORDER
);
123 directoryText
.setLayoutData(createFieldGridData());
124 directoryText
.addModifyListener(new ModifyListener() {
125 public void modifyText(final ModifyEvent e
) {
129 final Button b
= new Button(p
, SWT
.PUSH
);
130 b
.setText(UIText
.CloneDestinationPage_browseButton
);
131 b
.addSelectionListener(new SelectionAdapter() {
132 public void widgetSelected(final SelectionEvent e
) {
135 d
= new FileDialog(getShell(), SWT
.APPLICATION_MODAL
| SWT
.SAVE
);
136 if (directoryText
.getText().length() > 0) {
137 final File file
= new File(directoryText
.getText())
139 d
.setFilterPath(file
.getParent());
140 d
.setFileName(file
.getName());
142 final String r
= d
.open();
144 directoryText
.setText(r
);
148 newLabel(g
, UIText
.CloneDestinationPage_promptInitialBranch
+ ":"); //$NON-NLS-1$
149 initialBranch
= new Combo(g
, SWT
.DROP_DOWN
| SWT
.READ_ONLY
);
150 initialBranch
.setLayoutData(createFieldGridData());
151 initialBranch
.addSelectionListener(new SelectionAdapter() {
153 public void widgetSelected(final SelectionEvent e
) {
159 private void createConfigGroup(final Composite parent
) {
160 final Group g
= createGroup(parent
,
161 UIText
.CloneDestinationPage_groupConfiguration
);
163 newLabel(g
, UIText
.CloneDestinationPage_promptRemoteName
+ ":"); //$NON-NLS-1$
164 remoteText
= new Text(g
, SWT
.BORDER
);
165 remoteText
.setText(Constants
.DEFAULT_REMOTE_NAME
);
166 remoteText
.setLayoutData(createFieldGridData());
167 remoteText
.addModifyListener(new ModifyListener() {
168 public void modifyText(ModifyEvent e
) {
174 private static Group
createGroup(final Composite parent
, final String text
) {
175 final Group g
= new Group(parent
, SWT
.NONE
);
176 final GridLayout layout
= new GridLayout();
177 layout
.numColumns
= 2;
180 final GridData gd
= new GridData();
181 gd
.grabExcessHorizontalSpace
= true;
182 gd
.horizontalAlignment
= SWT
.FILL
;
187 private static void newLabel(final Group g
, final String text
) {
188 new Label(g
, SWT
.NULL
).setText(text
);
191 private static GridData
createFieldGridData() {
192 return new GridData(SWT
.FILL
, SWT
.DEFAULT
, true, false);
196 * @return location the user wants to store this repository.
198 public File
getDestinationFile() {
199 return new File(directoryText
.getText());
203 * @return initial branch selected (includes refs/heads prefix).
205 public String
getInitialBranch() {
206 final int ix
= initialBranch
.getSelectionIndex();
208 return Constants
.R_HEADS
+ Constants
.MASTER
;
209 return Constants
.R_HEADS
+ initialBranch
.getItem(ix
);
213 * @return remote name
215 public String
getRemote() {
216 return remoteText
.getText();
220 * Check internal state for page completion status.
222 private void checkPage() {
223 final String dstpath
= directoryText
.getText();
224 if (dstpath
.length() == 0) {
225 setErrorMessage(NLS
.bind(UIText
.CloneDestinationPage_fieldRequired
,
226 UIText
.CloneDestinationPage_promptDirectory
));
227 setPageComplete(false);
230 final File absoluteFile
= new File(dstpath
).getAbsoluteFile();
231 if (!isEmptyDir(absoluteFile
)) {
232 setErrorMessage(NLS
.bind(
233 UIText
.CloneDestinationPage_errorNotEmptyDir
, absoluteFile
235 setPageComplete(false);
239 if (!canCreateSubdir(absoluteFile
.getParentFile())) {
240 setErrorMessage(NLS
.bind(UIText
.GitCloneWizard_errorCannotCreate
,
241 absoluteFile
.getPath()));
242 setPageComplete(false);
245 if (!branchPage
.isSourceRepoEmpty()
246 && initialBranch
.getSelectionIndex() < 0) {
247 setErrorMessage(NLS
.bind(UIText
.CloneDestinationPage_fieldRequired
,
248 UIText
.CloneDestinationPage_promptInitialBranch
));
249 setPageComplete(false);
252 if (remoteText
.getText().length() == 0) {
253 setErrorMessage(NLS
.bind(UIText
.CloneDestinationPage_fieldRequired
,
254 UIText
.CloneDestinationPage_promptRemoteName
));
255 setPageComplete(false);
259 setErrorMessage(null);
260 setPageComplete(true);
263 private static boolean isEmptyDir(final File dir
) {
266 if (!dir
.isDirectory())
268 return dir
.listFiles().length
== 0;
271 // this is actually just an optimistic heuristic - should be named
272 // isThereHopeThatCanCreateSubdir() as probably there is no 100% reliable
273 // way to check that in Java for Windows
274 private static boolean canCreateSubdir(final File parent
) {
278 return parent
.isDirectory() && parent
.canWrite();
279 return canCreateSubdir(parent
.getParentFile());
282 private void revalidate() {
283 if (sourcePage
.selectionEquals(validatedRepoSelection
)
284 && branchPage
.selectionEquals(validatedSelectedBranches
,
290 if (!sourcePage
.selectionEquals(validatedRepoSelection
)) {
291 validatedRepoSelection
= sourcePage
.getSelection();
292 // update repo-related selection only if it changed
293 final String n
= validatedRepoSelection
.getURI().getHumanishName();
294 setDescription(NLS
.bind(UIText
.CloneDestinationPage_description
, n
));
295 directoryText
.setText(new File(ResourcesPlugin
.getWorkspace()
296 .getRoot().getRawLocation().toFile(), n
).getAbsolutePath());
299 validatedSelectedBranches
= branchPage
.getSelectedBranches();
300 validatedHEAD
= branchPage
.getHEAD();
302 initialBranch
.removeAll();
303 final Ref head
= branchPage
.getHEAD();
305 for (final Ref r
: branchPage
.getSelectedBranches()) {
306 String name
= r
.getName();
307 if (name
.startsWith(Constants
.R_HEADS
))
308 name
= name
.substring((Constants
.R_HEADS
).length());
309 if (head
!= null && head
.getName().equals(r
.getName()))
310 newix
= initialBranch
.getItemCount();
311 initialBranch
.add(name
);
313 initialBranch
.select(newix
);