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 * See LICENSE for the full license text, also available.
7 *******************************************************************************/
9 package org
.spearce
.egit
.core
;
12 import java
.io
.IOException
;
13 import java
.io
.InputStream
;
15 import org
.eclipse
.core
.resources
.IContainer
;
16 import org
.eclipse
.core
.resources
.IFile
;
17 import org
.eclipse
.core
.resources
.IResource
;
18 import org
.eclipse
.core
.runtime
.CoreException
;
19 import org
.spearce
.egit
.core
.project
.RepositoryMapping
;
20 import org
.spearce
.jgit
.errors
.IncorrectObjectTypeException
;
21 import org
.spearce
.jgit
.lib
.Constants
;
22 import org
.spearce
.jgit
.lib
.FileMode
;
23 import org
.spearce
.jgit
.lib
.ObjectId
;
24 import org
.spearce
.jgit
.lib
.Repository
;
25 import org
.spearce
.jgit
.treewalk
.AbstractTreeIterator
;
26 import org
.spearce
.jgit
.treewalk
.WorkingTreeIterator
;
27 import org
.spearce
.jgit
.util
.FS
;
30 * Adapts an Eclipse {@link IContainer} for use in a <code>TreeWalk</code>.
32 * This iterator converts an Eclipse IContainer object into something that a
33 * TreeWalk instance can iterate over in parallel with any other Git tree data
34 * structure, such as another working directory tree from outside of the
35 * workspace or a stored tree from a Repository object database.
37 * Modification times provided by this iterator are obtained from the cache
38 * Eclipse uses to track external resource modification. This can be faster, but
39 * requires the user refresh their workspace when external modifications take
40 * place. This is not really a concern as it is common practice to need to do a
41 * workspace refresh after externally modifying a file.
43 * @see org.spearce.jgit.treewalk.TreeWalk
45 public class ContainerTreeIterator
extends WorkingTreeIterator
{
46 private static String
computePrefix(final IContainer base
) {
47 final RepositoryMapping rm
= RepositoryMapping
.getMapping(base
);
49 throw new IllegalArgumentException("Not in a Git project: " + base
);
50 return rm
.getRepoRelativePath(base
);
53 private final IContainer node
;
56 * Construct a new iterator from the workspace.
58 * The iterator will support traversal over the named container, but only if
59 * it is contained within a project which has the Git repository provider
60 * connected and this resource is mapped into a Git repository. During the
61 * iteration the paths will be automatically generated to match the proper
62 * repository paths for this container's children.
65 * the part of the workspace the iterator will walk over.
67 public ContainerTreeIterator(final IContainer base
) {
68 super(computePrefix(base
));
73 private ContainerTreeIterator(final WorkingTreeIterator p
,
74 final IContainer base
) {
81 public AbstractTreeIterator
createSubtreeIterator(final Repository db
)
82 throws IncorrectObjectTypeException
, IOException
{
83 if (FileMode
.TREE
.equals(mode
))
84 return new ContainerTreeIterator(this,
85 (IContainer
) ((ResourceEntry
) current()).rsrc
);
87 throw new IncorrectObjectTypeException(ObjectId
.zeroId(),
91 private Entry
[] entries() {
92 final IResource
[] all
;
94 // all = node.members(IContainer.INCLUDE_HIDDEN); 3.4 flag
95 all
= node
.members(0);
96 } catch (CoreException err
) {
100 final Entry
[] r
= new Entry
[all
.length
];
101 for (int i
= 0; i
< r
.length
; i
++)
102 r
[i
] = new ResourceEntry(all
[i
]);
106 static class ResourceEntry
extends Entry
{
107 final IResource rsrc
;
109 private final FileMode mode
;
111 private long length
= -1;
113 ResourceEntry(final IResource f
) {
116 switch (f
.getType()) {
118 if (FS
.INSTANCE
.canExecute(asFile()))
119 mode
= FileMode
.EXECUTABLE_FILE
;
121 mode
= FileMode
.REGULAR_FILE
;
123 case IResource
.FOLDER
: {
124 final IContainer c
= (IContainer
) f
;
125 if (c
.findMember(".git") != null)
126 mode
= FileMode
.GITLINK
;
128 mode
= FileMode
.TREE
;
132 mode
= FileMode
.MISSING
;
138 public FileMode
getMode() {
143 public String
getName() {
144 return rsrc
.getName();
148 public long getLength() {
150 if (rsrc
instanceof IFile
)
151 length
= asFile().length();
159 public long getLastModified() {
160 return rsrc
.getLocalTimeStamp();
164 public InputStream
openInputStream() throws IOException
{
165 if (rsrc
instanceof IFile
) {
167 return ((IFile
) rsrc
).getContents(true);
168 } catch (CoreException err
) {
169 final IOException ioe
= new IOException(err
.getMessage());
174 throw new IOException("Not a regular file: " + rsrc
);
177 private File
asFile() {
178 return ((IFile
) rsrc
).getLocation().toFile();