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
;
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
;
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
;
53 * Wizard page for connecting projects to Git repositories.
55 class ExistingOrNewPage
extends WizardPage
{
57 private final SharingWizard myWizard
;
58 private Button button
;
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
);
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())
86 if (t
.getParentItem() != null) {
87 tree
.deselect(t
.getParentItem());
88 for(TreeItem ti
: t
.getParentItem().getItems())
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
);
107 TreeColumn c2
= new TreeColumn(tree
,SWT
.NONE
);
108 c2
.setText(UIText
.ExistingOrNewPage_HeaderPath
);
110 TreeColumn c3
= new TreeColumn(tree
,SWT
.NONE
);
111 c3
.setText(UIText
.ExistingOrNewPage_HeaderRepository
);
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
;
121 mappings
= repositoryFinder
.find(new NullProgressMonitor());
122 Iterator
<RepositoryMapping
> mi
= mappings
.iterator();
123 RepositoryMapping m
= mi
.hasNext() ? mi
.next() : null;
125 // no mapping found, enable repository creation
126 treeItem
.setText(2, ""); //$NON-NLS-1$
128 // at least one mapping found
129 fillTreeItemWithGitDirectory(m
, treeItem
, false);
132 while (mi
.hasNext()) { // fill in additional mappings
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
);
151 Repository repository
= new Repository(gitDir
);
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
) {
188 IPath fromOSString
= Path
.fromOSString(e
.text
);
189 button
.setEnabled(minumumPath
190 .matchingFirstSegments(fromOSString
) == fromOSString
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
) {
208 updateCreateOptions();
212 private void fillTreeItemWithGitDirectory(RepositoryMapping m
, TreeItem treeItem2
, boolean isAlternative
) {
213 if (m
.getGitDir() == null)
214 treeItem2
.setText(2, UIText
.ExistingOrNewPage_SymbolicValueEmptyMapping
);
216 IPath container
= m
.getContainerPath();
217 if (!container
.isEmpty())
218 container
= container
.addTrailingSeparator();
219 IPath relativePath
= container
.append(m
.getGitDir());
221 treeItem2
.setText(0, relativePath
.removeLastSegments(1).addTrailingSeparator().toString());
222 treeItem2
.setText(2, relativePath
.toString());
226 private void updateCreateOptions() {
229 for (TreeItem ti
: tree
.getSelection()) {
230 String path
= ti
.getText(2);
231 if (!path
.equals("")) { //$NON-NLS-1$
235 String gitDirParentCandidate
= ti
.getText(1);
236 IPath thisPath
= Path
.fromOSString(gitDirParentCandidate
);
240 int n
= p
.matchingFirstSegments(thisPath
);
241 p
= p
.removeLastSegments(p
.segmentCount() - n
);
246 repositoryToCreate
.setText(p
.toOSString());
248 repositoryToCreate
.setText(""); //$NON-NLS-1$
250 button
.setEnabled(p
!= null);
251 repositoryToCreate
.setEnabled(p
!= null);
252 dotGitSegment
.setEnabled(p
!= null);
253 getContainer().updateButtons();
257 public boolean isPageComplete() {
258 if (tree
.getSelectionCount() == 0)
260 for (TreeItem ti
: tree
.getSelection()) {
261 String path
= ti
.getText(2);
262 if (path
.equals("")) { //$NON-NLS-1$
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());