1 package com.proalpha.pds.gitutils.mylyn;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.Collections;
10 import org.eclipse.core.runtime.FileLocator;
11 import org.eclipse.core.runtime.Path;
12 import org.eclipse.core.runtime.Platform;
13 import org.eclipse.jface.resource.ImageDescriptor;
14 import org.eclipse.jface.wizard.WizardPage;
15 import org.eclipse.jgit.api.Git;
16 import org.eclipse.jgit.api.errors.GitAPIException;
17 import org.eclipse.jgit.lib.Ref;
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.events.SelectionAdapter;
20 import org.eclipse.swt.events.SelectionEvent;
21 import org.eclipse.swt.events.SelectionListener;
22 import org.eclipse.swt.layout.GridData;
23 import org.eclipse.swt.layout.GridLayout;
24 import org.eclipse.swt.widgets.Button;
25 import org.eclipse.swt.widgets.Combo;
26 import org.eclipse.swt.widgets.Composite;
27 import org.eclipse.swt.widgets.Group;
28 import org.eclipse.swt.widgets.Label;
29 import org.eclipse.swt.widgets.Text;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 import com.proalpha.git.util.PaBranchName;
34 import com.proalpha.git.util.PaRepository;
35 import com.proalpha.pds.gitutils.Activator;
51 private static final String BRANCH_TYPE_STORY =
"Story";
52 private static final String BRANCH_TYPE_SUBTASK =
"Sub-task";
53 private static final String BRANCH_TYPE_EPIC =
"Epic";
54 private static final String BRANCH_TYPE_SPRINT =
"Sprint";
57 private Text txtSrcBranch;
58 private Text txtTargetBranch;
59 private Button btnUpdateSrcBranch;
60 private Button btnUpdateTargetBranch;
61 private Button btnEditSrcBranchname;
62 private Button btnEditTargetBranchname;
63 private Combo cmbTargetBranch;
64 private Label lblSrcBranchInfo;
65 private Label lblTargetBranchInfo;
67 private TargetBranchStatus targetBranchStatus;
69 private List<String> serverBranches;
70 private List<String> targetBranchSelection =
new ArrayList<>();
76 private enum TargetBranchStatus {
77 UNKNOWN, LOCAL, REMOTE, MISSING
88 this.settings = settings;
90 setTitle(
"Branch Selection");
91 setMessage(
"Select the branches to checkout or rather create", INFORMATION);
92 URL url = FileLocator.find(Platform.getBundle(
Activator.PLUGIN_ID),
new Path(
"icons/pA-logox72.png"),
93 Collections.emptyMap());
95 setImageDescriptor(ImageDescriptor.createFromURL(url));
99 public void createControl(Composite parent) {
101 Composite container =
new Composite(parent, SWT.NULL);
102 setControl(container);
103 container.setLayout(
new GridLayout(1,
false));
104 container.setBackgroundMode(SWT.INHERIT_DEFAULT);
106 GridData gdGrp =
new GridData(SWT.CENTER, SWT.TOP,
true,
false, 1, 1);
107 gdGrp.heightHint = 303;
108 gdGrp.widthHint = 450;
110 Group grp =
new Group(container, SWT.NONE);
111 grp.setLayoutData(gdGrp);
112 grp.setText(
"Branch settings");
113 grp.setBackgroundMode(SWT.INHERIT_DEFAULT);
115 setSourceBranchSettings(container, grp);
116 setTargetBranchSettings(container, grp);
119 private void setTargetBranchSettings(Composite container, Group grp) {
120 Label lblTargetBranch =
new Label(grp, SWT.WRAP);
121 lblTargetBranch.setText(
"Target");
122 lblTargetBranch.setBounds(10, 123, 60, 15);
125 cmbTargetBranch =
new Combo(grp, SWT.CHECK);
126 cmbTargetBranch.addSelectionListener(
new SelectionListener() {
127 public void widgetSelected(SelectionEvent selectedItem) {
128 String targetBranchSelected =
null;
129 if (selectedItem !=
null) {
130 targetBranchSelected = ((Combo) selectedItem.getSource()).getText();
131 if (targetBranchSelected !=
null) {
133 updateTargetBranchSelection(targetBranchSelected);
139 public void widgetDefaultSelected(SelectionEvent e) {
143 cmbTargetBranch.setBounds(76, 120, 100, 16);
145 txtTargetBranch =
new Text(grp, SWT.BORDER);
146 txtTargetBranch.setBounds(76, 145, 212, 21);
147 txtTargetBranch.setEnabled(
false);
148 txtTargetBranch.setText((settings.getTargetBranch() ==
null) ?
"" : settings.getTargetBranch());
149 txtTargetBranch.addModifyListener(modifyEvent -> {
150 if (txtTargetBranch.getText().length() != 0)
151 settings.setTargetBranch(txtTargetBranch.getText());
152 updateTargetBranchStatus();
153 updateDependentFields();
155 setPageComplete(targetBranchStatus == TargetBranchStatus.LOCAL
156 || targetBranchStatus == TargetBranchStatus.REMOTE || isSourceBranchValid());
159 btnEditTargetBranchname =
new Button(grp, SWT.CHECK);
160 btnEditTargetBranchname.addSelectionListener(
new SelectionAdapter() {
162 public void widgetSelected(SelectionEvent e) {
163 txtTargetBranch.setEnabled(btnEditTargetBranchname.getSelection());
164 if (!btnEditTargetBranchname.getSelection()) {
166 txtTargetBranch.setText(settings.getTargetBranch());
170 btnEditTargetBranchname.setBounds(314, 123, 60, 16);
171 btnEditTargetBranchname.setText(
"modify");
173 btnUpdateTargetBranch =
new Button(grp, SWT.CHECK);
174 btnUpdateTargetBranch.addSelectionListener(
new SelectionAdapter() {
176 public void widgetSelected(SelectionEvent e) {
177 settings.setUpdateTargetBranch(btnUpdateTargetBranch.getSelection());
179 updateDependentFields();
182 btnUpdateTargetBranch.setBounds(384, 123, 60, 16);
183 btnUpdateTargetBranch.setText(
"update");
185 lblTargetBranchInfo =
new Label(grp, SWT.WRAP);
186 lblTargetBranchInfo.setBounds(76, 170, 330, 60);
187 lblTargetBranchInfo.setForeground(container.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
190 private void setSourceBranchSettings(Composite container, Group grp) {
191 Label lblSrcBranch =
new Label(grp, SWT.WRAP);
192 lblSrcBranch.setText(
"Source");
193 lblSrcBranch.setBounds(10, 22, 60, 15);
195 txtSrcBranch =
new Text(grp, SWT.BORDER);
196 txtSrcBranch.setBounds(76, 19, 212, 21);
197 txtSrcBranch.setText((settings.getSourceBranch() ==
null) ?
"" : settings.getSourceBranch());
198 txtSrcBranch.setEnabled(
false);
199 txtSrcBranch.addModifyListener(modifyEvent -> {
200 if (txtSrcBranch.getText().length() != 0)
201 settings.setSourceBranch(txtSrcBranch.getText());
202 updateDependentFields();
203 setPageComplete(targetBranchStatus == TargetBranchStatus.LOCAL
204 || targetBranchStatus == TargetBranchStatus.REMOTE || isSourceBranchValid());
207 btnEditSrcBranchname =
new Button(grp, SWT.CHECK);
208 btnEditSrcBranchname.addSelectionListener(
new SelectionAdapter() {
210 public void widgetSelected(SelectionEvent e) {
211 txtSrcBranch.setEnabled(btnEditSrcBranchname.getSelection());
212 if (!btnEditSrcBranchname.getSelection()) {
214 txtSrcBranch.setText(settings.getSourceBranch());
218 btnEditSrcBranchname.setBounds(314, 22, 60, 16);
219 btnEditSrcBranchname.setText(
"modify");
221 btnUpdateSrcBranch =
new Button(grp, SWT.CHECK);
222 btnUpdateSrcBranch.addSelectionListener(
new SelectionAdapter() {
224 public void widgetSelected(SelectionEvent e) {
225 settings.setUpdateSourceBranch(btnUpdateSrcBranch.getSelection());
226 updateDependentFields();
229 btnUpdateSrcBranch.setBounds(384, 22, 60, 16);
230 btnUpdateSrcBranch.setText(
"update");
232 lblSrcBranchInfo =
new Label(grp, SWT.WRAP);
233 lblSrcBranchInfo.setBounds(76, 49, 330, 60);
234 lblSrcBranchInfo.setForeground(container.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
238 public void setVisible(
boolean visible) {
239 super.setVisible(visible);
252 private void initialize() {
253 serverBranches = getBranchesFromServer();
254 updateTargetBranchStatus();
256 txtSrcBranch.setText((settings.getSourceBranch() ==
null) ?
"" : settings.getSourceBranch());
258 btnUpdateSrcBranch.setSelection(settings.isUpdateSourceBranch());
259 btnUpdateTargetBranch.setSelection(settings.isUpdateTargetBranch());
261 targetBranchSelection.clear();
263 if (!settings.getTask().getTaskKind().isEmpty() && settings.getTask().getTaskKind().equals(BRANCH_TYPE_SUBTASK))
264 targetBranchSelection.add(BRANCH_TYPE_SUBTASK);
265 targetBranchSelection.add(BRANCH_TYPE_STORY);
266 if (!settings.getTaskEpic().isEmpty())
267 targetBranchSelection.add(BRANCH_TYPE_EPIC);
268 if (!settings.getTaskSprint().isEmpty())
269 targetBranchSelection.add(BRANCH_TYPE_SPRINT);
270 cmbTargetBranch.setItems(targetBranchSelection.stream().toArray(String[]::
new));
271 cmbTargetBranch.setText(BRANCH_TYPE_STORY);
272 updateTargetBranchSelection(BRANCH_TYPE_STORY);
278 private void updateDependentFields() {
279 StringBuilder sb =
new StringBuilder();
281 for (String s : getSourceBranchInfo()) {
286 lblSrcBranchInfo.setText(sb.toString());
288 sb =
new StringBuilder();
289 for (String s : getTargetBranchInfo()) {
294 lblTargetBranchInfo.setText(sb.toString());
303 private boolean isSourceBranchValid() {
304 if (this.settings ==
null)
307 return PaRepository.getLocalBranches(this.settings.getRepository()).contains(this.settings.getSourceBranch());
314 private void updateTargetBranchSelection(String selectedBranchValue) {
316 switch (selectedBranchValue) {
318 case BRANCH_TYPE_SUBTASK:
322 case BRANCH_TYPE_STORY:
323 if (settings.getTask().getTaskKind().equals(BRANCH_TYPE_SUBTASK))
329 case BRANCH_TYPE_EPIC:
333 case BRANCH_TYPE_SPRINT:
338 txtTargetBranch.setText(settings.getTargetBranch());
341 txtTargetBranch.setText(settings.getTargetBranch());
343 updateTargetBranchStatus();
344 updateDependentFields();
346 setPageComplete(targetBranchStatus == TargetBranchStatus.LOCAL
347 || targetBranchStatus == TargetBranchStatus.REMOTE || isSourceBranchValid());
354 private void updateTargetBranchStatus() {
355 if (this.settings.getRepository() ==
null)
356 this.targetBranchStatus = TargetBranchStatus.UNKNOWN;
359 if (PaRepository.isValidRef(
this.settings.getRepository(), settings.getTargetBranch()) && PaRepository
360 .getLocalBranches(
this.settings.getRepository()).contains(
this.settings.getTargetBranch())) {
361 this.targetBranchStatus = TargetBranchStatus.LOCAL;
364 if (PaRepository.getRemoteBranches(
this.settings.getRepository()).contains(
this.settings.getTargetBranch())
365 ||
this.serverBranches.contains(
this.settings.getTargetBranch()))
366 this.targetBranchStatus = TargetBranchStatus.REMOTE;
369 this.targetBranchStatus = TargetBranchStatus.MISSING;
380 private List<String> getSourceBranchInfo() {
381 List<String> infos =
new ArrayList<>();
383 if (!isSourceBranchValid()) {
384 infos.add(
"The source branch does not exist!");
388 if (this.targetBranchStatus == TargetBranchStatus.LOCAL
389 ||
this.targetBranchStatus == TargetBranchStatus.REMOTE) {
390 infos.add(
"The source branch will not be used, because the target branch exists.");
394 else if (this.targetBranchStatus == TargetBranchStatus.MISSING) {
395 infos.add(
"The source branch will be branched off.");
397 if (!settings.isUpdateSourceBranch()) {
399 "Warning: Your new target branch is probably not based on the newest version of the source branch.");
412 private List<String> getTargetBranchInfo() {
413 List<String> infos =
new ArrayList<>();
415 if (this.targetBranchStatus == TargetBranchStatus.UNKNOWN)
419 if (this.targetBranchStatus == TargetBranchStatus.LOCAL) {
420 infos.add(
"The target branch already exists in the local repository and will be checked out.");
422 if (!settings.isUpdateTargetBranch()) {
423 infos.add(
"Warning: The target branch will not be updated. It is probably outdated.");
427 if (this.targetBranchStatus == TargetBranchStatus.REMOTE)
428 infos.add(
"The target branch already exists on server and will be fetched/checked out.");
431 infos.add(
"The target branch does not exist and will be created.");
451 private List<String> getBranchesFromServer() {
453 List<String> branches =
new ArrayList<>();
457 Set<String> remotes = this.settings.getRepository().getRemoteNames();
458 if (remotes.iterator().hasNext()) {
459 remote = remotes.iterator().next();
460 String url = this.settings.getRepository().getConfig().getString(
"remote", remote,
"url");
461 Collection<Ref> refs = Git.lsRemoteRepository().setRemote(url).setHeads(
true).call();
463 for (Ref ref : refs) {
464 branches.add(PaBranchName.getShortBranchName(ref.getName(),
this.settings.getRepository()));
467 }
catch (GitAPIException e) {
468 logger.error(
"InvalidRemoteException occured", e);
void deriveDefaultSourceBranch()
void deriveTargetBranch(String branchSuffix)
void deriveDefaultTargetBranch()
SelectBranchesPage(FeatureBranchSettings settings)