Sort the files/folders of the 'Git Repositories' view
[egit/spearce.git] / org.eclipse.egit.ui / src / org / eclipse / egit / ui / internal / repository / RepositoriesViewContentProvider.java
blob08ad07c28b615639826065306ce333b32d14081e
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
8 * Contributors:
9 * Mathias Kinzler (SAP AG) - initial implementation
10 *******************************************************************************/
11 package org.eclipse.egit.ui.internal.repository;
13 import java.io.File;
14 import java.io.IOException;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.Comparator;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Set;
23 import java.util.TreeSet;
25 import org.eclipse.core.resources.IProjectDescription;
26 import org.eclipse.core.runtime.IProgressMonitor;
27 import org.eclipse.core.runtime.IStatus;
28 import org.eclipse.core.runtime.NullProgressMonitor;
29 import org.eclipse.core.runtime.Status;
30 import org.eclipse.egit.ui.Activator;
31 import org.eclipse.egit.ui.UIText;
32 import org.eclipse.egit.ui.internal.clone.GitProjectsImportPage;
33 import org.eclipse.egit.ui.internal.repository.RepositoryTreeNode.RepositoryTreeNodeType;
34 import org.eclipse.jface.viewers.ITreeContentProvider;
35 import org.eclipse.jface.viewers.Viewer;
36 import org.eclipse.jgit.lib.Ref;
37 import org.eclipse.jgit.lib.Repository;
38 import org.eclipse.osgi.util.NLS;
39 import org.eclipse.ui.statushandlers.StatusManager;
41 /**
42 * Content Provider for the Git Repositories View
44 public class RepositoriesViewContentProvider implements ITreeContentProvider {
46 @SuppressWarnings("unchecked")
47 public Object[] getElements(Object inputElement) {
49 Comparator<RepositoryTreeNode<Repository>> sorter = new Comparator<RepositoryTreeNode<Repository>>() {
51 public int compare(RepositoryTreeNode<Repository> o1,
52 RepositoryTreeNode<Repository> o2) {
53 return getRepositoryName(o1.getObject()).compareTo(
54 getRepositoryName(o2.getObject()));
59 Set<RepositoryTreeNode<Repository>> output = new TreeSet<RepositoryTreeNode<Repository>>(
60 sorter);
62 for (Repository repo : ((List<Repository>) inputElement)) {
63 output.add(new RepositoryTreeNode<Repository>(null,
64 RepositoryTreeNodeType.REPO, repo, repo));
67 return output.toArray();
70 public void dispose() {
71 // nothing
74 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
75 // nothing
78 public Object[] getChildren(Object parentElement) {
80 RepositoryTreeNode node = (RepositoryTreeNode) parentElement;
81 Repository repo = node.getRepository();
83 switch (node.getType()) {
85 case BRANCHES: {
86 List<RepositoryTreeNode<Ref>> refs = new ArrayList<RepositoryTreeNode<Ref>>();
88 for (Ref ref : repo.getAllRefs().values()) {
89 refs.add(new RepositoryTreeNode<Ref>(node,
90 RepositoryTreeNodeType.REF, repo, ref));
93 return refs.toArray();
96 case REMOTES: {
97 List<RepositoryTreeNode<String>> remotes = new ArrayList<RepositoryTreeNode<String>>();
99 Repository rep = node.getRepository();
101 Set<String> configNames = rep.getConfig().getSubsections(
102 RepositoriesView.REMOTE);
104 for (String configName : configNames) {
105 remotes.add(new RepositoryTreeNode<String>(node,
106 RepositoryTreeNodeType.REMOTE, repo, configName));
109 return remotes.toArray();
112 case REPO: {
113 List<RepositoryTreeNode<Repository>> branches = new ArrayList<RepositoryTreeNode<Repository>>();
115 branches.add(new RepositoryTreeNode<Repository>(node,
116 RepositoryTreeNodeType.BRANCHES, node.getRepository(), node
117 .getRepository()));
119 branches.add(new RepositoryTreeNode<Repository>(node,
120 RepositoryTreeNodeType.WORKINGDIR, node.getRepository(),
121 node.getRepository()));
123 branches.add(new RepositoryTreeNode<Repository>(node,
124 RepositoryTreeNodeType.PROJECTS, node.getRepository(), node
125 .getRepository()));
127 branches.add(new RepositoryTreeNode<Repository>(node,
128 RepositoryTreeNodeType.REMOTES, node.getRepository(), node
129 .getRepository()));
131 return branches.toArray();
134 case PROJECTS: {
135 List<RepositoryTreeNode<File>> projects = new ArrayList<RepositoryTreeNode<File>>();
137 // TODO do we want to show the projects here?
138 Collection<File> result = new HashSet<File>();
139 Set<String> traversed = new HashSet<String>();
140 collectProjectFilesFromDirectory(result, repo.getDirectory()
141 .getParentFile(), traversed, new NullProgressMonitor());
142 for (File file : result) {
143 projects.add(new RepositoryTreeNode<File>(node,
144 RepositoryTreeNodeType.PROJ, repo, file));
147 Comparator<RepositoryTreeNode<File>> sorter = new Comparator<RepositoryTreeNode<File>>() {
149 public int compare(RepositoryTreeNode<File> o1,
150 RepositoryTreeNode<File> o2) {
151 return o1.getObject().getName().compareTo(
152 o2.getObject().getName());
155 Collections.sort(projects, sorter);
157 return projects.toArray();
160 case WORKINGDIR: {
161 List<RepositoryTreeNode<File>> children = new ArrayList<RepositoryTreeNode<File>>();
163 File workingDir = repo.getWorkDir();
164 if (workingDir == null || !workingDir.exists())
165 return null;
167 File[] childFiles = workingDir.listFiles();
168 Arrays.sort(childFiles, new Comparator<File>() {
169 public int compare(File o1, File o2) {
170 if (o1.isDirectory()) {
171 if (o2.isDirectory()) {
172 return o1.compareTo(o2);
174 return -1;
175 } else if (o2.isDirectory()) {
176 return 1;
178 return o1.compareTo(o2);
181 for (File file : childFiles) {
182 if (file.isDirectory()) {
183 children.add(new RepositoryTreeNode<File>(node,
184 RepositoryTreeNodeType.FOLDER, repo, file));
185 } else {
186 children.add(new RepositoryTreeNode<File>(node,
187 RepositoryTreeNodeType.FILE, repo, file));
191 return children.toArray();
194 case FOLDER: {
195 List<RepositoryTreeNode<File>> children = new ArrayList<RepositoryTreeNode<File>>();
197 File parent = ((File) node.getObject());
199 File[] childFiles = parent.listFiles();
200 Arrays.sort(childFiles, new Comparator<File>() {
201 public int compare(File o1, File o2) {
202 if (o1.isDirectory()) {
203 if (o2.isDirectory()) {
204 return o1.compareTo(o2);
206 return -1;
207 } else if (o2.isDirectory()) {
208 return 1;
210 return o1.compareTo(o2);
213 for (File file : childFiles) {
214 if (file.isDirectory()) {
215 children.add(new RepositoryTreeNode<File>(node,
216 RepositoryTreeNodeType.FOLDER, repo, file));
217 } else {
218 children.add(new RepositoryTreeNode<File>(node,
219 RepositoryTreeNodeType.FILE, repo, file));
223 return children.toArray();
226 default:
227 return null;
232 public Object getParent(Object element) {
234 return ((RepositoryTreeNode) element).getParent();
237 public boolean hasChildren(Object element) {
238 Object[] children = getChildren(element);
239 return children != null && children.length > 0;
242 private boolean collectProjectFilesFromDirectory(Collection<File> files,
243 File directory, Set<String> directoriesVisited,
244 IProgressMonitor monitor) {
246 // stolen from the GitCloneWizard; perhaps we should completely drop
247 // the projects from this view, though
248 if (monitor.isCanceled()) {
249 return false;
251 monitor.subTask(NLS.bind(
252 UIText.RepositoriesView_Checking_Message,
253 directory.getPath()));
254 File[] contents = directory.listFiles();
255 if (contents == null)
256 return false;
258 // first look for project description files
259 final String dotProject = IProjectDescription.DESCRIPTION_FILE_NAME;
260 for (int i = 0; i < contents.length; i++) {
261 File file = contents[i];
262 if (file.isFile() && file.getName().equals(dotProject)) {
263 files.add(file.getParentFile());
264 // don't search sub-directories since we can't have nested
265 // projects
266 return true;
269 // no project description found, so recurse into sub-directories
270 for (int i = 0; i < contents.length; i++) {
271 if (contents[i].isDirectory()) {
272 if (!contents[i].getName().equals(
273 GitProjectsImportPage.METADATA_FOLDER)) {
274 try {
275 String canonicalPath = contents[i].getCanonicalPath();
276 if (!directoriesVisited.add(canonicalPath)) {
277 // already been here --> do not recurse
278 continue;
280 } catch (IOException exception) {
281 StatusManager.getManager().handle(
282 new Status(IStatus.ERROR, Activator
283 .getPluginId(), exception
284 .getLocalizedMessage(), exception));
287 collectProjectFilesFromDirectory(files, contents[i],
288 directoriesVisited, monitor);
292 return true;
295 private static String getRepositoryName(Repository repository) {
296 return repository.getDirectory().getParentFile().getName();