1 /*******************************************************************************
2 * Copyright (C) 2009, 2013 Robin Rosenberg and others.
3 * Copyright (C) 2009, Mykola Nikishov <mn@mn.com.ua>
4 * Copyright (C) 2011, Mathias Kinzler <mathias.kinzler@sap.com>
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *******************************************************************************/
11 package org
.eclipse
.egit
.ui
.internal
.sharing
;
14 import java
.io
.IOException
;
15 import java
.util
.Collection
;
16 import java
.util
.HashMap
;
17 import java
.util
.Iterator
;
20 import org
.eclipse
.core
.resources
.IProject
;
21 import org
.eclipse
.core
.resources
.IResource
;
22 import org
.eclipse
.core
.resources
.ResourcesPlugin
;
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
.RepositoryUtil
;
28 import org
.eclipse
.egit
.core
.project
.RepositoryFinder
;
29 import org
.eclipse
.egit
.core
.project
.RepositoryMapping
;
30 import org
.eclipse
.egit
.ui
.Activator
;
31 import org
.eclipse
.egit
.ui
.internal
.UIIcons
;
32 import org
.eclipse
.egit
.ui
.internal
.UIText
;
33 import org
.eclipse
.egit
.ui
.internal
.repository
.NewRepositoryWizard
;
34 import org
.eclipse
.jface
.dialogs
.Dialog
;
35 import org
.eclipse
.jface
.dialogs
.IMessageProvider
;
36 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
37 import org
.eclipse
.jface
.layout
.GridDataFactory
;
38 import org
.eclipse
.jface
.layout
.GridLayoutFactory
;
39 import org
.eclipse
.jface
.viewers
.ArrayContentProvider
;
40 import org
.eclipse
.jface
.viewers
.CheckStateChangedEvent
;
41 import org
.eclipse
.jface
.viewers
.CheckboxTableViewer
;
42 import org
.eclipse
.jface
.viewers
.CheckboxTreeViewer
;
43 import org
.eclipse
.jface
.viewers
.ComboViewer
;
44 import org
.eclipse
.jface
.viewers
.ICheckStateListener
;
45 import org
.eclipse
.jface
.viewers
.ISelection
;
46 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
47 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
48 import org
.eclipse
.jface
.viewers
.ViewerSorter
;
49 import org
.eclipse
.jface
.window
.Window
;
50 import org
.eclipse
.jface
.wizard
.WizardDialog
;
51 import org
.eclipse
.jface
.wizard
.WizardPage
;
52 import org
.eclipse
.jgit
.lib
.Constants
;
53 import org
.eclipse
.jgit
.lib
.ObjectId
;
54 import org
.eclipse
.jgit
.lib
.Repository
;
55 import org
.eclipse
.jgit
.lib
.RepositoryBuilder
;
56 import org
.eclipse
.jgit
.revwalk
.RevCommit
;
57 import org
.eclipse
.jgit
.revwalk
.RevTree
;
58 import org
.eclipse
.jgit
.revwalk
.RevWalk
;
59 import org
.eclipse
.jgit
.storage
.file
.FileRepositoryBuilder
;
60 import org
.eclipse
.jgit
.treewalk
.TreeWalk
;
61 import org
.eclipse
.osgi
.util
.NLS
;
62 import org
.eclipse
.swt
.SWT
;
63 import org
.eclipse
.swt
.events
.ModifyEvent
;
64 import org
.eclipse
.swt
.events
.ModifyListener
;
65 import org
.eclipse
.swt
.events
.SelectionAdapter
;
66 import org
.eclipse
.swt
.events
.SelectionEvent
;
67 import org
.eclipse
.swt
.layout
.GridData
;
68 import org
.eclipse
.swt
.layout
.GridLayout
;
69 import org
.eclipse
.swt
.widgets
.Button
;
70 import org
.eclipse
.swt
.widgets
.Combo
;
71 import org
.eclipse
.swt
.widgets
.Composite
;
72 import org
.eclipse
.swt
.widgets
.DirectoryDialog
;
73 import org
.eclipse
.swt
.widgets
.Event
;
74 import org
.eclipse
.swt
.widgets
.Label
;
75 import org
.eclipse
.swt
.widgets
.Listener
;
76 import org
.eclipse
.swt
.widgets
.Table
;
77 import org
.eclipse
.swt
.widgets
.TableColumn
;
78 import org
.eclipse
.swt
.widgets
.TableItem
;
79 import org
.eclipse
.swt
.widgets
.Text
;
80 import org
.eclipse
.swt
.widgets
.Tree
;
81 import org
.eclipse
.swt
.widgets
.TreeColumn
;
82 import org
.eclipse
.swt
.widgets
.TreeItem
;
83 import org
.eclipse
.ui
.PlatformUI
;
84 import org
.eclipse
.ui
.ide
.IDE
.SharedImages
;
87 * Wizard page for connecting projects to Git repositories.
89 class ExistingOrNewPage
extends WizardPage
{
91 private final SharingWizard myWizard
;
93 private Button createRepo
;
97 private CheckboxTreeViewer viewer
;
99 private Text repositoryToCreate
;
101 private IPath minumumPath
;
103 private Label dotGitSegment
;
105 private Composite externalComposite
;
107 private Composite parentRepoComposite
;
109 private Text workDir
;
111 private Text relPath
;
113 private Button browseRepository
;
115 private Repository selectedRepository
;
117 private CheckboxTableViewer projectMoveViewer
;
119 private final MoveProjectsLabelProvider moveProjectsLabelProvider
= new MoveProjectsLabelProvider();
121 private boolean internalMode
= false;
123 ExistingOrNewPage(SharingWizard w
) {
124 super(ExistingOrNewPage
.class.getName());
125 setTitle(UIText
.ExistingOrNewPage_title
);
126 setImageDescriptor(UIIcons
.WIZBAN_CONNECT_REPO
);
131 public void createControl(Composite parent
) {
132 final RepositoryUtil util
= Activator
.getDefault().getRepositoryUtil();
133 Composite main
= new Composite(parent
, SWT
.NONE
);
134 // use zero spacing to save some real estate here
135 GridLayoutFactory
.fillDefaults().spacing(0, 0).applyTo(main
);
137 final Button internalModeButton
= new Button(main
, SWT
.CHECK
);
139 .setText(UIText
.ExistingOrNewPage_InternalModeCheckbox
);
141 .setToolTipText(UIText
.ExistingOrNewPage_CreationInWorkspaceWarningTooltip
);
142 internalModeButton
.addSelectionListener(new SelectionAdapter() {
144 public void widgetSelected(SelectionEvent e
) {
145 internalMode
= internalModeButton
.getSelection();
150 externalComposite
= new Composite(main
, SWT
.NONE
);
151 GridDataFactory
.fillDefaults().grab(true, true)
152 .applyTo(externalComposite
);
153 externalComposite
.setLayout(new GridLayout(3, false));
155 new Label(externalComposite
, SWT
.NONE
)
156 .setText(UIText
.ExistingOrNewPage_ExistingRepositoryLabel
);
157 final Combo existingRepoCombo
= new Combo(externalComposite
,
159 GridDataFactory
.fillDefaults().grab(true, false)
160 .applyTo(existingRepoCombo
);
161 final ComboViewer v
= new ComboViewer(existingRepoCombo
);
162 v
.setContentProvider(new RepoComboContentProvider());
163 v
.setLabelProvider(new RepoComboLabelProvider());
164 v
.setInput(new Object());
165 // the default ViewerSorter seems to do the right thing
166 // i.e. sort as String
167 v
.setSorter(new ViewerSorter());
169 existingRepoCombo
.addSelectionListener(new SelectionAdapter() {
171 public void widgetSelected(SelectionEvent e
) {
172 selectedRepository
= null;
173 IStructuredSelection sel
= (IStructuredSelection
) v
175 setRepository((Repository
) sel
.getFirstElement());
180 Button createRepoWizard
= new Button(externalComposite
, SWT
.PUSH
);
181 createRepoWizard
.setText(UIText
.ExistingOrNewPage_CreateRepositoryButton
);
182 createRepoWizard
.addSelectionListener(new SelectionAdapter() {
184 public void widgetSelected(SelectionEvent e
) {
185 NewRepositoryWizard wiz
= new NewRepositoryWizard(true);
186 if (new WizardDialog(getShell(), wiz
).open() == Window
.OK
) {
188 selectedRepository
= wiz
.getCreatedRepository();
189 v
.setSelection(new StructuredSelection(selectedRepository
));
195 new Label(externalComposite
, SWT
.NONE
)
196 .setText(UIText
.ExistingOrNewPage_WorkingDirectoryLabel
);
197 workDir
= new Text(externalComposite
, SWT
.BORDER
| SWT
.READ_ONLY
);
198 GridDataFactory
.fillDefaults().grab(true, false).applyTo(workDir
);
199 GridDataFactory
.fillDefaults().applyTo(workDir
);
200 // leave the space between the "Create" and "Browse" buttons empty (i.e.
201 // do not fill to the right border
202 new Label(externalComposite
, SWT
.NONE
);
204 new Label(externalComposite
, SWT
.NONE
)
205 .setText(UIText
.ExistingOrNewPage_RelativePathLabel
);
206 relPath
= new Text(externalComposite
, SWT
.BORDER
);
207 relPath
.addModifyListener(new ModifyListener() {
209 public void modifyText(ModifyEvent e
) {
214 GridDataFactory
.fillDefaults().grab(true, false).applyTo(relPath
);
215 browseRepository
= new Button(externalComposite
, SWT
.PUSH
);
216 browseRepository
.setEnabled(false);
218 .setText(UIText
.ExistingOrNewPage_BrowseRepositoryButton
);
219 browseRepository
.addSelectionListener(new SelectionAdapter() {
221 public void widgetSelected(SelectionEvent e
) {
222 DirectoryDialog dlg
= new DirectoryDialog(getShell());
223 dlg
.setFilterPath(selectedRepository
.getWorkTree().getPath());
224 String directory
= dlg
.open();
225 if (directory
!= null) {
226 setRelativePath(directory
);
232 Table projectMoveTable
= new Table(externalComposite
, SWT
.MULTI
233 | SWT
.FULL_SELECTION
| SWT
.CHECK
| SWT
.BORDER
);
234 projectMoveViewer
= new CheckboxTableViewer(projectMoveTable
);
235 GridDataFactory
.fillDefaults().span(3, 1).grab(true, true)
236 .applyTo(projectMoveTable
);
239 tc
= new TableColumn(projectMoveTable
, SWT
.NONE
);
240 tc
.setText(UIText
.ExistingOrNewPage_ProjectNameColumnHeader
);
243 tc
= new TableColumn(projectMoveTable
, SWT
.NONE
);
244 tc
.setText(UIText
.ExistingOrNewPage_CurrentLocationColumnHeader
);
247 tc
= new TableColumn(projectMoveTable
, SWT
.NONE
);
248 tc
.setText(UIText
.ExistingOrNewPage_NewLocationTargetHeader
);
251 projectMoveTable
.setHeaderVisible(true);
253 .setContentProvider(ArrayContentProvider
.getInstance());
254 projectMoveViewer
.setLabelProvider(moveProjectsLabelProvider
);
255 projectMoveViewer
.setInput(myWizard
.projects
);
256 projectMoveViewer
.addCheckStateListener(new ICheckStateListener() {
258 public void checkStateChanged(CheckStateChangedEvent event
) {
262 TableItem
[] children
= projectMoveViewer
.getTable().getItems();
263 for (int i
= 0; i
< children
.length
; i
++) {
264 TableItem item
= children
[i
];
265 IProject data
= (IProject
) item
.getData();
266 RepositoryFinder repositoryFinder
= new RepositoryFinder(data
);
267 repositoryFinder
.setFindInChildren(false);
269 Collection
<RepositoryMapping
> find
= repositoryFinder
270 .find(new NullProgressMonitor());
271 if (find
.size() != 1)
272 item
.setChecked(true);
273 } catch (CoreException e1
) {
274 item
.setText(2, e1
.getMessage());
278 parentRepoComposite
= new Composite(main
, SWT
.NONE
);
279 parentRepoComposite
.setLayout(new GridLayout(3, false));
280 GridDataFactory
.fillDefaults().grab(true, true)
281 .applyTo(parentRepoComposite
);
283 tree
= new Tree(parentRepoComposite
, SWT
.BORDER
| SWT
.MULTI
284 | SWT
.FULL_SELECTION
| SWT
.CHECK
);
285 viewer
= new CheckboxTreeViewer(tree
);
286 tree
.setHeaderVisible(true);
287 tree
.setLayout(new GridLayout());
288 tree
.setLayoutData(GridDataFactory
.fillDefaults().grab(true, true)
289 .span(3, 1).create());
290 viewer
.addCheckStateListener(new ICheckStateListener() {
293 public void checkStateChanged(CheckStateChangedEvent event
) {
294 if (event
.getChecked()) {
295 ProjectAndRepo checkable
= (ProjectAndRepo
) event
297 for (TreeItem ti
: tree
.getItems()) {
298 if (ti
.getItemCount() > 0
299 || ((ProjectAndRepo
) ti
.getData()).getRepo()
300 .equals("")) //$NON-NLS-1$
301 ti
.setChecked(false);
302 for (TreeItem subTi
: ti
.getItems()) {
303 IProject project
= ((ProjectAndRepo
) subTi
304 .getData()).getProject();
305 if (checkable
.getProject() != null
306 && !subTi
.getData().equals(checkable
)
307 && checkable
.getProject().equals(project
))
308 subTi
.setChecked(false);
314 TreeColumn c1
= new TreeColumn(tree
, SWT
.NONE
);
315 c1
.setText(UIText
.ExistingOrNewPage_HeaderProject
);
317 TreeColumn c2
= new TreeColumn(tree
, SWT
.NONE
);
318 c2
.setText(UIText
.ExistingOrNewPage_HeaderLocation
);
320 TreeColumn c3
= new TreeColumn(tree
, SWT
.NONE
);
321 c3
.setText(UIText
.ExistingOrNewPage_HeaderRepository
);
323 boolean allProjectsInExistingRepos
= true;
324 for (IProject project
: myWizard
.projects
) {
325 RepositoryFinder repositoryFinder
= new RepositoryFinder(project
);
326 repositoryFinder
.setFindInChildren(false);
328 Collection
<RepositoryMapping
> mappings
;
329 mappings
= repositoryFinder
.find(new NullProgressMonitor());
330 Iterator
<RepositoryMapping
> mi
= mappings
.iterator();
331 RepositoryMapping m
= mi
.hasNext() ? mi
.next() : null;
333 // no mapping found, enable repository creation
334 TreeItem treeItem
= new TreeItem(tree
, SWT
.NONE
);
335 updateProjectTreeItem(treeItem
, project
);
336 treeItem
.setText(1, project
.getLocation().toOSString());
337 treeItem
.setText(2, ""); //$NON-NLS-1$
338 treeItem
.setData(new ProjectAndRepo(project
, "")); //$NON-NLS-1$
339 allProjectsInExistingRepos
= false;
340 } else if (!mi
.hasNext()) {
341 // exactly one mapping found
342 TreeItem treeItem
= new TreeItem(tree
, SWT
.NONE
);
343 updateProjectTreeItem(treeItem
, project
);
344 treeItem
.setText(1, project
.getLocation().toOSString());
345 fillTreeItemWithGitDirectory(m
, treeItem
, false);
346 treeItem
.setData(new ProjectAndRepo(project
, m
347 .getGitDirAbsolutePath().toOSString()));
348 treeItem
.setChecked(true);
352 TreeItem treeItem
= new TreeItem(tree
, SWT
.NONE
);
353 updateProjectTreeItem(treeItem
, project
);
354 treeItem
.setText(1, project
.getLocation().toOSString());
355 treeItem
.setData(new ProjectAndRepo(project
, "")); //$NON-NLS-1$
357 TreeItem treeItem2
= new TreeItem(treeItem
, SWT
.NONE
);
358 updateProjectTreeItem(treeItem2
, project
);
359 fillTreeItemWithGitDirectory(m
, treeItem2
, true);
360 treeItem2
.setData(new ProjectAndRepo(project
, m
361 .getGitDirAbsolutePath().toOSString()));
362 while (mi
.hasNext()) { // fill in additional mappings
364 treeItem2
= new TreeItem(treeItem
, SWT
.NONE
);
365 updateProjectTreeItem(treeItem2
, project
);
366 fillTreeItemWithGitDirectory(m
, treeItem2
, true);
367 treeItem2
.setData(new ProjectAndRepo(m
.getContainer()
368 .getProject(), m
.getGitDirAbsolutePath()
371 treeItem
.setExpanded(true);
372 allProjectsInExistingRepos
= false;
374 } catch (CoreException e
) {
375 TreeItem treeItem2
= new TreeItem(tree
, SWT
.BOLD
| SWT
.ITALIC
);
376 treeItem2
.setText(e
.getMessage());
380 createRepo
= new Button(parentRepoComposite
, SWT
.PUSH
);
381 createRepo
.setLayoutData(GridDataFactory
.fillDefaults().create());
382 createRepo
.setText(UIText
.ExistingOrNewPage_CreateButton
);
383 createRepo
.addSelectionListener(new SelectionAdapter() {
385 public void widgetSelected(SelectionEvent e
) {
386 File gitDir
= new File(repositoryToCreate
.getText(),
389 Repository repository
= FileRepositoryBuilder
392 for (IProject project
: getProjects(false).keySet()) {
393 // If we don't refresh the project directories right
394 // now we won't later know that a .git directory
395 // exists within it and we won't mark the .git
396 // directory as a team-private member. Failure
397 // to do so might allow someone to delete
398 // the .git directory without us stopping them.
399 // (Half lie, we should optimize so we do not
400 // refresh when the .git is not within the project)
402 if (!gitDir
.toString().contains("..")) //$NON-NLS-1$
403 project
.refreshLocal(IResource
.DEPTH_ONE
,
404 new NullProgressMonitor());
406 util
.addConfiguredRepository(gitDir
);
407 } catch (IOException e1
) {
409 .bind(UIText
.ExistingOrNewPage_ErrorFailedToCreateRepository
,
411 org
.eclipse
.egit
.ui
.Activator
.handleError(msg
, e1
, true);
412 } catch (CoreException e2
) {
414 .bind(UIText
.ExistingOrNewPage_ErrorFailedToRefreshRepository
,
416 org
.eclipse
.egit
.ui
.Activator
.handleError(msg
, e2
, true);
418 for (TreeItem ti
: tree
.getSelection()) {
419 IPath projectPath
= new Path(ti
.getText(1));
420 IPath gitPath
= new Path(gitDir
.toString());
421 IPath relative
= gitPath
.makeRelativeTo(projectPath
);
422 ti
.setText(2, relative
.toOSString());
423 ((ProjectAndRepo
) ti
.getData()).repo
= gitDir
.toString();
429 repositoryToCreate
= new Text(parentRepoComposite
, SWT
.SINGLE
431 repositoryToCreate
.setLayoutData(GridDataFactory
.fillDefaults()
432 .grab(true, false).span(1, 1).create());
433 repositoryToCreate
.addListener(SWT
.Modify
, new Listener() {
435 public void handleEvent(Event e
) {
436 if (repositoryToCreate
.getText().equals("")) { //$NON-NLS-1$
437 createRepo
.setEnabled(false);
440 IPath fromOSString
= Path
.fromOSString(repositoryToCreate
442 createRepo
.setEnabled(minumumPath
443 .matchingFirstSegments(fromOSString
) == fromOSString
447 dotGitSegment
= new Label(parentRepoComposite
, SWT
.NONE
);
448 dotGitSegment
.setEnabled(false);
449 dotGitSegment
.setText(File
.separatorChar
+ Constants
.DOT_GIT
);
450 dotGitSegment
.setLayoutData(GridDataFactory
.fillDefaults()
451 .align(SWT
.LEFT
, SWT
.CENTER
).create());
453 tree
.addSelectionListener(new SelectionAdapter() {
455 public void widgetSelected(SelectionEvent e
) {
456 tree
.select((TreeItem
) e
.item
);
461 Dialog
.applyDialogFont(main
);
464 if (allProjectsInExistingRepos
) {
466 internalModeButton
.setSelection(true);
471 private void updateProjectTreeItem(TreeItem item
, IProject project
) {
473 PlatformUI
.getWorkbench().getSharedImages()
474 .getImage(SharedImages
.IMG_OBJ_PROJECT
));
475 item
.setText(0, project
.getName());
478 protected void setRelativePath(String directory
) {
479 IPath folderPath
= new Path(directory
).setDevice(null);
480 IPath workdirPath
= new Path(this.selectedRepository
.getWorkTree()
481 .getPath()).setDevice(null);
482 if (!workdirPath
.isPrefixOf(folderPath
)) {
483 MessageDialog
.openError(getShell(),
484 UIText
.ExistingOrNewPage_WrongPathErrorDialogTitle
,
485 UIText
.ExistingOrNewPage_WrongPathErrorDialogMessage
);
488 relPath
.setText(folderPath
.removeFirstSegments(
489 workdirPath
.segmentCount()).toString());
492 protected void setRepository(Repository repository
) {
493 if (repository
== this.selectedRepository
)
495 this.selectedRepository
= repository
;
496 relPath
.setText(""); //$NON-NLS-1$
500 public void setVisible(boolean visible
) {
501 super.setVisible(visible
);
506 private void fillTreeItemWithGitDirectory(RepositoryMapping m
,
507 TreeItem treeItem
, boolean isAlternative
) {
508 if (m
.getGitDir() == null)
510 UIText
.ExistingOrNewPage_SymbolicValueEmptyMapping
);
512 IPath relativePath
= new Path(m
.getGitDir());
514 IPath withoutLastSegment
= relativePath
.removeLastSegments(1);
516 if (withoutLastSegment
.isEmpty())
517 path
= Path
.fromPortableString("."); //$NON-NLS-1$
519 path
= withoutLastSegment
;
520 treeItem
.setText(0, path
.toString());
522 treeItem
.setText(2, relativePath
.toOSString());
524 IProject project
= m
.getContainer().getProject();
525 Repository repo
= new RepositoryBuilder().setGitDir(
526 m
.getGitDirAbsolutePath().toFile()).build();
527 File workTree
= repo
.getWorkTree();
528 IPath workTreePath
= Path
.fromOSString(workTree
530 if (workTreePath
.isPrefixOf(project
.getLocation())) {
531 IPath makeRelativeTo
= project
.getLocation()
532 .makeRelativeTo(workTreePath
);
533 String repoRelativePath
= makeRelativeTo
534 .append("/.project").toPortableString(); //$NON-NLS-1$
535 ObjectId headCommitId
= repo
.resolve(Constants
.HEAD
);
536 if (headCommitId
!= null) {
538 try (RevWalk revWalk
= new RevWalk(repo
)) {
539 RevCommit headCommit
= revWalk
540 .parseCommit(headCommitId
);
541 RevTree headTree
= headCommit
.getTree();
542 TreeWalk projectInRepo
= TreeWalk
.forPath(repo
,
543 repoRelativePath
, headTree
);
544 if (projectInRepo
!= null) {
545 // the .project file is tracked by this repo
546 treeItem
.setChecked(true);
552 } catch (IOException e1
) {
555 UIText
.ExistingOrNewPage_FailedToDetectRepositoryMessage
,
561 protected void updateControls() {
563 setErrorMessage(null);
565 setDescription(UIText
.ExistingOrNewPage_DescriptionExternalMode
);
566 if (this.selectedRepository
!= null) {
567 workDir
.setText(this.selectedRepository
.getWorkTree().getPath());
568 String relativePath
= relPath
.getText();
569 File testFile
= new File(this.selectedRepository
.getWorkTree(),
571 if (!testFile
.exists())
574 UIText
.ExistingOrNewPage_FolderWillBeCreatedMessage
,
575 relativePath
), IMessageProvider
.WARNING
);
576 IPath targetPath
= new Path(selectedRepository
.getWorkTree()
578 targetPath
= targetPath
.append(relPath
.getText());
579 moveProjectsLabelProvider
.targetFolder
= targetPath
;
580 projectMoveViewer
.refresh(true);
581 browseRepository
.setEnabled(true);
582 for (Object checked
: projectMoveViewer
.getCheckedElements()) {
583 IProject prj
= (IProject
) checked
;
584 IPath projectMoveTarget
= targetPath
.append(prj
.getName());
585 boolean mustMove
= !prj
.getLocation().equals(
587 File targetTest
= new File(projectMoveTarget
.toOSString());
588 if (mustMove
&& targetTest
.exists()) {
590 .bind(UIText
.ExistingOrNewPage_ExistingTargetErrorMessage
,
594 File parent
= targetTest
.getParentFile();
595 while (parent
!= null) {
596 if (new File(parent
, ".project").exists()) { //$NON-NLS-1$
598 .bind(UIText
.ExistingOrNewPage_NestedProjectErrorMessage
,
599 new String
[] { prj
.getName(),
600 targetTest
.getPath(),
601 parent
.getPath() }));
604 parent
= parent
.getParentFile();
606 // break after the first error
607 if (getErrorMessage() != null)
611 workDir
.setText(UIText
.ExistingOrNewPage_NoRepositorySelectedMessage
);
612 setPageComplete(getErrorMessage() == null
613 && selectedRepository
!= null
614 && projectMoveViewer
.getCheckedElements().length
> 0);
616 setDescription(UIText
.ExistingOrNewPage_description
);
617 IPath p
= proposeNewRepositoryPath(tree
.getSelection());
620 repositoryToCreate
.setText(p
.toOSString());
622 repositoryToCreate
.setText(""); //$NON-NLS-1$
624 createRepo
.setEnabled(p
!= null);
625 repositoryToCreate
.setEnabled(p
!= null);
626 dotGitSegment
.setEnabled(p
!= null);
628 boolean pageComplete
= viewer
.getCheckedElements().length
> 0;
629 for (Object checkedElement
: viewer
.getCheckedElements()) {
630 String path
= ((ProjectAndRepo
) checkedElement
).getRepo();
631 if (((ProjectAndRepo
) checkedElement
).getRepo() != null
632 && path
.equals("")) { //$NON-NLS-1$
633 pageComplete
= false;
636 setPageComplete(pageComplete
);
637 // provide a warning if Repository is created in workspace
638 for (IProject project
: myWizard
.projects
) {
639 if (createRepo
.isEnabled()
640 && ResourcesPlugin
.getWorkspace().getRoot()
642 .isPrefixOf(project
.getLocation())) {
644 UIText
.ExistingOrNewPage_RepoCreationInWorkspaceCreationWarning
,
645 IMessageProvider
.WARNING
);
651 externalComposite
.setVisible(!internalMode
);
652 parentRepoComposite
.setVisible(internalMode
);
654 gd
= (GridData
) parentRepoComposite
.getLayoutData();
655 gd
.exclude
= !internalMode
;
657 gd
= (GridData
) externalComposite
.getLayoutData();
658 gd
.exclude
= internalMode
;
660 ((Composite
) getControl()).layout(true);
663 private static IPath
proposeNewRepositoryPath(TreeItem
[] treeItems
) {
665 for (TreeItem ti
: treeItems
) {
666 String gitDirParentCandidate
= ti
.getText(1);
667 if (gitDirParentCandidate
.equals("")) //$NON-NLS-1$
669 if (ti
.getItemCount() > 0)
670 if (hasRepositoryInOwnDirectory(ti
.getItems()))
672 if (hasRepositoryInOwnDirectory(ti
))
674 IPath thisPath
= Path
.fromOSString(gitDirParentCandidate
);
678 int n
= p
.matchingFirstSegments(thisPath
);
679 p
= p
.removeLastSegments(p
.segmentCount() - n
);
685 private static boolean hasRepositoryInOwnDirectory(TreeItem
... items
) {
686 for (TreeItem item
: items
)
687 if (".git".equals(item
.getText(2))) //$NON-NLS-1$
694 * pass true to get the checked elements, false to get the
696 * @return map between project and repository root directory (converted to
697 * an absolute path) for all projects selected by user
699 public Map
<IProject
, File
> getProjects(boolean checked
) {
700 final Object
[] elements
;
703 elements
= projectMoveViewer
.getCheckedElements();
705 ISelection selection
= viewer
.getSelection();
706 elements
= ((IStructuredSelection
) selection
).toArray();
709 elements
= viewer
.getCheckedElements();
711 ISelection selection
= viewer
.getSelection();
712 if (selection
instanceof IStructuredSelection
)
713 elements
= ((IStructuredSelection
) selection
).toArray();
715 elements
= new Object
[0];
718 Map
<IProject
, File
> ret
= new HashMap
<IProject
, File
>(elements
.length
);
719 for (Object ti
: elements
) {
721 File workdir
= selectedRepository
.getWorkTree();
722 IProject project
= (IProject
) ti
;
723 IPath targetLocation
= new Path(relPath
.getText())
724 .append(project
.getName());
725 File targetFile
= new File(workdir
, targetLocation
.toOSString());
726 ret
.put(project
, targetFile
);
729 final IProject project
= ((ProjectAndRepo
) ti
).getProject();
730 String path
= ((ProjectAndRepo
) ti
).getRepo();
731 final IPath selectedRepo
= Path
.fromOSString(path
);
732 IPath localPathToRepo
= selectedRepo
;
733 if (!selectedRepo
.isAbsolute()) {
734 localPathToRepo
= project
.getLocation()
735 .append(selectedRepo
);
737 ret
.put(project
, localPathToRepo
.toFile());
743 public boolean getInternalMode() {
747 private static class ProjectAndRepo
{
748 private IProject project
;
752 public ProjectAndRepo(IProject project
, String repo
) {
753 this.project
= project
;
757 public IProject
getProject() {
761 public String
getRepo() {
766 public Repository
getSelectedRepsoitory() {
767 return selectedRepository
;