Update org.apache.commons:commons-compress to 1.25.0
[egit/eclipse.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / internal / clone / SourceBranchPage.java
bloba69492ad8f9613a9f89e1078d282c7a0fc84344b
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>
5 * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
6 * Copyright (c) 2010, Benjamin Muskalla <bmuskalla@eclipsesource.com>
7 * Copyright (c) 2012, IBM Corporation
9 * All rights reserved. This program and the accompanying materials
10 * are made available under the terms of the Eclipse Public License 2.0
11 * which accompanies this distribution, and is available at
12 * https://www.eclipse.org/legal/epl-2.0/
14 * SPDX-License-Identifier: EPL-2.0
15 *******************************************************************************/
16 package org.eclipse.egit.ui.internal.clone;
18 import java.lang.reflect.InvocationTargetException;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.List;
24 import org.eclipse.core.runtime.IProgressMonitor;
25 import org.eclipse.core.runtime.jobs.IJobChangeEvent;
26 import org.eclipse.core.runtime.jobs.JobChangeAdapter;
27 import org.eclipse.egit.core.credentials.UserPasswordCredentials;
28 import org.eclipse.egit.core.internal.credentials.EGitCredentialsProvider;
29 import org.eclipse.egit.core.op.ListRemoteOperation;
30 import org.eclipse.egit.core.settings.GitSettings;
31 import org.eclipse.egit.ui.Activator;
32 import org.eclipse.egit.ui.UIPreferences;
33 import org.eclipse.egit.ui.UIUtils;
34 import org.eclipse.egit.ui.internal.CommonUtils;
35 import org.eclipse.egit.ui.internal.UIIcons;
36 import org.eclipse.egit.ui.internal.UIText;
37 import org.eclipse.egit.ui.internal.components.CachedCheckboxTreeViewer;
38 import org.eclipse.egit.ui.internal.components.FilteredCheckboxTree;
39 import org.eclipse.egit.ui.internal.components.RepositorySelection;
40 import org.eclipse.egit.ui.internal.dialogs.SourceBranchFailureDialog;
41 import org.eclipse.egit.ui.internal.repository.tree.RepositoryTreeNodeType;
42 import org.eclipse.jface.dialogs.Dialog;
43 import org.eclipse.jface.dialogs.IMessageProvider;
44 import org.eclipse.jface.operation.IRunnableWithProgress;
45 import org.eclipse.jface.viewers.CheckStateChangedEvent;
46 import org.eclipse.jface.viewers.ICheckStateListener;
47 import org.eclipse.jface.viewers.ITreeContentProvider;
48 import org.eclipse.jface.viewers.LabelProvider;
49 import org.eclipse.jface.viewers.Viewer;
50 import org.eclipse.jface.wizard.WizardPage;
51 import org.eclipse.jgit.annotations.NonNull;
52 import org.eclipse.jgit.api.errors.TransportException;
53 import org.eclipse.jgit.lib.Constants;
54 import org.eclipse.jgit.lib.ObjectId;
55 import org.eclipse.jgit.lib.Ref;
56 import org.eclipse.jgit.transport.TagOpt;
57 import org.eclipse.jgit.transport.URIish;
58 import org.eclipse.osgi.util.NLS;
59 import org.eclipse.swt.SWT;
60 import org.eclipse.swt.events.SelectionAdapter;
61 import org.eclipse.swt.events.SelectionEvent;
62 import org.eclipse.swt.graphics.Image;
63 import org.eclipse.swt.layout.GridData;
64 import org.eclipse.swt.layout.GridLayout;
65 import org.eclipse.swt.layout.RowLayout;
66 import org.eclipse.swt.widgets.Button;
67 import org.eclipse.swt.widgets.Composite;
68 import org.eclipse.swt.widgets.Group;
69 import org.eclipse.swt.widgets.Label;
70 import org.eclipse.ui.PlatformUI;
71 import org.eclipse.ui.dialogs.PatternFilter;
72 import org.eclipse.ui.progress.WorkbenchJob;
74 class SourceBranchPage extends WizardPage {
76 private RepositorySelection validatedRepoSelection;
78 private Ref head;
80 private final List<Ref> availableRefs = new ArrayList<>();
82 private Label label;
84 private String transportError;
86 private Button selectB;
88 private Button unselectB;
90 private TagOpt tagOption = TagOpt.AUTO_FOLLOW;
92 private CachedCheckboxTreeViewer refsViewer;
94 private UserPasswordCredentials credentials;
96 private String helpContext = null;
98 SourceBranchPage() {
99 super(SourceBranchPage.class.getName());
100 setTitle(UIText.SourceBranchPage_title);
101 setDescription(UIText.SourceBranchPage_description);
104 List<Ref> getSelectedBranches() {
105 Object[] checkedElements = refsViewer.getCheckedElements();
106 Ref[] checkedRefs = new Ref[checkedElements.length];
107 System.arraycopy(checkedElements, 0, checkedRefs, 0, checkedElements.length);
108 return Arrays.asList(checkedRefs);
111 TagOpt getTagOption() {
112 return tagOption;
115 List<Ref> getAvailableBranches() {
116 return availableRefs;
119 Ref getHEAD() {
120 return head;
123 boolean isSourceRepoEmpty() {
124 return availableRefs.isEmpty();
127 boolean isAllSelected() {
128 return availableRefs.size() == refsViewer.getCheckedElements().length;
131 @Override
132 public void createControl(final Composite parent) {
133 final Composite panel = new Composite(parent, SWT.NULL);
134 final GridLayout layout = new GridLayout();
135 layout.numColumns = 1;
136 panel.setLayout(layout);
138 label = new Label(panel, SWT.NONE);
139 label.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
141 FilteredCheckboxTree fTree = new FilteredCheckboxTree(panel, null,
142 SWT.NONE, new PatternFilter()) {
144 * Overridden to check page when refreshing is done.
146 @Override
147 protected WorkbenchJob doCreateRefreshJob() {
148 WorkbenchJob refreshJob = super.doCreateRefreshJob();
149 refreshJob.addJobChangeListener(new JobChangeAdapter() {
150 @Override
151 public void done(IJobChangeEvent event) {
152 if (event.getResult().isOK()) {
153 getDisplay().asyncExec(new Runnable() {
154 @Override
155 public void run() {
156 checkPage();
162 return refreshJob;
165 UIUtils.associateLabel(fTree.getFilterControl(), label);
166 refsViewer = fTree.getCheckboxTreeViewer();
168 ITreeContentProvider provider = new ITreeContentProvider() {
170 @Override
171 public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
172 // nothing
175 @Override
176 public void dispose() {
177 // nothing
180 @Override
181 public Object[] getElements(Object input) {
182 return ((List) input).toArray();
185 @Override
186 public boolean hasChildren(Object element) {
187 return false;
190 @Override
191 public Object getParent(Object element) {
192 return null;
195 @Override
196 public Object[] getChildren(Object parentElement) {
197 return null;
200 refsViewer.setContentProvider(provider);
201 refsViewer.setLabelProvider(new LabelProvider() {
202 @Override
203 public String getText(Object element) {
204 if (((Ref)element).getName().startsWith(Constants.R_HEADS))
205 return ((Ref)element).getName().substring(Constants.R_HEADS.length());
206 return ((Ref)element).getName();
209 @Override
210 public Image getImage(Object element) {
211 return UIIcons.getImage(
212 Activator.getDefault().getResourceManager(),
213 RepositoryTreeNodeType.REF.getIcon());
217 refsViewer.addCheckStateListener(new ICheckStateListener() {
218 @Override
219 public void checkStateChanged(CheckStateChangedEvent event) {
220 checkPage();
223 final Composite bPanel = new Composite(panel, SWT.NONE);
224 bPanel.setLayout(new RowLayout());
225 selectB = new Button(bPanel, SWT.PUSH);
226 selectB.setText(UIText.SourceBranchPage_selectAll);
227 selectB.addSelectionListener(new SelectionAdapter() {
228 @Override
229 public void widgetSelected(final SelectionEvent e) {
230 refsViewer.setAllChecked(true);
231 checkPage();
234 unselectB = new Button(bPanel, SWT.PUSH);
235 unselectB.setText(UIText.SourceBranchPage_selectNone);
236 unselectB.addSelectionListener(new SelectionAdapter() {
237 @Override
238 public void widgetSelected(final SelectionEvent e) {
239 refsViewer.setAllChecked(false);
240 checkPage();
243 createTagOptionGroup(panel);
244 bPanel.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
246 Dialog.applyDialogFont(panel);
247 setControl(panel);
248 checkPage();
251 private void createTagOptionGroup(Composite parent) {
252 final Group tagsGroup = new Group(parent, SWT.NULL);
253 tagsGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
254 tagsGroup.setText(UIText.TagOptions_groupName);
255 tagsGroup.setLayout(new GridLayout());
256 createTagOptionButton(tagsGroup, TagOpt.AUTO_FOLLOW,
257 UIText.TagOptions_autoFollow);
258 createTagOptionButton(tagsGroup, TagOpt.FETCH_TAGS,
259 UIText.TagOptions_fetchTags);
260 createTagOptionButton(tagsGroup, TagOpt.NO_TAGS,
261 UIText.TagOptions_noTags);
264 private void createTagOptionButton(Group tagsGroup, final TagOpt option,
265 String text) {
266 Button button = new Button(tagsGroup, SWT.RADIO);
267 button.setText(text);
268 button.setSelection(option == tagOption);
269 button.addSelectionListener(new SelectionAdapter() {
270 @Override
271 public void widgetSelected(SelectionEvent e) {
272 tagOption = option;
277 public void setSelection(@NonNull RepositorySelection selection) {
278 revalidate(selection);
281 public void setCredentials(UserPasswordCredentials credentials) {
282 this.credentials = credentials;
286 * Set the ID for context sensitive help
288 * @param id
289 * help context
291 public void setHelpContext(String id) {
292 helpContext = id;
295 @Override
296 public void performHelp() {
297 PlatformUI.getWorkbench().getHelpSystem().displayHelp(helpContext);
301 * Check internal state for page completion status. This method should be
302 * called only when all necessary data from previous form is available.
304 private void checkPage() {
305 setMessage(null);
306 int checkedElementCount = refsViewer.getCheckedElements().length;
307 selectB.setEnabled(checkedElementCount != availableRefs.size());
308 unselectB.setEnabled(checkedElementCount != 0);
309 if (transportError != null) {
310 setErrorMessage(transportError);
311 setPageComplete(false);
312 return;
315 if (getSelectedBranches().isEmpty()) {
316 setErrorMessage(UIText.SourceBranchPage_errorBranchRequired);
317 setPageComplete(false);
318 return;
320 setErrorMessage(null);
321 setPageComplete(true);
324 private void checkForEmptyRepo() {
325 if (isSourceRepoEmpty()) {
326 setErrorMessage(null);
327 setMessage(UIText.SourceBranchPage_repoEmpty, IMessageProvider.WARNING);
328 setPageComplete(true);
332 private void revalidate(@NonNull final RepositorySelection newRepoSelection) {
333 if (newRepoSelection.equals(validatedRepoSelection)) {
334 // URI hasn't changed, no need to refill the page with new data
335 checkPage();
336 return;
339 label.setText(NLS.bind(UIText.SourceBranchPage_branchList,
340 newRepoSelection.getURI().toString()));
341 label.getParent().layout();
343 validatedRepoSelection = null;
344 transportError = null;
345 head = null;
346 availableRefs.clear();
347 refsViewer.setInput(null);
348 setPageComplete(false);
349 setErrorMessage(null);
350 setMessage(null);
351 label.getDisplay().asyncExec(new Runnable() {
352 @Override
353 public void run() {
354 revalidateImpl(newRepoSelection);
359 private void revalidateImpl(final RepositorySelection newRepoSelection) {
360 if (label.isDisposed() || !isCurrentPage())
361 return;
363 final ListRemoteOperation listRemoteOp;
364 final URIish uri = newRepoSelection.getURI();
365 try {
366 listRemoteOp = new ListRemoteOperation(uri,
367 GitSettings.getRemoteConnectionTimeout());
368 if (credentials != null)
369 listRemoteOp
370 .setCredentialsProvider(new EGitCredentialsProvider(
371 credentials.getUser(), credentials
372 .getPassword()));
373 getContainer().run(true, true, new IRunnableWithProgress() {
374 @Override
375 public void run(IProgressMonitor monitor)
376 throws InvocationTargetException, InterruptedException {
377 listRemoteOp.run(monitor);
380 } catch (InvocationTargetException e) {
381 Throwable why = e.getCause();
382 transportError(why);
383 if (showDetailedFailureDialog())
384 SourceBranchFailureDialog.show(getShell(), uri);
385 return;
386 } catch (InterruptedException e) {
387 transportError(UIText.SourceBranchPage_remoteListingCancelled);
388 return;
391 final Ref idHEAD = listRemoteOp.getRemoteRef(Constants.HEAD);
392 head = null;
393 boolean headIsMaster = false;
394 final String masterBranchRef = Constants.R_HEADS + Constants.MASTER;
395 for (final Ref r : listRemoteOp.getRemoteRefs()) {
396 final String n = r.getName();
397 if (!n.startsWith(Constants.R_HEADS)) {
398 continue;
400 availableRefs.add(r);
401 if (idHEAD == null || headIsMaster) {
402 continue;
404 ObjectId objectId = r.getObjectId();
405 if (objectId == null) {
406 continue;
408 if (objectId.equals(idHEAD.getObjectId())) {
409 headIsMaster = masterBranchRef.equals(r.getName());
410 if (head == null || headIsMaster) {
411 head = r;
415 Collections.sort(availableRefs, CommonUtils.REF_ASCENDING_COMPARATOR);
416 if (idHEAD != null && head == null) {
417 head = idHEAD;
418 availableRefs.add(0, idHEAD);
421 validatedRepoSelection = newRepoSelection;
422 refsViewer.setInput(availableRefs);
423 refsViewer.setAllChecked(true);
424 checkPage();
425 checkForEmptyRepo();
428 private void transportError(final Throwable why) {
429 Activator.logError(why.getMessage(), why);
430 Throwable cause = why.getCause();
431 if (why instanceof TransportException && cause != null)
432 transportError(NLS.bind(getMessage(why), why.getMessage(),
433 cause.getMessage()));
434 else
435 transportError(why.getMessage());
438 private String getMessage(final Throwable why) {
439 if (why.getMessage().endsWith("Auth fail")) //$NON-NLS-1$
440 return UIText.SourceBranchPage_AuthFailMessage;
441 else
442 return UIText.SourceBranchPage_CompositeTransportErrorMessage;
445 private void transportError(final String msg) {
446 transportError = msg;
447 checkPage();
450 private boolean showDetailedFailureDialog() {
451 return Activator
452 .getDefault()
453 .getPreferenceStore()
454 .getBoolean(
455 UIPreferences.CLONE_WIZARD_SHOW_DETAILED_FAILURE_DIALOG);