Use try-with-resource to avoid leaks with RevWalk and TreeWalk
[egit/eclipse.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / internal / actions / SynchronizeWithMenu.java
blob846e7cefee68346296d78614443e93a01a0faa3d
1 /*******************************************************************************
2 * Copyright (C) 2011, 2015 Dariusz Luksza <dariusz@luksza.org> and others.
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
9 package org.eclipse.egit.ui.internal.actions;
11 import static org.eclipse.jgit.lib.Constants.HEAD;
12 import static org.eclipse.jgit.lib.Constants.R_REFS;
13 import static org.eclipse.jgit.lib.Constants.R_TAGS;
15 import java.io.IOException;
16 import java.util.Collections;
17 import java.util.HashSet;
18 import java.util.LinkedList;
19 import java.util.List;
21 import org.eclipse.core.resources.IProject;
22 import org.eclipse.core.resources.IResource;
23 import org.eclipse.core.runtime.IAdaptable;
24 import org.eclipse.egit.core.project.RepositoryMapping;
25 import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData;
26 import org.eclipse.egit.ui.Activator;
27 import org.eclipse.egit.ui.internal.CommonUtils;
28 import org.eclipse.egit.ui.internal.UIIcons;
29 import org.eclipse.egit.ui.internal.UIText;
30 import org.eclipse.egit.ui.internal.synchronize.GitModelSynchronize;
31 import org.eclipse.egit.ui.internal.synchronize.GitSynchronizeWizard;
32 import org.eclipse.jface.action.ContributionItem;
33 import org.eclipse.jface.viewers.ISelection;
34 import org.eclipse.jface.viewers.IStructuredSelection;
35 import org.eclipse.jface.wizard.WizardDialog;
36 import org.eclipse.jgit.lib.Constants;
37 import org.eclipse.jgit.lib.ObjectIdRef.PeeledTag;
38 import org.eclipse.jgit.lib.Ref;
39 import org.eclipse.jgit.lib.RefDatabase;
40 import org.eclipse.jgit.lib.Repository;
41 import org.eclipse.jgit.revwalk.RevCommit;
42 import org.eclipse.jgit.revwalk.RevTag;
43 import org.eclipse.jgit.revwalk.RevWalk;
44 import org.eclipse.swt.SWT;
45 import org.eclipse.swt.events.SelectionAdapter;
46 import org.eclipse.swt.events.SelectionEvent;
47 import org.eclipse.swt.graphics.Image;
48 import org.eclipse.swt.widgets.Menu;
49 import org.eclipse.swt.widgets.MenuItem;
50 import org.eclipse.ui.ISelectionService;
51 import org.eclipse.ui.menus.IWorkbenchContribution;
52 import org.eclipse.ui.services.IServiceLocator;
54 /**
55 * Dynamic sub menu under Team > Synchronize
57 public class SynchronizeWithMenu extends ContributionItem implements
58 IWorkbenchContribution {
60 /** the maximum number of refs to show in the sub-menu */
61 private static final int MAX_NUM_MENU_ENTRIES = 20;
63 private final Image tagImage;
65 private final Image branchImage;
67 private ISelectionService srv;
69 /**
72 public SynchronizeWithMenu() {
73 this(null);
76 /**
77 * @param id
79 public SynchronizeWithMenu(String id) {
80 super(id);
82 tagImage = UIIcons.TAG.createImage();
83 branchImage = UIIcons.BRANCH.createImage();
86 @Override
87 public void fill(final Menu menu, int index) {
88 if (srv == null)
89 return;
90 final IResource selectedResource = getSelection();
91 if (selectedResource == null || selectedResource.isLinked(IResource.CHECK_ANCESTORS))
92 return;
94 RepositoryMapping mapping = RepositoryMapping
95 .getMapping(selectedResource.getProject());
96 if (mapping == null)
97 return;
99 final Repository repo = mapping.getRepository();
100 if (repo == null)
101 return;
103 List<Ref> refs = new LinkedList<Ref>();
104 RefDatabase refDatabase = repo.getRefDatabase();
105 try {
106 refs.addAll(refDatabase.getAdditionalRefs());
107 } catch (IOException e) {
108 // do nothing
110 try {
111 refs.addAll(refDatabase.getRefs(RefDatabase.ALL).values());
112 } catch (IOException e) {
113 // do nothing
115 Collections.sort(refs, CommonUtils.REF_ASCENDING_COMPARATOR);
116 String currentBranch;
117 try {
118 currentBranch = repo.getFullBranch();
119 } catch (IOException e) {
120 currentBranch = ""; //$NON-NLS-1$
123 int count = 0;
124 String oldName = null;
125 int refsLength = R_REFS.length();
126 int tagsLength = R_TAGS.substring(refsLength).length();
127 for (Ref ref : refs) {
128 final String name = ref.getName();
129 if (name.equals(Constants.HEAD) || name.equals(currentBranch) || excludeTag(ref, repo))
130 continue;
131 if (name.startsWith(R_REFS) && oldName != null
132 && !oldName.regionMatches(refsLength, name, refsLength,
133 tagsLength))
134 new MenuItem(menu, SWT.SEPARATOR);
136 MenuItem item = new MenuItem(menu, SWT.PUSH);
137 item.setText(name);
138 if (name.startsWith(Constants.R_TAGS))
139 item.setImage(tagImage);
140 else if (name.startsWith(Constants.R_HEADS) || name.startsWith(Constants.R_REMOTES))
141 item.setImage(branchImage);
143 item.addSelectionListener(new SelectionAdapter() {
144 @Override
145 public void widgetSelected(SelectionEvent event) {
146 GitSynchronizeData data;
147 try {
148 data = new GitSynchronizeData(repo, HEAD, name, true);
149 if (!(selectedResource instanceof IProject)) {
150 HashSet<IResource> resources = new HashSet<IResource>();
151 resources.add(selectedResource);
152 data.setIncludedResources(resources);
155 GitModelSynchronize.launch(data, new IResource[] { selectedResource });
156 } catch (IOException e) {
157 Activator.logError(e.getMessage(), e);
162 if (++count == MAX_NUM_MENU_ENTRIES)
163 break;
164 oldName = name;
167 if (count > 1)
168 new MenuItem(menu, SWT.SEPARATOR);
170 MenuItem custom = new MenuItem(menu, SWT.PUSH);
171 custom.setText(UIText.SynchronizeWithMenu_custom);
172 custom.addSelectionListener(new SelectionAdapter() {
173 @Override
174 public void widgetSelected(SelectionEvent e) {
175 GitSynchronizeWizard gitWizard = new GitSynchronizeWizard();
176 WizardDialog wizard = new WizardDialog(menu.getShell(),
177 gitWizard);
178 wizard.create();
179 wizard.open();
184 @Override
185 public void initialize(IServiceLocator serviceLocator) {
186 srv = CommonUtils.getService(serviceLocator, ISelectionService.class);
189 @Override
190 public boolean isDynamic() {
191 return true;
193 @Override
194 public void dispose() {
195 tagImage.dispose();
196 branchImage.dispose();
199 private IResource getSelection() {
200 ISelection sel = srv.getSelection();
202 if (!(sel instanceof IStructuredSelection))
203 return null;
205 Object selected = ((IStructuredSelection) sel).getFirstElement();
206 if (selected instanceof IAdaptable)
207 return CommonUtils.getAdapter(((IAdaptable) selected), IResource.class);
209 if (selected instanceof IResource)
210 return (IResource) selected;
212 return null;
215 private boolean excludeTag(Ref ref, Repository repo) {
216 if (ref instanceof PeeledTag) {
217 RevWalk rw = new RevWalk(repo);
218 try {
219 RevTag tag = rw.parseTag(ref.getObjectId());
221 return !(rw.parseAny(tag.getObject()) instanceof RevCommit);
222 } catch (IOException e) {
223 Activator.logError(e.getMessage(), e);
224 } finally {
225 rw.close();
226 rw.dispose();
230 return false;