Fix sharing projects
[egit.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / internal / sharing / ExistingOrNewPage.java
blob62e8f73d8e6a28821e5e76e581c18757abafa664
1 /*******************************************************************************
2 * Copyright (C) 2009, Robin Rosenberg
3 * Copyright (C) 2009, Mykola Nikishov <mn@mn.com.ua>
5 * All rights reserved. This program and the accompanying materials
6 * are made available under the terms of the Eclipse Public License v1.0
7 * which accompanies this distribution, and is available at
8 * http://www.eclipse.org/legal/epl-v10.html
9 *******************************************************************************/
10 package org.eclipse.egit.ui.internal.sharing;
12 import java.io.File;
13 import java.io.IOException;
14 import java.util.Collection;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.Iterator;
18 import java.util.Map;
19 import java.util.Set;
21 import org.eclipse.core.resources.IProject;
22 import org.eclipse.core.resources.IResource;
23 import org.eclipse.core.runtime.CoreException;
24 import org.eclipse.core.runtime.IPath;
25 import org.eclipse.core.runtime.NullProgressMonitor;
26 import org.eclipse.core.runtime.Path;
27 import org.eclipse.egit.core.Activator;
28 import org.eclipse.egit.core.project.RepositoryFinder;
29 import org.eclipse.egit.core.project.RepositoryMapping;
30 import org.eclipse.egit.ui.UIIcons;
31 import org.eclipse.egit.ui.UIText;
32 import org.eclipse.jface.dialogs.MessageDialog;
33 import org.eclipse.jface.layout.GridDataFactory;
34 import org.eclipse.jface.wizard.WizardPage;
35 import org.eclipse.jgit.lib.Constants;
36 import org.eclipse.jgit.lib.Repository;
37 import org.eclipse.swt.SWT;
38 import org.eclipse.swt.events.SelectionAdapter;
39 import org.eclipse.swt.events.SelectionEvent;
40 import org.eclipse.swt.events.SelectionListener;
41 import org.eclipse.swt.layout.GridLayout;
42 import org.eclipse.swt.widgets.Button;
43 import org.eclipse.swt.widgets.Composite;
44 import org.eclipse.swt.widgets.Event;
45 import org.eclipse.swt.widgets.Group;
46 import org.eclipse.swt.widgets.Listener;
47 import org.eclipse.swt.widgets.Text;
48 import org.eclipse.swt.widgets.Tree;
49 import org.eclipse.swt.widgets.TreeColumn;
50 import org.eclipse.swt.widgets.TreeItem;
52 /**
53 * Wizard page for connecting projects to Git repositories.
55 class ExistingOrNewPage extends WizardPage {
57 private final SharingWizard myWizard;
58 private Button button;
59 private Tree tree;
60 private Text repositoryToCreate;
61 private IPath minumumPath;
62 private Text dotGitSegment;
64 ExistingOrNewPage(SharingWizard w) {
65 super(ExistingOrNewPage.class.getName());
66 setTitle(UIText.ExistingOrNewPage_title);
67 setDescription(UIText.ExistingOrNewPage_description);
68 setImageDescriptor(UIIcons.WIZBAN_CONNECT_REPO);
69 this.myWizard = w;
72 public void createControl(Composite parent) {
73 Group g = new Group(parent, SWT.NONE);
74 g.setLayout(new GridLayout(3,false));
75 g.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
76 tree = new Tree(g, SWT.BORDER|SWT.MULTI|SWT.FULL_SELECTION);
77 tree.setHeaderVisible(true);
78 tree.setLayout(new GridLayout());
79 tree.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).span(3,1).create());
80 tree.addSelectionListener(new SelectionAdapter() {
82 public void widgetSelected(SelectionEvent e) {
83 TreeItem t = (TreeItem) e.item;
84 for(TreeItem ti : t.getItems())
85 tree.deselect(ti);
86 if (t.getParentItem() != null) {
87 tree.deselect(t.getParentItem());
88 for(TreeItem ti : t.getParentItem().getItems())
89 if (ti != t)
90 tree.deselect(ti);
92 Set<IProject> projects = new HashSet<IProject>();
93 for (TreeItem treeItem : tree.getSelection()) {
94 if (treeItem.getData() == null && treeItem.getParentItem() != null) {
95 treeItem = treeItem.getParentItem();
97 final IProject project = (IProject) treeItem.getData();
98 if (projects.contains(project))
99 tree.deselect(treeItem);
100 projects.add(project);
104 TreeColumn c1 = new TreeColumn(tree,SWT.NONE);
105 c1.setText(UIText.ExistingOrNewPage_HeaderProject);
106 c1.setWidth(100);
107 TreeColumn c2 = new TreeColumn(tree,SWT.NONE);
108 c2.setText(UIText.ExistingOrNewPage_HeaderPath);
109 c2.setWidth(400);
110 TreeColumn c3 = new TreeColumn(tree,SWT.NONE);
111 c3.setText(UIText.ExistingOrNewPage_HeaderRepository);
112 c3.setWidth(200);
113 for (IProject project : myWizard.projects) {
114 TreeItem treeItem = new TreeItem(tree, SWT.NONE);
115 treeItem.setData(project);
116 treeItem.setText(0, project.getName());
117 treeItem.setText(1, project.getLocation().toOSString());
118 RepositoryFinder repositoryFinder = new RepositoryFinder(project);
119 Collection<RepositoryMapping> mappings;
120 try {
121 mappings = repositoryFinder.find(new NullProgressMonitor());
122 Iterator<RepositoryMapping> mi = mappings.iterator();
123 RepositoryMapping m = mi.hasNext() ? mi.next() : null;
124 if (m == null) {
125 // no mapping found, enable repository creation
126 treeItem.setText(2, ""); //$NON-NLS-1$
127 } else {
128 // at least one mapping found
129 fillTreeItemWithGitDirectory(m, treeItem, false);
132 while (mi.hasNext()) { // fill in additional mappings
133 m = mi.next();
134 TreeItem treeItem2 = new TreeItem(treeItem, SWT.NONE);
135 treeItem2.setData(m.getContainer().getProject());
136 fillTreeItemWithGitDirectory(m, treeItem2, true);
138 } catch (CoreException e) {
139 TreeItem treeItem2 = new TreeItem(treeItem, SWT.BOLD|SWT.ITALIC);
140 treeItem2.setText(e.getMessage());
144 button = new Button(g, SWT.PUSH);
145 button.setLayoutData(GridDataFactory.fillDefaults().create());
146 button.setText(UIText.ExistingOrNewPage_CreateButton);
147 button.addSelectionListener(new SelectionListener() {
148 public void widgetSelected(SelectionEvent e) {
149 File gitDir = new File(repositoryToCreate.getText(),Constants.DOT_GIT);
150 try {
151 Repository repository = new Repository(gitDir);
152 repository.create();
153 for (IProject project : getProjects().keySet()) {
154 // If we don't refresh the project directories right
155 // now we won't later know that a .git directory
156 // exists within it and we won't mark the .git
157 // directory as a team-private member. Failure
158 // to do so might allow someone to delete
159 // the .git directory without us stopping them.
160 // (Half lie, we should optimize so we do not
161 // refresh when the .git is not within the project)
163 if (!gitDir.toString().contains("..")) //$NON-NLS-1$
164 project.refreshLocal(IResource.DEPTH_ONE,
165 new NullProgressMonitor());
167 } catch (IOException e1) {
168 MessageDialog.openError(getShell(), UIText.ExistingOrNewPage_ErrorFailedToCreateRepository, gitDir.toString() + ":\n" + e1.getMessage()); //$NON-NLS-1$
169 Activator.logError("Failed to create repository at " + gitDir, e1); //$NON-NLS-1$
170 } catch (CoreException e2) {
171 Activator.logError(UIText.ExistingOrNewPage_ErrorFailedToRefreshRepository + gitDir, e2);
173 for (TreeItem ti : tree.getSelection()) {
174 ti.setText(2, gitDir.toString());
176 updateCreateOptions();
177 getContainer().updateButtons();
179 public void widgetDefaultSelected(SelectionEvent e) {
182 repositoryToCreate = new Text(g, SWT.SINGLE | SWT.BORDER);
183 repositoryToCreate.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).span(1,1).create());
184 repositoryToCreate.addListener(SWT.Modify, new Listener() {
185 public void handleEvent(Event e) {
186 if (e.text == null)
187 return;
188 IPath fromOSString = Path.fromOSString(e.text);
189 button.setEnabled(minumumPath
190 .matchingFirstSegments(fromOSString) == fromOSString
191 .segmentCount());
194 dotGitSegment = new Text(g ,SWT.NONE);
195 dotGitSegment.setEnabled(false);
196 dotGitSegment.setEditable(false);
197 dotGitSegment.setText(File.separatorChar + Constants.DOT_GIT);
198 dotGitSegment.setLayoutData(GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.CENTER).create());
200 tree.addSelectionListener(new SelectionListener() {
201 public void widgetSelected(SelectionEvent e) {
202 updateCreateOptions();
204 public void widgetDefaultSelected(SelectionEvent e) {
205 // Empty
208 updateCreateOptions();
209 setControl(g);
212 private void fillTreeItemWithGitDirectory(RepositoryMapping m, TreeItem treeItem2, boolean isAlternative) {
213 if (m.getGitDir() == null)
214 treeItem2.setText(2, UIText.ExistingOrNewPage_SymbolicValueEmptyMapping);
215 else {
216 IPath container = m.getContainerPath();
217 if (!container.isEmpty())
218 container = container.addTrailingSeparator();
219 IPath relativePath = container.append(m.getGitDir());
220 if (isAlternative)
221 treeItem2.setText(0, relativePath.removeLastSegments(1).addTrailingSeparator().toString());
222 treeItem2.setText(2, relativePath.toString());
226 private void updateCreateOptions() {
227 minumumPath = null;
228 IPath p = null;
229 for (TreeItem ti : tree.getSelection()) {
230 String path = ti.getText(2);
231 if (!path.equals("")) { //$NON-NLS-1$
232 p = null;
233 break;
235 String gitDirParentCandidate = ti.getText(1);
236 IPath thisPath = Path.fromOSString(gitDirParentCandidate);
237 if (p == null)
238 p = thisPath;
239 else {
240 int n = p.matchingFirstSegments(thisPath);
241 p = p.removeLastSegments(p.segmentCount() - n);
244 minumumPath = p;
245 if (p != null) {
246 repositoryToCreate.setText(p.toOSString());
247 } else {
248 repositoryToCreate.setText(""); //$NON-NLS-1$
250 button.setEnabled(p != null);
251 repositoryToCreate.setEnabled(p != null);
252 dotGitSegment.setEnabled(p != null);
253 getContainer().updateButtons();
256 @Override
257 public boolean isPageComplete() {
258 if (tree.getSelectionCount() == 0)
259 return false;
260 for (TreeItem ti : tree.getSelection()) {
261 String path = ti.getText(2);
262 if (path.equals("")) { //$NON-NLS-1$
263 return false;
266 return true;
270 * @return map between project and repository root directory (converted to an
271 * absolute path) for all projects selected by user
273 public Map<IProject, File> getProjects() {
274 final TreeItem[] selection = tree.getSelection();
275 Map<IProject, File> ret = new HashMap<IProject, File>(selection.length);
276 for (int i = 0; i < selection.length; ++i) {
277 TreeItem treeItem = selection[i];
278 while (treeItem.getData() == null && treeItem.getParentItem() != null) {
279 treeItem = treeItem.getParentItem();
282 final IProject project = (IProject) treeItem.getData();
283 final IPath selectedRepo = Path.fromOSString(treeItem.getText(2));
284 IPath localPathToRepo = selectedRepo;
285 if (!selectedRepo.isAbsolute()) {
286 localPathToRepo = project.getLocation().append(selectedRepo);
288 ret.put(project, localPathToRepo.toFile());
290 return ret;