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
.project
.RepositoryFinder
;
28 import org
.eclipse
.egit
.core
.project
.RepositoryMapping
;
29 import org
.eclipse
.egit
.ui
.UIIcons
;
30 import org
.eclipse
.egit
.ui
.UIText
;
31 import org
.eclipse
.jface
.layout
.GridDataFactory
;
32 import org
.eclipse
.jface
.wizard
.WizardPage
;
33 import org
.eclipse
.jgit
.lib
.Constants
;
34 import org
.eclipse
.jgit
.lib
.Repository
;
35 import org
.eclipse
.osgi
.util
.NLS
;
36 import org
.eclipse
.swt
.SWT
;
37 import org
.eclipse
.swt
.events
.SelectionAdapter
;
38 import org
.eclipse
.swt
.events
.SelectionEvent
;
39 import org
.eclipse
.swt
.events
.SelectionListener
;
40 import org
.eclipse
.swt
.layout
.GridLayout
;
41 import org
.eclipse
.swt
.widgets
.Button
;
42 import org
.eclipse
.swt
.widgets
.Composite
;
43 import org
.eclipse
.swt
.widgets
.Event
;
44 import org
.eclipse
.swt
.widgets
.Group
;
45 import org
.eclipse
.swt
.widgets
.Listener
;
46 import org
.eclipse
.swt
.widgets
.Text
;
47 import org
.eclipse
.swt
.widgets
.Tree
;
48 import org
.eclipse
.swt
.widgets
.TreeColumn
;
49 import org
.eclipse
.swt
.widgets
.TreeItem
;
52 * Wizard page for connecting projects to Git repositories.
54 class ExistingOrNewPage
extends WizardPage
{
56 private final SharingWizard myWizard
;
57 private Button button
;
59 private Text repositoryToCreate
;
60 private IPath minumumPath
;
61 private Text dotGitSegment
;
63 ExistingOrNewPage(SharingWizard w
) {
64 super(ExistingOrNewPage
.class.getName());
65 setTitle(UIText
.ExistingOrNewPage_title
);
66 setDescription(UIText
.ExistingOrNewPage_description
);
67 setImageDescriptor(UIIcons
.WIZBAN_CONNECT_REPO
);
71 public void createControl(Composite parent
) {
72 Group g
= new Group(parent
, SWT
.NONE
);
73 g
.setLayout(new GridLayout(3,false));
74 g
.setLayoutData(GridDataFactory
.fillDefaults().grab(true, true).create());
75 tree
= new Tree(g
, SWT
.BORDER
|SWT
.MULTI
|SWT
.FULL_SELECTION
);
76 tree
.setHeaderVisible(true);
77 tree
.setLayout(new GridLayout());
78 tree
.setLayoutData(GridDataFactory
.fillDefaults().grab(true, true).span(3,1).create());
79 tree
.addSelectionListener(new SelectionAdapter() {
81 public void widgetSelected(SelectionEvent e
) {
82 TreeItem t
= (TreeItem
) e
.item
;
83 for(TreeItem ti
: t
.getItems())
85 if (t
.getParentItem() != null) {
86 tree
.deselect(t
.getParentItem());
87 for(TreeItem ti
: t
.getParentItem().getItems())
91 Set
<IProject
> projects
= new HashSet
<IProject
>();
92 for (TreeItem treeItem
: tree
.getSelection()) {
93 if (treeItem
.getData() == null && treeItem
.getParentItem() != null) {
94 treeItem
= treeItem
.getParentItem();
96 final IProject project
= (IProject
) treeItem
.getData();
97 if (projects
.contains(project
))
98 tree
.deselect(treeItem
);
99 projects
.add(project
);
103 TreeColumn c1
= new TreeColumn(tree
,SWT
.NONE
);
104 c1
.setText(UIText
.ExistingOrNewPage_HeaderProject
);
106 TreeColumn c2
= new TreeColumn(tree
,SWT
.NONE
);
107 c2
.setText(UIText
.ExistingOrNewPage_HeaderPath
);
109 TreeColumn c3
= new TreeColumn(tree
,SWT
.NONE
);
110 c3
.setText(UIText
.ExistingOrNewPage_HeaderRepository
);
112 for (IProject project
: myWizard
.projects
) {
113 TreeItem treeItem
= new TreeItem(tree
, SWT
.NONE
);
114 treeItem
.setData(project
);
115 treeItem
.setText(0, project
.getName());
116 treeItem
.setText(1, project
.getLocation().toOSString());
117 RepositoryFinder repositoryFinder
= new RepositoryFinder(project
);
118 Collection
<RepositoryMapping
> mappings
;
120 mappings
= repositoryFinder
.find(new NullProgressMonitor());
121 Iterator
<RepositoryMapping
> mi
= mappings
.iterator();
122 RepositoryMapping m
= mi
.hasNext() ? mi
.next() : null;
124 // no mapping found, enable repository creation
125 treeItem
.setText(2, ""); //$NON-NLS-1$
127 // at least one mapping found
128 fillTreeItemWithGitDirectory(m
, treeItem
, false);
131 while (mi
.hasNext()) { // fill in additional mappings
133 TreeItem treeItem2
= new TreeItem(treeItem
, SWT
.NONE
);
134 treeItem2
.setData(m
.getContainer().getProject());
135 fillTreeItemWithGitDirectory(m
, treeItem2
, true);
137 } catch (CoreException e
) {
138 TreeItem treeItem2
= new TreeItem(treeItem
, SWT
.BOLD
|SWT
.ITALIC
);
139 treeItem2
.setText(e
.getMessage());
143 button
= new Button(g
, SWT
.PUSH
);
144 button
.setLayoutData(GridDataFactory
.fillDefaults().create());
145 button
.setText(UIText
.ExistingOrNewPage_CreateButton
);
146 button
.addSelectionListener(new SelectionListener() {
147 public void widgetSelected(SelectionEvent e
) {
148 File gitDir
= new File(repositoryToCreate
.getText(),Constants
.DOT_GIT
);
150 Repository repository
= new Repository(gitDir
);
152 for (IProject project
: getProjects().keySet()) {
153 // If we don't refresh the project directories right
154 // now we won't later know that a .git directory
155 // exists within it and we won't mark the .git
156 // directory as a team-private member. Failure
157 // to do so might allow someone to delete
158 // the .git directory without us stopping them.
159 // (Half lie, we should optimize so we do not
160 // refresh when the .git is not within the project)
162 if (!gitDir
.toString().contains("..")) //$NON-NLS-1$
163 project
.refreshLocal(IResource
.DEPTH_ONE
,
164 new NullProgressMonitor());
166 } catch (IOException e1
) {
169 UIText
.ExistingOrNewPage_ErrorFailedToCreateRepository
,
171 org
.eclipse
.egit
.ui
.Activator
.handleError(msg
, e1
, true);
172 } catch (CoreException e2
) {
175 UIText
.ExistingOrNewPage_ErrorFailedToRefreshRepository
,
177 org
.eclipse
.egit
.ui
.Activator
.handleError(msg
, e2
, true);
179 for (TreeItem ti
: tree
.getSelection()) {
180 ti
.setText(2, gitDir
.toString());
182 updateCreateOptions();
183 getContainer().updateButtons();
185 public void widgetDefaultSelected(SelectionEvent e
) {
188 repositoryToCreate
= new Text(g
, SWT
.SINGLE
| SWT
.BORDER
);
189 repositoryToCreate
.setLayoutData(GridDataFactory
.fillDefaults().grab(true, false).span(1,1).create());
190 repositoryToCreate
.addListener(SWT
.Modify
, new Listener() {
191 public void handleEvent(Event e
) {
194 IPath fromOSString
= Path
.fromOSString(e
.text
);
195 button
.setEnabled(minumumPath
196 .matchingFirstSegments(fromOSString
) == fromOSString
200 dotGitSegment
= new Text(g
,SWT
.NONE
);
201 dotGitSegment
.setEnabled(false);
202 dotGitSegment
.setEditable(false);
203 dotGitSegment
.setText(File
.separatorChar
+ Constants
.DOT_GIT
);
204 dotGitSegment
.setLayoutData(GridDataFactory
.fillDefaults().align(SWT
.LEFT
, SWT
.CENTER
).create());
206 tree
.addSelectionListener(new SelectionListener() {
207 public void widgetSelected(SelectionEvent e
) {
208 updateCreateOptions();
210 public void widgetDefaultSelected(SelectionEvent e
) {
214 updateCreateOptions();
218 private void fillTreeItemWithGitDirectory(RepositoryMapping m
, TreeItem treeItem2
, boolean isAlternative
) {
219 if (m
.getGitDir() == null)
220 treeItem2
.setText(2, UIText
.ExistingOrNewPage_SymbolicValueEmptyMapping
);
222 IPath container
= m
.getContainerPath();
223 if (!container
.isEmpty())
224 container
= container
.addTrailingSeparator();
225 IPath relativePath
= container
.append(m
.getGitDir());
227 treeItem2
.setText(0, relativePath
.removeLastSegments(1).addTrailingSeparator().toString());
228 treeItem2
.setText(2, relativePath
.toString());
232 private void updateCreateOptions() {
235 for (TreeItem ti
: tree
.getSelection()) {
236 String path
= ti
.getText(2);
237 if (!path
.equals("")) { //$NON-NLS-1$
241 String gitDirParentCandidate
= ti
.getText(1);
242 IPath thisPath
= Path
.fromOSString(gitDirParentCandidate
);
246 int n
= p
.matchingFirstSegments(thisPath
);
247 p
= p
.removeLastSegments(p
.segmentCount() - n
);
252 repositoryToCreate
.setText(p
.toOSString());
254 repositoryToCreate
.setText(""); //$NON-NLS-1$
256 button
.setEnabled(p
!= null);
257 repositoryToCreate
.setEnabled(p
!= null);
258 dotGitSegment
.setEnabled(p
!= null);
259 getContainer().updateButtons();
263 public boolean isPageComplete() {
264 if (tree
.getSelectionCount() == 0)
266 for (TreeItem ti
: tree
.getSelection()) {
267 String path
= ti
.getText(2);
268 if (path
.equals("")) { //$NON-NLS-1$
276 * @return map between project and repository root directory (converted to an
277 * absolute path) for all projects selected by user
279 public Map
<IProject
, File
> getProjects() {
280 final TreeItem
[] selection
= tree
.getSelection();
281 Map
<IProject
, File
> ret
= new HashMap
<IProject
, File
>(selection
.length
);
282 for (int i
= 0; i
< selection
.length
; ++i
) {
283 TreeItem treeItem
= selection
[i
];
284 while (treeItem
.getData() == null && treeItem
.getParentItem() != null) {
285 treeItem
= treeItem
.getParentItem();
288 final IProject project
= (IProject
) treeItem
.getData();
289 final IPath selectedRepo
= Path
.fromOSString(treeItem
.getText(2));
290 IPath localPathToRepo
= selectedRepo
;
291 if (!selectedRepo
.isAbsolute()) {
292 localPathToRepo
= project
.getLocation().append(selectedRepo
);
294 ret
.put(project
, localPathToRepo
.toFile());