1 /*******************************************************************************
2 * Copyright (c) 2010, 2014 SAP AG and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * Mathias Kinzler (SAP AG) - initial implementation
10 * Marc Khouzam (Ericsson) - Add an option not to checkout the new branch
11 *******************************************************************************/
12 package org
.eclipse
.egit
.ui
.internal
.fetch
;
14 import java
.io
.IOException
;
15 import java
.lang
.reflect
.InvocationTargetException
;
16 import java
.net
.URISyntaxException
;
17 import java
.util
.ArrayList
;
18 import java
.util
.Collections
;
19 import java
.util
.Comparator
;
20 import java
.util
.List
;
21 import java
.util
.SortedSet
;
22 import java
.util
.TreeSet
;
23 import java
.util
.regex
.Matcher
;
24 import java
.util
.regex
.Pattern
;
25 import java
.util
.regex
.PatternSyntaxException
;
27 import org
.eclipse
.core
.resources
.WorkspaceJob
;
28 import org
.eclipse
.core
.runtime
.CoreException
;
29 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
30 import org
.eclipse
.core
.runtime
.IStatus
;
31 import org
.eclipse
.core
.runtime
.jobs
.Job
;
32 import org
.eclipse
.egit
.core
.op
.CreateLocalBranchOperation
;
33 import org
.eclipse
.egit
.core
.op
.ListRemoteOperation
;
34 import org
.eclipse
.egit
.core
.op
.TagOperation
;
35 import org
.eclipse
.egit
.ui
.Activator
;
36 import org
.eclipse
.egit
.ui
.JobFamilies
;
37 import org
.eclipse
.egit
.ui
.UIPreferences
;
38 import org
.eclipse
.egit
.ui
.UIUtils
;
39 import org
.eclipse
.egit
.ui
.internal
.UIText
;
40 import org
.eclipse
.egit
.ui
.internal
.ValidationUtils
;
41 import org
.eclipse
.egit
.ui
.internal
.branch
.BranchOperationUI
;
42 import org
.eclipse
.egit
.ui
.internal
.dialogs
.AbstractBranchSelectionDialog
;
43 import org
.eclipse
.egit
.ui
.internal
.dialogs
.BranchEditDialog
;
44 import org
.eclipse
.egit
.ui
.internal
.dialogs
.CheckoutConflictDialog
;
45 import org
.eclipse
.jface
.bindings
.keys
.KeyStroke
;
46 import org
.eclipse
.jface
.dialogs
.Dialog
;
47 import org
.eclipse
.jface
.dialogs
.IDialogSettings
;
48 import org
.eclipse
.jface
.dialogs
.IInputValidator
;
49 import org
.eclipse
.jface
.fieldassist
.ContentProposalAdapter
;
50 import org
.eclipse
.jface
.fieldassist
.IContentProposal
;
51 import org
.eclipse
.jface
.fieldassist
.IContentProposalProvider
;
52 import org
.eclipse
.jface
.fieldassist
.TextContentAdapter
;
53 import org
.eclipse
.jface
.layout
.GridDataFactory
;
54 import org
.eclipse
.jface
.operation
.IRunnableWithProgress
;
55 import org
.eclipse
.jface
.resource
.JFaceResources
;
56 import org
.eclipse
.jface
.window
.Window
;
57 import org
.eclipse
.jface
.wizard
.WizardPage
;
58 import org
.eclipse
.jgit
.api
.CheckoutCommand
;
59 import org
.eclipse
.jgit
.api
.CheckoutResult
;
60 import org
.eclipse
.jgit
.api
.CheckoutResult
.Status
;
61 import org
.eclipse
.jgit
.api
.Git
;
62 import org
.eclipse
.jgit
.api
.errors
.CheckoutConflictException
;
63 import org
.eclipse
.jgit
.api
.errors
.GitAPIException
;
64 import org
.eclipse
.jgit
.lib
.Constants
;
65 import org
.eclipse
.jgit
.lib
.PersonIdent
;
66 import org
.eclipse
.jgit
.lib
.Ref
;
67 import org
.eclipse
.jgit
.lib
.Repository
;
68 import org
.eclipse
.jgit
.lib
.TagBuilder
;
69 import org
.eclipse
.jgit
.revwalk
.RevCommit
;
70 import org
.eclipse
.jgit
.revwalk
.RevWalk
;
71 import org
.eclipse
.jgit
.transport
.FetchResult
;
72 import org
.eclipse
.jgit
.transport
.RefSpec
;
73 import org
.eclipse
.jgit
.transport
.RemoteConfig
;
74 import org
.eclipse
.jgit
.transport
.URIish
;
75 import org
.eclipse
.osgi
.util
.NLS
;
76 import org
.eclipse
.swt
.SWT
;
77 import org
.eclipse
.swt
.dnd
.Clipboard
;
78 import org
.eclipse
.swt
.dnd
.TextTransfer
;
79 import org
.eclipse
.swt
.events
.ModifyEvent
;
80 import org
.eclipse
.swt
.events
.ModifyListener
;
81 import org
.eclipse
.swt
.events
.SelectionAdapter
;
82 import org
.eclipse
.swt
.events
.SelectionEvent
;
83 import org
.eclipse
.swt
.layout
.GridData
;
84 import org
.eclipse
.swt
.layout
.GridLayout
;
85 import org
.eclipse
.swt
.widgets
.Button
;
86 import org
.eclipse
.swt
.widgets
.Combo
;
87 import org
.eclipse
.swt
.widgets
.Composite
;
88 import org
.eclipse
.swt
.widgets
.Group
;
89 import org
.eclipse
.swt
.widgets
.Label
;
90 import org
.eclipse
.swt
.widgets
.Shell
;
91 import org
.eclipse
.swt
.widgets
.Text
;
92 import org
.eclipse
.ui
.IWorkbenchCommandConstants
;
93 import org
.eclipse
.ui
.PlatformUI
;
96 * Fetch a change from Gerrit
98 public class FetchGerritChangePage
extends WizardPage
{
99 private static final String FETCH_GERRIT_CHANGE_PAGE_SECTION
= "FetchGerritChangePage"; //$NON-NLS-1$
101 private static final String LAST_URI_POSTFIX
= ".lastUri"; //$NON-NLS-1$
103 private static final String RUN_IN_BACKGROUND
= "runInBackground"; //$NON-NLS-1$
105 private final Repository repository
;
107 private final IDialogSettings settings
;
109 private final String lastUriKey
;
111 private Combo uriCombo
;
113 private List
<Change
> changeRefs
;
115 private Text refText
;
117 private Button createBranch
;
119 private Button createTag
;
121 private Button checkout
;
123 private Button dontCheckout
;
125 private Label tagTextlabel
;
127 private Text tagText
;
129 private Label branchTextlabel
;
131 private Text branchText
;
133 private String refName
;
135 private Composite warningAdditionalRefNotActive
;
137 private Button activateAdditionalRefs
;
139 private Button runInBackgroud
;
141 private IInputValidator branchValidator
;
142 private IInputValidator tagValidator
;
144 private Button branchEditButton
;
146 private Button branchCheckoutButton
;
150 * @param refName initial value for the ref field
152 public FetchGerritChangePage(Repository repository
, String refName
) {
153 super(FetchGerritChangePage
.class.getName());
154 this.repository
= repository
;
155 this.refName
= refName
;
157 .bind(UIText
.FetchGerritChangePage_PageTitle
,
158 Activator
.getDefault().getRepositoryUtil()
159 .getRepositoryName(repository
)));
160 setMessage(UIText
.FetchGerritChangePage_PageMessage
);
161 settings
= getDialogSettings();
162 lastUriKey
= repository
+ LAST_URI_POSTFIX
;
164 branchValidator
= ValidationUtils
.getRefNameInputValidator(repository
,
165 Constants
.R_HEADS
, true);
166 tagValidator
= ValidationUtils
.getRefNameInputValidator(repository
,
167 Constants
.R_TAGS
, true);
171 protected IDialogSettings
getDialogSettings() {
172 IDialogSettings s
= Activator
.getDefault().getDialogSettings();
173 IDialogSettings section
= s
174 .getSection(FETCH_GERRIT_CHANGE_PAGE_SECTION
);
176 section
= s
.addNewSection(FETCH_GERRIT_CHANGE_PAGE_SECTION
);
181 public void createControl(Composite parent
) {
182 Clipboard clipboard
= new Clipboard(parent
.getDisplay());
183 String clipText
= (String
) clipboard
.getContents(TextTransfer
185 String defaultUri
= null;
186 String defaultCommand
= null;
187 String defaultChange
= null;
188 if (clipText
!= null) {
189 final String pattern
= "git fetch (\\w+:\\S+) (refs/changes/\\d+/\\d+/\\d+) && git (\\w+) FETCH_HEAD"; //$NON-NLS-1$
190 Matcher matcher
= Pattern
.compile(pattern
).matcher(clipText
);
191 if (matcher
.matches()) {
192 defaultUri
= matcher
.group(1);
193 defaultChange
= matcher
.group(2);
194 defaultCommand
= matcher
.group(3);
197 Composite main
= new Composite(parent
, SWT
.NONE
);
198 main
.setLayout(new GridLayout(2, false));
199 GridDataFactory
.fillDefaults().grab(true, true).applyTo(main
);
200 new Label(main
, SWT
.NONE
)
201 .setText(UIText
.FetchGerritChangePage_UriLabel
);
202 uriCombo
= new Combo(main
, SWT
.DROP_DOWN
);
203 GridDataFactory
.fillDefaults().grab(true, false).applyTo(uriCombo
);
204 uriCombo
.addSelectionListener(new SelectionAdapter() {
206 public void widgetSelected(SelectionEvent e
) {
210 new Label(main
, SWT
.NONE
)
211 .setText(UIText
.FetchGerritChangePage_ChangeLabel
);
212 refText
= new Text(main
, SWT
.BORDER
);
213 if (defaultChange
!= null)
214 refText
.setText(defaultChange
);
215 GridDataFactory
.fillDefaults().grab(true, false).applyTo(refText
);
216 addRefContentProposalToText(refText
);
218 final Group checkoutGroup
= new Group(main
, SWT
.SHADOW_ETCHED_IN
);
219 checkoutGroup
.setLayout(new GridLayout(3, false));
220 GridDataFactory
.fillDefaults().span(3, 1).grab(true, false)
221 .applyTo(checkoutGroup
);
222 checkoutGroup
.setText(UIText
.FetchGerritChangePage_AfterFetchGroup
);
224 // radio: create local branch
225 createBranch
= new Button(checkoutGroup
, SWT
.RADIO
);
226 GridDataFactory
.fillDefaults().span(1, 1).applyTo(createBranch
);
227 createBranch
.setText(UIText
.FetchGerritChangePage_LocalBranchRadio
);
228 createBranch
.addSelectionListener(new SelectionAdapter() {
230 public void widgetSelected(SelectionEvent e
) {
235 branchCheckoutButton
= new Button(checkoutGroup
, SWT
.CHECK
);
236 GridDataFactory
.fillDefaults().span(2, 1).align(SWT
.END
, SWT
.CENTER
)
237 .applyTo(branchCheckoutButton
);
238 branchCheckoutButton
.setFont(JFaceResources
.getDialogFont());
240 .setText(UIText
.FetchGerritChangePage_LocalBranchCheckout
);
241 branchCheckoutButton
.setSelection(true);
243 branchTextlabel
= new Label(checkoutGroup
, SWT
.NONE
);
244 GridDataFactory
.defaultsFor(branchTextlabel
).exclude(false)
245 .applyTo(branchTextlabel
);
246 branchTextlabel
.setText(UIText
.FetchGerritChangePage_BranchNameText
);
247 branchText
= new Text(checkoutGroup
, SWT
.SINGLE
| SWT
.BORDER
);
248 GridDataFactory
.fillDefaults().grab(true, false).applyTo(branchText
);
249 branchText
.addModifyListener(new ModifyListener() {
251 public void modifyText(ModifyEvent e
) {
256 branchEditButton
= new Button(checkoutGroup
, SWT
.PUSH
);
257 branchEditButton
.setFont(JFaceResources
.getDialogFont());
258 branchEditButton
.setText(UIText
.FetchGerritChangePage_BranchEditButton
);
259 branchEditButton
.addSelectionListener(new SelectionAdapter() {
261 public void widgetSelected(SelectionEvent selectionEvent
) {
262 String txt
= branchText
.getText();
263 String refToMark
= "".equals(txt
) ?
null : Constants
.R_HEADS
+ txt
; //$NON-NLS-1$
264 AbstractBranchSelectionDialog dlg
= new BranchEditDialog(
265 checkoutGroup
.getShell(), repository
, refToMark
);
266 if (dlg
.open() == Window
.OK
) {
267 branchText
.setText(Repository
.shortenRefName(dlg
270 // force calling branchText's modify listeners
271 branchText
.setText(branchText
.getText());
275 GridDataFactory
.defaultsFor(branchEditButton
).exclude(false)
276 .applyTo(branchEditButton
);
279 createTag
= new Button(checkoutGroup
, SWT
.RADIO
);
280 GridDataFactory
.fillDefaults().span(3, 1).applyTo(createTag
);
281 createTag
.setText(UIText
.FetchGerritChangePage_TagRadio
);
282 createTag
.addSelectionListener(new SelectionAdapter() {
284 public void widgetSelected(SelectionEvent e
) {
289 tagTextlabel
= new Label(checkoutGroup
, SWT
.NONE
);
290 GridDataFactory
.defaultsFor(tagTextlabel
).exclude(true)
291 .applyTo(tagTextlabel
);
292 tagTextlabel
.setText(UIText
.FetchGerritChangePage_TagNameText
);
293 tagText
= new Text(checkoutGroup
, SWT
.SINGLE
| SWT
.BORDER
);
294 GridDataFactory
.fillDefaults().exclude(true).grab(true, false)
296 tagText
.addModifyListener(new ModifyListener() {
298 public void modifyText(ModifyEvent e
) {
303 // radio: checkout FETCH_HEAD
304 checkout
= new Button(checkoutGroup
, SWT
.RADIO
);
305 GridDataFactory
.fillDefaults().span(3, 1).applyTo(checkout
);
306 checkout
.setText(UIText
.FetchGerritChangePage_CheckoutRadio
);
307 checkout
.addSelectionListener(new SelectionAdapter() {
309 public void widgetSelected(SelectionEvent e
) {
314 // radio: don't checkout
315 dontCheckout
= new Button(checkoutGroup
, SWT
.RADIO
);
316 GridDataFactory
.fillDefaults().span(3, 1).applyTo(checkout
);
317 dontCheckout
.setText(UIText
.FetchGerritChangePage_UpdateRadio
);
318 dontCheckout
.addSelectionListener(new SelectionAdapter() {
320 public void widgetSelected(SelectionEvent e
) {
325 if ("checkout".equals(defaultCommand
)) //$NON-NLS-1$
326 checkout
.setSelection(true);
328 createBranch
.setSelection(true);
330 warningAdditionalRefNotActive
= new Composite(main
, SWT
.NONE
);
331 GridDataFactory
.fillDefaults().span(2, 1).grab(true, false)
332 .exclude(true).applyTo(warningAdditionalRefNotActive
);
333 warningAdditionalRefNotActive
.setLayout(new GridLayout(2, false));
334 warningAdditionalRefNotActive
.setVisible(false);
336 activateAdditionalRefs
= new Button(warningAdditionalRefNotActive
,
338 activateAdditionalRefs
339 .setText(UIText
.FetchGerritChangePage_ActivateAdditionalRefsButton
);
340 activateAdditionalRefs
341 .setToolTipText(UIText
.FetchGerritChangePage_ActivateAdditionalRefsTooltip
);
343 refText
.addModifyListener(new ModifyListener() {
345 public void modifyText(ModifyEvent e
) {
346 Change change
= Change
.fromRef(refText
.getText());
347 if (change
!= null) {
348 branchText
.setText(NLS
349 .bind(UIText
.FetchGerritChangePage_SuggestedRefNamePattern
,
350 change
.getChangeNumber(),
351 change
.getPatchSetNumber()));
352 tagText
.setText(branchText
.getText());
354 branchText
.setText(""); //$NON-NLS-1$
355 tagText
.setText(""); //$NON-NLS-1$
361 runInBackgroud
= new Button(main
, SWT
.CHECK
);
362 GridDataFactory
.fillDefaults().span(2, 1).align(SWT
.BEGINNING
, SWT
.END
)
364 .applyTo(runInBackgroud
);
365 runInBackgroud
.setText(UIText
.FetchGerritChangePage_RunInBackground
);
367 // get all available URIs from the repository
368 SortedSet
<String
> uris
= new TreeSet
<String
>();
370 for (RemoteConfig rc
: RemoteConfig
.getAllRemoteConfigs(repository
372 if (rc
.getURIs().size() > 0)
373 uris
.add(rc
.getURIs().get(0).toPrivateString());
374 for (URIish u
: rc
.getPushURIs())
375 uris
.add(u
.toPrivateString());
378 } catch (URISyntaxException e
) {
379 Activator
.handleError(e
.getMessage(), e
, false);
380 setErrorMessage(e
.getMessage());
382 for (String aUri
: uris
)
384 if (defaultUri
!= null)
385 uriCombo
.setText(defaultUri
);
388 restoreRunInBackgroundSelection();
390 Dialog
.applyDialogFont(main
);
395 private void storeLastUsedUri(String uri
) {
396 settings
.put(lastUriKey
, uri
.trim());
399 private void selectLastUsedUri() {
400 String lastUri
= settings
.get(lastUriKey
);
401 if (lastUri
!= null) {
402 int i
= uriCombo
.indexOf(lastUri
);
411 private void storeRunInBackgroundSelection() {
412 settings
.put(RUN_IN_BACKGROUND
, runInBackgroud
.getSelection());
415 private void restoreRunInBackgroundSelection() {
416 runInBackgroud
.setSelection(settings
.getBoolean(RUN_IN_BACKGROUND
));
420 public void setVisible(boolean visible
) {
421 super.setVisible(visible
);
422 if (visible
&& refName
!= null)
423 refText
.setText(refName
);
426 private void checkPage() {
427 boolean createBranchSelected
= createBranch
.getSelection();
428 branchText
.setEnabled(createBranchSelected
);
429 branchText
.setVisible(createBranchSelected
);
430 branchTextlabel
.setVisible(createBranchSelected
);
431 branchEditButton
.setVisible(createBranchSelected
);
432 branchCheckoutButton
.setVisible(createBranchSelected
);
433 GridData gd
= (GridData
) branchText
.getLayoutData();
434 gd
.exclude
= !createBranchSelected
;
435 gd
= (GridData
) branchTextlabel
.getLayoutData();
436 gd
.exclude
= !createBranchSelected
;
437 gd
= (GridData
) branchEditButton
.getLayoutData();
438 gd
.exclude
= !createBranchSelected
;
439 gd
= (GridData
) branchCheckoutButton
.getLayoutData();
440 gd
.exclude
= !createBranchSelected
;
442 boolean createTagSelected
= createTag
.getSelection();
443 tagText
.setEnabled(createTagSelected
);
444 tagText
.setVisible(createTagSelected
);
445 tagTextlabel
.setVisible(createTagSelected
);
446 gd
= (GridData
) tagText
.getLayoutData();
447 gd
.exclude
= !createTagSelected
;
448 gd
= (GridData
) tagTextlabel
.getLayoutData();
449 gd
.exclude
= !createTagSelected
;
450 branchText
.getParent().layout(true);
452 boolean showActivateAdditionalRefs
= false;
453 showActivateAdditionalRefs
= (checkout
.getSelection() || dontCheckout
457 .getPreferenceStore()
459 UIPreferences
.RESOURCEHISTORY_SHOW_ADDITIONAL_REFS
);
461 gd
= (GridData
) warningAdditionalRefNotActive
.getLayoutData();
462 gd
.exclude
= !showActivateAdditionalRefs
;
463 warningAdditionalRefNotActive
.setVisible(showActivateAdditionalRefs
);
464 warningAdditionalRefNotActive
.getParent().layout(true);
466 setErrorMessage(null);
468 if (refText
.getText().length() > 0) {
469 Change change
= Change
.fromRef(refText
.getText());
470 if (change
== null) {
471 setErrorMessage(UIText
.FetchGerritChangePage_MissingChangeMessage
);
475 setErrorMessage(UIText
.FetchGerritChangePage_MissingChangeMessage
);
479 if (createBranchSelected
)
480 setErrorMessage(branchValidator
.isValid(branchText
.getText()));
481 else if (createTagSelected
)
482 setErrorMessage(tagValidator
.isValid(tagText
.getText()));
484 setPageComplete(getErrorMessage() == null);
488 private List
<Change
> getRefsForContentAssist()
489 throws InvocationTargetException
, InterruptedException
{
490 if (changeRefs
== null) {
491 final String uriText
= uriCombo
.getText();
492 getWizard().getContainer().run(true, true,
493 new IRunnableWithProgress() {
495 public void run(IProgressMonitor monitor
)
496 throws InvocationTargetException
,
497 InterruptedException
{
498 ListRemoteOperation listOp
;
500 listOp
= new ListRemoteOperation(
505 .getPreferenceStore()
506 .getInt(UIPreferences
.REMOTE_CONNECTION_TIMEOUT
));
507 } catch (URISyntaxException e
) {
508 throw new InvocationTargetException(e
);
512 changeRefs
= new ArrayList
<Change
>();
513 for (Ref ref
: listOp
.getRemoteRefs()) {
514 Change change
= Change
.fromRef(ref
.getName());
516 changeRefs
.add(change
);
518 Collections
.sort(changeRefs
,
519 new Comparator
<Change
>() {
521 public int compare(Change o1
, Change o2
) {
522 // change number descending
523 int changeDiff
= o2
.changeNumber
524 .compareTo(o1
.changeNumber
);
526 // patch set number descending
530 o1
.getPatchSetNumber());
542 final RefSpec spec
= new RefSpec().setSource(refText
.getText())
543 .setDestination(Constants
.FETCH_HEAD
);
544 final String uri
= uriCombo
.getText();
545 final boolean doCheckout
= checkout
.getSelection();
546 final boolean doCreateTag
= createTag
.getSelection();
547 final boolean doCreateBranch
= createBranch
.getSelection();
548 final boolean doCheckoutNewBranch
= branchCheckoutButton
.getSelection();
549 final boolean doActivateAdditionalRefs
= (checkout
.getSelection() || dontCheckout
550 .getSelection()) && activateAdditionalRefs
.getSelection();
551 final String textForTag
= tagText
.getText();
552 final String textForBranch
= branchText
.getText();
554 storeRunInBackgroundSelection();
556 if (runInBackgroud
.getSelection()) {
557 Job job
= new WorkspaceJob(
558 UIText
.FetchGerritChangePage_GetChangeTaskName
) {
561 public IStatus
runInWorkspace(IProgressMonitor monitor
) {
562 internalDoFetch(spec
, uri
, doCheckout
, doCreateTag
,
563 doCreateBranch
, doCheckoutNewBranch
,
564 doActivateAdditionalRefs
,
565 textForTag
, textForBranch
, monitor
);
566 return org
.eclipse
.core
.runtime
.Status
.OK_STATUS
;
570 public boolean belongsTo(Object family
) {
571 if (JobFamilies
.FETCH
.equals(family
))
573 return super.belongsTo(family
);
581 getWizard().getContainer().run(true, true,
582 new IRunnableWithProgress() {
584 public void run(IProgressMonitor monitor
)
585 throws InvocationTargetException
,
586 InterruptedException
{
588 internalDoFetch(spec
, uri
, doCheckout
,
589 doCreateTag
, doCreateBranch
,
591 doActivateAdditionalRefs
, textForTag
,
592 textForBranch
, monitor
);
593 } catch (RuntimeException e
) {
595 } catch (Exception e
) {
596 throw new InvocationTargetException(e
);
602 } catch (InvocationTargetException e
) {
603 Activator
.handleError(e
.getCause().getMessage(), e
.getCause(),
606 } catch (InterruptedException e
) {
613 private void internalDoFetch(RefSpec spec
, String uri
, boolean doCheckout
,
614 boolean doCreateTag
, boolean doCreateBranch
,
615 boolean doCheckoutNewBranch
,
616 boolean doActivateAdditionalRefs
, String textForTag
,
617 String textForBranch
, IProgressMonitor monitor
) {
622 if (doCreateTag
|| doCreateBranch
)
625 UIText
.FetchGerritChangePage_GetChangeTaskName
,
629 RevCommit commit
= fetchChange(uri
, spec
,
633 createTag(spec
, textForTag
, commit
, monitor
);
636 createBranch(textForBranch
, doCheckoutNewBranch
, commit
, monitor
);
638 if (doCheckout
|| doCreateTag
)
639 checkout(commit
, monitor
);
641 if (doActivateAdditionalRefs
)
642 activateAdditionalRefs();
644 storeLastUsedUri(uri
);
646 } catch (Exception e
) {
647 Activator
.handleError(e
.getMessage(), e
, true);
653 private RevCommit
fetchChange(String uri
, RefSpec spec
,
654 IProgressMonitor monitor
) throws CoreException
, URISyntaxException
,
656 int timeout
= Activator
.getDefault().getPreferenceStore()
657 .getInt(UIPreferences
.REMOTE_CONNECTION_TIMEOUT
);
659 List
<RefSpec
> specs
= new ArrayList
<RefSpec
>(1);
662 String taskName
= NLS
663 .bind(UIText
.FetchGerritChangePage_FetchingTaskName
,
665 monitor
.setTaskName(taskName
);
666 FetchResult fetchRes
= new FetchOperationUI(repository
,
667 new URIish(uri
), specs
, timeout
, false).execute(monitor
);
670 try (RevWalk rw
= new RevWalk(repository
)) {
671 return rw
.parseCommit(
672 fetchRes
.getAdvertisedRef(spec
.getSource()).getObjectId());
676 private void createTag(final RefSpec spec
, final String textForTag
,
677 RevCommit commit
, IProgressMonitor monitor
) throws CoreException
{
678 monitor
.setTaskName(UIText
.FetchGerritChangePage_CreatingTagTaskName
);
679 final TagBuilder tag
= new TagBuilder();
680 PersonIdent personIdent
= new PersonIdent(repository
);
682 tag
.setTag(textForTag
);
683 tag
.setTagger(personIdent
);
684 tag
.setMessage(NLS
.bind(
685 UIText
.FetchGerritChangePage_GeneratedTagMessage
,
687 tag
.setObjectId(commit
);
688 new TagOperation(repository
, tag
, false).execute(monitor
);
692 private void createBranch(final String textForBranch
, boolean doCheckout
,
693 RevCommit commit
, IProgressMonitor monitor
) throws CoreException
,
695 monitor
.setTaskName(UIText
.FetchGerritChangePage_CreatingBranchTaskName
);
696 CreateLocalBranchOperation bop
= new CreateLocalBranchOperation(
697 repository
, textForBranch
, commit
);
698 bop
.execute(monitor
);
701 CheckoutCommand co
= new Git(repository
).checkout();
703 co
.setName(textForBranch
).call();
704 } catch (CheckoutConflictException e
) {
705 final CheckoutResult result
= co
.getResult();
707 if (result
.getStatus() == Status
.CONFLICTS
) {
708 final Shell shell
= getWizard().getContainer().getShell();
710 shell
.getDisplay().asyncExec(new Runnable() {
713 new CheckoutConflictDialog(shell
, repository
,
714 result
.getConflictList()).open();
723 private void checkout(RevCommit commit
, IProgressMonitor monitor
)
724 throws CoreException
{
725 monitor
.setTaskName(UIText
.FetchGerritChangePage_CheckingOutTaskName
);
726 BranchOperationUI
.checkout(repository
, commit
.name()).run(monitor
);
731 private void activateAdditionalRefs() {
732 // do this in the UI thread as it results in a
733 // refresh() on the history page
734 PlatformUI
.getWorkbench().getDisplay().asyncExec(new Runnable() {
739 .getPreferenceStore()
741 UIPreferences
.RESOURCEHISTORY_SHOW_ADDITIONAL_REFS
,
747 private void addRefContentProposalToText(final Text textField
) {
748 KeyStroke stroke
= UIUtils
749 .getKeystrokeOfBestActiveBindingFor(IWorkbenchCommandConstants
.EDIT_CONTENT_ASSIST
);
751 UIUtils
.addBulbDecorator(textField
, NLS
.bind(
752 UIText
.FetchGerritChangePage_ContentAssistTooltip
,
755 IContentProposalProvider cp
= new IContentProposalProvider() {
757 public IContentProposal
[] getProposals(String contents
, int position
) {
758 List
<IContentProposal
> resultList
= new ArrayList
<IContentProposal
>();
760 // make the simplest possible pattern check: allow "*"
761 // for multiple characters
762 String patternString
= contents
;
763 // ignore spaces in the beginning
764 while (patternString
.length() > 0
765 && patternString
.charAt(0) == ' ')
766 patternString
= patternString
.substring(1);
768 // we quote the string as it may contain spaces
769 // and other stuff colliding with the Pattern
770 patternString
= Pattern
.quote(patternString
);
772 patternString
= patternString
.replaceAll("\\x2A", ".*"); //$NON-NLS-1$ //$NON-NLS-2$
774 // make sure we add a (logical) * at the end
775 if (!patternString
.endsWith(".*")) //$NON-NLS-1$
776 patternString
= patternString
+ ".*"; //$NON-NLS-1$
778 // let's compile a case-insensitive pattern (assumes ASCII only)
781 pattern
= Pattern
.compile(patternString
,
782 Pattern
.CASE_INSENSITIVE
);
783 } catch (PatternSyntaxException e
) {
787 List
<Change
> proposals
;
789 proposals
= getRefsForContentAssist();
790 } catch (InvocationTargetException e
) {
791 Activator
.handleError(e
.getMessage(), e
, false);
793 } catch (InterruptedException e
) {
797 if (proposals
!= null)
798 for (final Change ref
: proposals
) {
801 ref
.getChangeNumber().toString())
804 IContentProposal propsal
= new ChangeContentProposal(
806 resultList
.add(propsal
);
809 return resultList
.toArray(new IContentProposal
[resultList
814 ContentProposalAdapter adapter
= new ContentProposalAdapter(textField
,
815 new TextContentAdapter(), cp
, stroke
, null);
816 // set the acceptance style to always replace the complete content
817 adapter
.setProposalAcceptanceStyle(ContentProposalAdapter
.PROPOSAL_REPLACE
);
820 private final static class Change
{
821 private final String refName
;
823 private final Integer changeNumber
;
825 private final Integer patchSetNumber
;
827 static Change
fromRef(String refName
) {
829 if (!refName
.startsWith("refs/changes/")) //$NON-NLS-1$
831 String
[] tokens
= refName
.substring(13).split("/"); //$NON-NLS-1$
832 if (tokens
.length
!= 3)
834 Integer changeNumber
= Integer
.valueOf(tokens
[1]);
835 Integer patchSetNumber
= Integer
.valueOf(tokens
[2]);
836 return new Change(refName
, changeNumber
, patchSetNumber
);
837 } catch (NumberFormatException e
) {
838 // if we can't parse this, just return null
840 } catch (IndexOutOfBoundsException e
) {
841 // if we can't parse this, just return null
846 private Change(String refName
, Integer changeNumber
,
847 Integer patchSetNumber
) {
848 this.refName
= refName
;
849 this.changeNumber
= changeNumber
;
850 this.patchSetNumber
= patchSetNumber
;
853 public String
getRefName() {
857 public Integer
getChangeNumber() {
861 public Integer
getPatchSetNumber() {
862 return patchSetNumber
;
866 * @see java.lang.Object#toString()
869 public String
toString() {
874 private final static class ChangeContentProposal
implements
876 private final Change myChange
;
878 ChangeContentProposal(Change change
) {
883 public String
getContent() {
884 return myChange
.getRefName();
888 public int getCursorPosition() {
893 public String
getDescription() {
895 UIText
.FetchGerritChangePage_ContentAssistDescription
,
896 myChange
.getPatchSetNumber(), myChange
.getChangeNumber());
900 public String
getLabel() {
902 .bind("{0} - {1}", myChange
.getChangeNumber(), myChange
.getPatchSetNumber()); //$NON-NLS-1$
906 * @see java.lang.Object#toString()
909 public String
toString() {