Git Import Wizard
[egit.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / internal / clone / SourceBranchPage.java
blobe1af8973e073fd9d0fbde9ae0b593f1f7351e136
1 /*******************************************************************************
2 * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
3 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
4 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *******************************************************************************/
11 package org.eclipse.egit.ui.internal.clone;
13 import java.io.File;
14 import java.io.IOException;
15 import java.lang.reflect.InvocationTargetException;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.Comparator;
19 import java.util.List;
21 import org.eclipse.core.runtime.IProgressMonitor;
22 import org.eclipse.core.runtime.IStatus;
23 import org.eclipse.core.runtime.Status;
24 import org.eclipse.egit.core.op.ListRemoteOperation;
25 import org.eclipse.egit.ui.Activator;
26 import org.eclipse.egit.ui.UIText;
27 import org.eclipse.egit.ui.internal.components.BaseWizardPage;
28 import org.eclipse.egit.ui.internal.components.RepositorySelection;
29 import org.eclipse.egit.ui.internal.components.RepositorySelectionPage;
30 import org.eclipse.egit.ui.internal.components.SelectionChangeListener;
31 import org.eclipse.jface.dialogs.ErrorDialog;
32 import org.eclipse.jface.dialogs.IMessageProvider;
33 import org.eclipse.jface.operation.IRunnableWithProgress;
34 import org.eclipse.osgi.util.NLS;
35 import org.eclipse.swt.SWT;
36 import org.eclipse.swt.events.SelectionAdapter;
37 import org.eclipse.swt.events.SelectionEvent;
38 import org.eclipse.swt.layout.GridData;
39 import org.eclipse.swt.layout.GridLayout;
40 import org.eclipse.swt.layout.RowLayout;
41 import org.eclipse.swt.widgets.Button;
42 import org.eclipse.swt.widgets.Composite;
43 import org.eclipse.swt.widgets.Label;
44 import org.eclipse.swt.widgets.Table;
45 import org.eclipse.swt.widgets.TableItem;
46 import org.eclipse.jgit.lib.Constants;
47 import org.eclipse.jgit.lib.Ref;
48 import org.eclipse.jgit.lib.Repository;
49 import org.eclipse.jgit.transport.URIish;
51 class SourceBranchPage extends BaseWizardPage {
52 private final RepositorySelectionPage sourcePage;
54 private RepositorySelection validatedRepoSelection;
56 private Ref head;
58 private List<Ref> availableRefs = new ArrayList<Ref>();
60 private List<Ref> selectedRefs = new ArrayList<Ref>();
62 private boolean sourceRepoEmpty = false;
64 private Label label;
66 private Table refsTable;
68 private String transportError;
70 SourceBranchPage(final RepositorySelectionPage sp) {
71 super(SourceBranchPage.class.getName());
72 sourcePage = sp;
73 setTitle(UIText.SourceBranchPage_title);
74 setDescription(UIText.SourceBranchPage_description);
76 sourcePage.addSelectionListener(new SelectionChangeListener() {
77 public void selectionChanged() {
78 if (!sourcePage.selectionEquals(validatedRepoSelection))
79 setPageComplete(false);
80 else
81 checkPage();
83 });
86 List<Ref> getSelectedBranches() {
87 return new ArrayList<Ref>(selectedRefs);
90 Ref getHEAD() {
91 return head;
94 boolean isSourceRepoEmpty() {
95 return sourceRepoEmpty;
98 boolean isAllSelected() {
99 return availableRefs.size() == selectedRefs.size();
102 boolean selectionEquals(final List<Ref> actSelectedRef, final Ref actHead) {
103 return this.selectedRefs.equals(actSelectedRef) && this.head == actHead;
106 public void createControl(final Composite parent) {
107 final Composite panel = new Composite(parent, SWT.NULL);
108 final GridLayout layout = new GridLayout();
109 layout.numColumns = 1;
110 panel.setLayout(layout);
112 label = new Label(panel, SWT.NONE);
113 label.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
115 refsTable = new Table(panel, SWT.CHECK | SWT.V_SCROLL | SWT.BORDER);
116 refsTable.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
117 refsTable.addSelectionListener(new SelectionAdapter() {
118 @Override
119 public void widgetSelected(final SelectionEvent e) {
120 if (e.detail != SWT.CHECK)
121 return;
123 final TableItem tableItem = (TableItem) e.item;
124 final int i = refsTable.indexOf(tableItem);
125 final Ref ref = availableRefs.get(i);
127 if (tableItem.getChecked()) {
128 int insertionPos = 0;
129 for (int j = 0; j < i; j++) {
130 if (selectedRefs.contains(availableRefs.get(j)))
131 insertionPos++;
133 selectedRefs.add(insertionPos, ref);
134 } else
135 selectedRefs.remove(ref);
137 notifySelectionChanged();
138 checkPage();
142 final Composite bPanel = new Composite(panel, SWT.NONE);
143 bPanel.setLayout(new RowLayout());
144 final Button selectB;
145 selectB = new Button(bPanel, SWT.PUSH);
146 selectB.setText(UIText.SourceBranchPage_selectAll);
147 selectB.addSelectionListener(new SelectionAdapter() {
148 public void widgetSelected(final SelectionEvent e) {
149 for (int i = 0; i < refsTable.getItemCount(); i++)
150 refsTable.getItem(i).setChecked(true);
151 selectedRefs.clear();
152 selectedRefs.addAll(availableRefs);
153 notifySelectionChanged();
154 checkPage();
157 final Button unselectB = new Button(bPanel, SWT.PUSH);
158 unselectB.setText(UIText.SourceBranchPage_selectNone);
159 unselectB.addSelectionListener(new SelectionAdapter() {
160 public void widgetSelected(final SelectionEvent e) {
161 for (int i = 0; i < refsTable.getItemCount(); i++)
162 refsTable.getItem(i).setChecked(false);
163 selectedRefs.clear();
164 notifySelectionChanged();
165 checkPage();
168 bPanel.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
170 addSelectionListener(new SelectionChangeListener() {
171 public void selectionChanged() {
172 selectB.setEnabled(selectedRefs.size() != availableRefs.size());
173 unselectB.setEnabled(selectedRefs.size() != 0);
177 setControl(panel);
178 checkPage();
181 @Override
182 public void setVisible(final boolean visible) {
183 if (visible)
184 revalidate();
185 super.setVisible(visible);
189 * Check internal state for page completion status. This method should be
190 * called only when all necessary data from previous form is available.
192 private void checkPage() {
193 if (transportError != null) {
194 setErrorMessage(transportError);
195 setPageComplete(false);
196 return;
199 if (isSourceRepoEmpty()) {
200 setMessage(UIText.SourceBranchPage_repoEmpty, IMessageProvider.WARNING);
201 setPageComplete(true);
202 return;
205 if ( getSelectedBranches().isEmpty()) {
206 setErrorMessage(UIText.SourceBranchPage_errorBranchRequired);
207 setPageComplete(false);
208 return;
211 setErrorMessage(null);
212 setPageComplete(true);
215 private void revalidate() {
216 if (sourcePage.selectionEquals(validatedRepoSelection)) {
217 // URI hasn't changed, no need to refill the page with new data
218 checkPage();
219 return;
222 final RepositorySelection newRepoSelection = sourcePage.getSelection();
223 label.setText(NLS.bind(UIText.SourceBranchPage_branchList,
224 newRepoSelection.getURI().toString()));
225 label.getParent().layout();
227 validatedRepoSelection = null;
228 transportError = null;
229 head = null;
230 availableRefs.clear();
231 selectedRefs.clear();
232 refsTable.removeAll();
233 setPageComplete(false);
234 setErrorMessage(null);
235 label.getDisplay().asyncExec(new Runnable() {
236 public void run() {
237 revalidateImpl(newRepoSelection);
242 private void revalidateImpl(final RepositorySelection newRepoSelection) {
243 if (label.isDisposed() || !isCurrentPage())
244 return;
246 final ListRemoteOperation listRemoteOp;
247 try {
248 final URIish uri = newRepoSelection.getURI();
249 final Repository db = new Repository(new File("/tmp")); //$NON-NLS-1$
250 listRemoteOp = new ListRemoteOperation(db, uri);
251 getContainer().run(true, true, new IRunnableWithProgress() {
252 public void run(IProgressMonitor monitor)
253 throws InvocationTargetException, InterruptedException {
254 listRemoteOp.run(monitor);
257 } catch (InvocationTargetException e) {
258 Throwable why = e.getCause();
259 transportError(why.getMessage());
260 ErrorDialog.openError(getShell(),
261 UIText.SourceBranchPage_transportError,
262 UIText.SourceBranchPage_cannotListBranches, new Status(
263 IStatus.ERROR, Activator.getPluginId(), 0, why
264 .getMessage(), why.getCause()));
265 return;
266 } catch (IOException e) {
267 transportError(UIText.SourceBranchPage_cannotCreateTemp);
268 return;
269 } catch (InterruptedException e) {
270 transportError(UIText.SourceBranchPage_remoteListingCancelled);
271 return;
274 final Ref idHEAD = listRemoteOp.getRemoteRef(Constants.HEAD);
275 head = null;
276 for (final Ref r : listRemoteOp.getRemoteRefs()) {
277 final String n = r.getName();
278 if (!n.startsWith(Constants.R_HEADS))
279 continue;
280 availableRefs.add(r);
281 if (idHEAD == null || head != null)
282 continue;
283 if (r.getObjectId().equals(idHEAD.getObjectId()))
284 head = r;
286 Collections.sort(availableRefs, new Comparator<Ref>() {
287 public int compare(final Ref o1, final Ref o2) {
288 return o1.getName().compareTo(o2.getName());
291 if (idHEAD != null && head == null) {
292 head = idHEAD;
293 availableRefs.add(0, idHEAD);
296 validatedRepoSelection = newRepoSelection;
297 for (final Ref r : availableRefs) {
298 String n = r.getName();
299 if (n.startsWith(Constants.R_HEADS))
300 n = n.substring(Constants.R_HEADS.length());
301 final TableItem ti = new TableItem(refsTable, SWT.NONE);
302 ti.setText(n);
303 ti.setChecked(true);
304 selectedRefs.add(r);
306 if (availableRefs.size() == 0)
307 sourceRepoEmpty = true;
308 notifySelectionChanged();
309 checkPage();
312 private void transportError(final String msg) {
313 transportError = msg;
314 checkPage();