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
;
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
;
32 * Adapts an Eclipse {@link IContainer} for use in a <code>TreeWalk</code>.
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.
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
);
51 throw new IllegalArgumentException(
52 "Not in a Git project: " + base
); //$NON-NLS-1$
53 return rm
.getRepoRelativePath(base
);
56 private final IContainer node
;
59 * Construct a new iterator from a container in the workspace.
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.
68 * the part of the workspace the iterator will walk over.
70 public ContainerTreeIterator(final IContainer base
) {
71 super(computePrefix(base
));
77 * Construct a new iterator from the workspace root.
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.
85 * the workspace root to walk over.
87 public ContainerTreeIterator(final IWorkspaceRoot root
) {
88 super(""); //$NON-NLS-1$
94 * Construct a new iterator from a container in the workspace, with a given
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.
104 * the parent iterator we were created from.
106 * the part of the workspace the iterator will walk over.
108 public ContainerTreeIterator(final WorkingTreeIterator p
,
109 final IContainer base
) {
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
);
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
;
138 all
= node
.members(IContainer
.INCLUDE_HIDDEN
);
139 } catch (CoreException err
) {
143 final Entry
[] r
= new Entry
[all
.length
];
144 for (int i
= 0; i
< r
.length
; i
++)
145 r
[i
] = new ResourceEntry(all
[i
]);
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
) {
162 switch (f
.getType()) {
164 if (FS
.DETECTED
.canExecute(asFile()))
165 mode
= FileMode
.EXECUTABLE_FILE
;
167 mode
= FileMode
.REGULAR_FILE
;
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
;
175 mode
= FileMode
.TREE
;
179 mode
= FileMode
.MISSING
;
185 public FileMode
getMode() {
190 public String
getName() {
191 if (rsrc
.getType() == IResource
.PROJECT
)
192 return rsrc
.getLocation().lastSegment();
194 return rsrc
.getName();
198 public long getLength() {
200 if (rsrc
instanceof IFile
)
201 length
= asFile().length();
209 public long getLastModified() {
210 return rsrc
.getLocalTimeStamp();
214 public InputStream
openInputStream() throws IOException
{
215 if (rsrc
instanceof IFile
) {
217 return ((IFile
) rsrc
).getContents(true);
218 } catch (CoreException err
) {
219 final IOException ioe
= new IOException(err
.getMessage());
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() {
236 private File
asFile() {
237 return ((IFile
) rsrc
).getLocation().toFile();