1 /*******************************************************************************
2 * Copyright (c) 2010 SAP AG.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * Mathias Kinzler (SAP AG) - initial implementation
10 *******************************************************************************/
11 package org
.eclipse
.egit
.ui
.internal
.repository
;
14 import java
.io
.IOException
;
15 import java
.net
.URISyntaxException
;
16 import java
.util
.ArrayList
;
17 import java
.util
.Arrays
;
18 import java
.util
.Collection
;
19 import java
.util
.Collections
;
20 import java
.util
.Comparator
;
21 import java
.util
.HashSet
;
22 import java
.util
.List
;
24 import java
.util
.Map
.Entry
;
26 import org
.eclipse
.core
.resources
.IProjectDescription
;
27 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
28 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
29 import org
.eclipse
.egit
.ui
.Activator
;
30 import org
.eclipse
.egit
.ui
.UIText
;
31 import org
.eclipse
.egit
.ui
.internal
.clone
.GitProjectsImportPage
;
32 import org
.eclipse
.egit
.ui
.internal
.repository
.RepositoryTreeNode
.RepositoryTreeNodeType
;
33 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
34 import org
.eclipse
.jface
.viewers
.Viewer
;
35 import org
.eclipse
.jgit
.lib
.Constants
;
36 import org
.eclipse
.jgit
.lib
.Ref
;
37 import org
.eclipse
.jgit
.lib
.RefDatabase
;
38 import org
.eclipse
.jgit
.lib
.Repository
;
39 import org
.eclipse
.jgit
.transport
.RemoteConfig
;
40 import org
.eclipse
.osgi
.util
.NLS
;
43 * Content Provider for the Git Repositories View
45 public class RepositoriesViewContentProvider
implements ITreeContentProvider
{
47 @SuppressWarnings("unchecked")
48 public Object
[] getElements(Object inputElement
) {
50 List
<RepositoryTreeNode
> nodes
= (List
<RepositoryTreeNode
>) inputElement
;
51 Collections
.sort(nodes
);
52 return nodes
.toArray();
55 public void dispose() {
59 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
63 public Object
[] getChildren(Object parentElement
) {
65 RepositoryTreeNode node
= (RepositoryTreeNode
) parentElement
;
66 Repository repo
= node
.getRepository();
68 switch (node
.getType()) {
72 List
<RepositoryTreeNode
<Repository
>> nodes
= new ArrayList
<RepositoryTreeNode
<Repository
>>();
74 nodes
.add(new RepositoryTreeNode
<Repository
>(node
,
75 RepositoryTreeNodeType
.LOCALBRANCHES
, repo
, repo
));
76 nodes
.add(new RepositoryTreeNode
<Repository
>(node
,
77 RepositoryTreeNodeType
.REMOTEBRANCHES
, repo
, repo
));
79 return nodes
.toArray();
83 List
<RepositoryTreeNode
<Ref
>> refs
= new ArrayList
<RepositoryTreeNode
<Ref
>>();
86 for (Entry
<String
, Ref
> refEntry
: repo
.getRefDatabase()
87 .getRefs(Constants
.R_HEADS
).entrySet()) {
88 if (!refEntry
.getValue().isSymbolic())
89 refs
.add(new RepositoryTreeNode
<Ref
>(node
,
90 RepositoryTreeNodeType
.REF
, repo
, refEntry
93 } catch (IOException e
) {
94 handleException(e
, node
);
97 return refs
.toArray();
100 case REMOTEBRANCHES
: {
101 List
<RepositoryTreeNode
<Ref
>> refs
= new ArrayList
<RepositoryTreeNode
<Ref
>>();
104 for (Entry
<String
, Ref
> refEntry
: repo
.getRefDatabase()
105 .getRefs(Constants
.R_REMOTES
).entrySet()) {
106 if (!refEntry
.getValue().isSymbolic())
107 refs
.add(new RepositoryTreeNode
<Ref
>(node
,
108 RepositoryTreeNodeType
.REF
, repo
, refEntry
111 } catch (IOException e
) {
112 handleException(e
, node
);
115 return refs
.toArray();
118 List
<RepositoryTreeNode
<Ref
>> refs
= new ArrayList
<RepositoryTreeNode
<Ref
>>();
121 for (Entry
<String
, Ref
> refEntry
: repo
.getRefDatabase()
122 .getRefs(Constants
.R_TAGS
).entrySet()) {
123 refs
.add(new RepositoryTreeNode
<Ref
>(node
,
124 RepositoryTreeNodeType
.TAG
, repo
, refEntry
127 } catch (IOException e
) {
128 handleException(e
, node
);
131 return refs
.toArray();
135 List
<RepositoryTreeNode
<Ref
>> refs
= new ArrayList
<RepositoryTreeNode
<Ref
>>();
138 for (Entry
<String
, Ref
> refEntry
: repo
.getRefDatabase()
139 .getRefs(RefDatabase
.ALL
).entrySet()) {
140 if (refEntry
.getValue().isSymbolic())
141 refs
.add(new RepositoryTreeNode
<Ref
>(node
,
142 RepositoryTreeNodeType
.SYMBOLICREF
, repo
,
143 refEntry
.getValue()));
145 } catch (IOException e
) {
146 handleException(e
, node
);
149 return refs
.toArray();
153 List
<RepositoryTreeNode
<String
>> remotes
= new ArrayList
<RepositoryTreeNode
<String
>>();
155 Repository rep
= node
.getRepository();
157 Set
<String
> configNames
= rep
.getConfig().getSubsections(
158 RepositoriesView
.REMOTE
);
160 for (String configName
: configNames
) {
161 remotes
.add(new RepositoryTreeNode
<String
>(node
,
162 RepositoryTreeNodeType
.REMOTE
, repo
, configName
));
165 return remotes
.toArray();
170 List
<RepositoryTreeNode
<?
extends Object
>> nodeList
= new ArrayList
<RepositoryTreeNode
<?
extends Object
>>();
172 nodeList
.add(new RepositoryTreeNode
<Repository
>(node
,
173 RepositoryTreeNodeType
.BRANCHES
, node
.getRepository(), node
176 nodeList
.add(new RepositoryTreeNode
<Repository
>(node
,
177 RepositoryTreeNodeType
.TAGS
, repo
, repo
));
179 nodeList
.add(new RepositoryTreeNode
<Repository
>(node
,
180 RepositoryTreeNodeType
.SYMBOLICREFS
, repo
, repo
));
182 nodeList
.add(new RepositoryTreeNode
<Repository
>(node
,
183 RepositoryTreeNodeType
.WORKINGDIR
, node
.getRepository(),
184 node
.getRepository()));
186 nodeList
.add(new RepositoryTreeNode
<Repository
>(node
,
187 RepositoryTreeNodeType
.PROJECTS
, node
.getRepository(), node
190 nodeList
.add(new RepositoryTreeNode
<Repository
>(node
,
191 RepositoryTreeNodeType
.REMOTES
, node
.getRepository(), node
194 return nodeList
.toArray();
198 List
<RepositoryTreeNode
<File
>> projects
= new ArrayList
<RepositoryTreeNode
<File
>>();
200 // TODO do we want to show the projects here?
201 Collection
<File
> result
= new HashSet
<File
>();
202 Set
<String
> traversed
= new HashSet
<String
>();
203 collectProjectFilesFromDirectory(result
, repo
.getDirectory()
204 .getParentFile(), traversed
, new NullProgressMonitor());
205 for (File file
: result
) {
206 projects
.add(new RepositoryTreeNode
<File
>(node
,
207 RepositoryTreeNodeType
.PROJ
, repo
, file
));
210 Comparator
<RepositoryTreeNode
<File
>> sorter
= new Comparator
<RepositoryTreeNode
<File
>>() {
212 public int compare(RepositoryTreeNode
<File
> o1
,
213 RepositoryTreeNode
<File
> o2
) {
214 return o1
.getObject().getName().compareTo(
215 o2
.getObject().getName());
218 Collections
.sort(projects
, sorter
);
220 return projects
.toArray();
224 List
<RepositoryTreeNode
<File
>> children
= new ArrayList
<RepositoryTreeNode
<File
>>();
226 File workingDir
= repo
.getWorkDir();
227 if (workingDir
== null || !workingDir
.exists())
230 File
[] childFiles
= workingDir
.listFiles();
231 Arrays
.sort(childFiles
, new Comparator
<File
>() {
232 public int compare(File o1
, File o2
) {
233 if (o1
.isDirectory()) {
234 if (o2
.isDirectory()) {
235 return o1
.compareTo(o2
);
238 } else if (o2
.isDirectory()) {
241 return o1
.compareTo(o2
);
244 for (File file
: childFiles
) {
245 if (file
.isDirectory()) {
246 children
.add(new RepositoryTreeNode
<File
>(node
,
247 RepositoryTreeNodeType
.FOLDER
, repo
, file
));
249 children
.add(new RepositoryTreeNode
<File
>(node
,
250 RepositoryTreeNodeType
.FILE
, repo
, file
));
254 return children
.toArray();
258 List
<RepositoryTreeNode
<File
>> children
= new ArrayList
<RepositoryTreeNode
<File
>>();
260 File parent
= ((File
) node
.getObject());
262 File
[] childFiles
= parent
.listFiles();
263 Arrays
.sort(childFiles
, new Comparator
<File
>() {
264 public int compare(File o1
, File o2
) {
265 if (o1
.isDirectory()) {
266 if (o2
.isDirectory()) {
267 return o1
.compareTo(o2
);
270 } else if (o2
.isDirectory()) {
273 return o1
.compareTo(o2
);
276 for (File file
: childFiles
) {
277 if (file
.isDirectory()) {
278 children
.add(new RepositoryTreeNode
<File
>(node
,
279 RepositoryTreeNodeType
.FOLDER
, repo
, file
));
281 children
.add(new RepositoryTreeNode
<File
>(node
,
282 RepositoryTreeNodeType
.FILE
, repo
, file
));
286 return children
.toArray();
291 List
<RepositoryTreeNode
<String
>> children
= new ArrayList
<RepositoryTreeNode
<String
>>();
293 String remoteName
= (String
) node
.getObject();
296 rc
= new RemoteConfig(node
.getRepository().getConfig(),
298 } catch (URISyntaxException e
) {
299 handleException(e
, node
);
300 return children
.toArray();
303 if (!rc
.getURIs().isEmpty())
304 children
.add(new RepositoryTreeNode
<String
>(node
,
305 RepositoryTreeNodeType
.FETCH
, node
.getRepository(), rc
306 .getURIs().get(0).toPrivateString()));
308 if (!rc
.getPushURIs().isEmpty())
309 if (rc
.getPushURIs().size() == 1)
310 children
.add(new RepositoryTreeNode
<String
>(node
,
311 RepositoryTreeNodeType
.PUSH
, node
.getRepository(),
312 rc
.getPushURIs().get(0).toPrivateString()));
314 children
.add(new RepositoryTreeNode
<String
>(node
,
315 RepositoryTreeNodeType
.PUSH
, node
.getRepository(),
316 rc
.getPushURIs().get(0).toPrivateString() + "...")); //$NON-NLS-1$
318 return children
.toArray();
347 private void handleException(Exception e
, RepositoryTreeNode parentNode
) {
348 Activator
.handleError(e
.getMessage(), e
, false);
349 // add a node indicating that there was an Exception
350 new RepositoryTreeNode
<String
>(parentNode
,
351 RepositoryTreeNodeType
.ERROR
, parentNode
.getRepository(),
352 UIText
.RepositoriesViewContentProvider_ExceptionNodeText
);
355 public Object
getParent(Object element
) {
357 return ((RepositoryTreeNode
) element
).getParent();
360 public boolean hasChildren(Object element
) {
361 Object
[] children
= getChildren(element
);
362 return children
!= null && children
.length
> 0;
365 private boolean collectProjectFilesFromDirectory(Collection
<File
> files
,
366 File directory
, Set
<String
> directoriesVisited
,
367 IProgressMonitor monitor
) {
369 // stolen from the GitCloneWizard; perhaps we should completely drop
370 // the projects from this view, though
371 if (monitor
.isCanceled()) {
374 monitor
.subTask(NLS
.bind(UIText
.RepositoriesView_Checking_Message
,
375 directory
.getPath()));
376 File
[] contents
= directory
.listFiles();
377 if (contents
== null)
380 // first look for project description files
381 final String dotProject
= IProjectDescription
.DESCRIPTION_FILE_NAME
;
382 for (int i
= 0; i
< contents
.length
; i
++) {
383 File file
= contents
[i
];
384 if (file
.isFile() && file
.getName().equals(dotProject
)) {
385 files
.add(file
.getParentFile());
386 // don't search sub-directories since we can't have nested
391 // no project description found, so recurse into sub-directories
392 for (int i
= 0; i
< contents
.length
; i
++) {
393 if (contents
[i
].isDirectory()) {
394 if (!contents
[i
].getName().equals(
395 GitProjectsImportPage
.METADATA_FOLDER
)) {
397 String canonicalPath
= contents
[i
].getCanonicalPath();
398 if (!directoriesVisited
.add(canonicalPath
)) {
399 // already been here --> do not recurse
402 } catch (IOException e
) {
403 Activator
.handleError(e
.getMessage(), e
, false);
405 collectProjectFilesFromDirectory(files
, contents
[i
],
406 directoriesVisited
, monitor
);