Fix build
[egit.git] / org.eclipse.egit.core / src / org / eclipse / egit / core / ContainerTreeIterator.java
blobda290912264a512090719d1e5b1dac3b52c7bc73
1 /*******************************************************************************
2 * Copyright (C) 2008, Google Inc.
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
10 package org.eclipse.egit.core;
12 import java.io.File;
13 import java.io.IOException;
14 import java.io.InputStream;
16 import org.eclipse.core.resources.IContainer;
17 import org.eclipse.core.resources.IFile;
18 import org.eclipse.core.resources.IResource;
19 import org.eclipse.core.resources.IWorkspaceRoot;
20 import org.eclipse.core.runtime.CoreException;
21 import org.eclipse.egit.core.project.RepositoryMapping;
22 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
23 import org.eclipse.jgit.lib.Constants;
24 import org.eclipse.jgit.lib.FileMode;
25 import org.eclipse.jgit.lib.ObjectId;
26 import org.eclipse.jgit.lib.Repository;
27 import org.eclipse.jgit.treewalk.AbstractTreeIterator;
28 import org.eclipse.jgit.treewalk.WorkingTreeIterator;
29 import org.eclipse.jgit.util.FS;
31 /**
32 * Adapts an Eclipse {@link IContainer} for use in a <code>TreeWalk</code>.
33 * <p>
34 * This iterator converts an Eclipse IContainer object into something that a
35 * TreeWalk instance can iterate over in parallel with any other Git tree data
36 * structure, such as another working directory tree from outside of the
37 * workspace or a stored tree from a Repository object database.
38 * <p>
39 * Modification times provided by this iterator are obtained from the cache
40 * Eclipse uses to track external resource modification. This can be faster, but
41 * requires the user refresh their workspace when external modifications take
42 * place. This is not really a concern as it is common practice to need to do a
43 * workspace refresh after externally modifying a file.
45 * @see org.eclipse.jgit.treewalk.TreeWalk
47 public class ContainerTreeIterator extends WorkingTreeIterator {
48 private static String computePrefix(final IContainer base) {
49 final RepositoryMapping rm = RepositoryMapping.getMapping(base);
50 if (rm == null)
51 throw new IllegalArgumentException(
52 "Not in a Git project: " + base); //$NON-NLS-1$
53 return rm.getRepoRelativePath(base);
56 private final IContainer node;
58 /**
59 * Construct a new iterator from a container in the workspace.
60 * <p>
61 * The iterator will support traversal over the named container, but only if
62 * it is contained within a project which has the Git repository provider
63 * connected and this resource is mapped into a Git repository. During the
64 * iteration the paths will be automatically generated to match the proper
65 * repository paths for this container's children.
67 * @param base
68 * the part of the workspace the iterator will walk over.
70 public ContainerTreeIterator(final IContainer base) {
71 super(computePrefix(base));
72 node = base;
73 init(entries());
76 /**
77 * Construct a new iterator from the workspace root.
78 * <p>
79 * The iterator will support traversal over workspace projects that have
80 * a Git repository provider connected and is mapped into a Git repository.
81 * During the iteration the paths will be automatically generated to match
82 * the proper repository paths for this container's children.
84 * @param root
85 * the workspace root to walk over.
87 public ContainerTreeIterator(final IWorkspaceRoot root) {
88 super(""); //$NON-NLS-1$
89 node = root;
90 init(entries());
93 /**
94 * Construct a new iterator from a container in the workspace, with a given
95 * parent iterator.
96 * <p>
97 * The iterator will support traversal over the named container, but only if
98 * it is contained within a project which has the Git repository provider
99 * connected and this resource is mapped into a Git repository. During the
100 * iteration the paths will be automatically generated to match the proper
101 * repository paths for this container's children.
103 * @param p
104 * the parent iterator we were created from.
105 * @param base
106 * the part of the workspace the iterator will walk over.
108 public ContainerTreeIterator(final WorkingTreeIterator p,
109 final IContainer base) {
110 super(p);
111 node = base;
112 init(entries());
115 @Override
116 public AbstractTreeIterator createSubtreeIterator(final Repository db)
117 throws IncorrectObjectTypeException, IOException {
118 if (FileMode.TREE.equals(mode))
119 return new ContainerTreeIterator(this,
120 (IContainer) ((ResourceEntry) current()).rsrc);
121 else
122 throw new IncorrectObjectTypeException(ObjectId.zeroId(),
123 Constants.TYPE_TREE);
127 * Get the ResourceEntry for the current entry.
129 * @return the current entry
131 public ResourceEntry getResourceEntry() {
132 return (ResourceEntry) current();
135 private Entry[] entries() {
136 final IResource[] all;
137 try {
138 all = node.members(IContainer.INCLUDE_HIDDEN);
139 } catch (CoreException err) {
140 return EOF;
143 final Entry[] r = new Entry[all.length];
144 for (int i = 0; i < r.length; i++)
145 r[i] = new ResourceEntry(all[i]);
146 return r;
150 * Wrapper for a resource in the Eclipse workspace
152 static public class ResourceEntry extends Entry {
153 final IResource rsrc;
155 private final FileMode mode;
157 private long length = -1;
159 ResourceEntry(final IResource f) {
160 rsrc = f;
162 switch (f.getType()) {
163 case IResource.FILE:
164 if (FS.DETECTED.canExecute(asFile()))
165 mode = FileMode.EXECUTABLE_FILE;
166 else
167 mode = FileMode.REGULAR_FILE;
168 break;
169 case IResource.PROJECT:
170 case IResource.FOLDER: {
171 final IContainer c = (IContainer) f;
172 if (c.findMember(Constants.DOT_GIT) != null)
173 mode = FileMode.GITLINK;
174 else
175 mode = FileMode.TREE;
176 break;
178 default:
179 mode = FileMode.MISSING;
180 break;
184 @Override
185 public FileMode getMode() {
186 return mode;
189 @Override
190 public String getName() {
191 if (rsrc.getType() == IResource.PROJECT)
192 return rsrc.getLocation().lastSegment();
193 else
194 return rsrc.getName();
197 @Override
198 public long getLength() {
199 if (length < 0) {
200 if (rsrc instanceof IFile)
201 length = asFile().length();
202 else
203 length = 0;
205 return length;
208 @Override
209 public long getLastModified() {
210 return rsrc.getLocalTimeStamp();
213 @Override
214 public InputStream openInputStream() throws IOException {
215 if (rsrc instanceof IFile) {
216 try {
217 return ((IFile) rsrc).getContents(true);
218 } catch (CoreException err) {
219 final IOException ioe = new IOException(err.getMessage());
220 ioe.initCause(err);
221 throw ioe;
224 throw new IOException("Not a regular file: " + rsrc); //$NON-NLS-1$
228 * Get the underlying resource of this entry.
230 * @return the underlying resource
232 public IResource getResource() {
233 return rsrc;
236 private File asFile() {
237 return ((IFile) rsrc).getLocation().toFile();