Restore IContainer.INCLUDE_HIDDEN within ContainerTreeIterator
[egit.git] / org.spearce.egit.core / src / org / spearce / egit / core / ContainerTreeIterator.java
blob61717f55a743ae9ac12f493cfcfdec5bb138b996
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;
11 import java.io.File;
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;
29 /**
30 * Adapts an Eclipse {@link IContainer} for use in a <code>TreeWalk</code>.
31 * <p>
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.
36 * <p>
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);
48 if (rm == null)
49 throw new IllegalArgumentException("Not in a Git project: " + base);
50 return rm.getRepoRelativePath(base);
53 private final IContainer node;
55 /**
56 * Construct a new iterator from the workspace.
57 * <p>
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.
64 * @param base
65 * the part of the workspace the iterator will walk over.
67 public ContainerTreeIterator(final IContainer base) {
68 super(computePrefix(base));
69 node = base;
70 init(entries());
73 private ContainerTreeIterator(final WorkingTreeIterator p,
74 final IContainer base) {
75 super(p);
76 node = base;
77 init(entries());
80 @Override
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);
86 else
87 throw new IncorrectObjectTypeException(ObjectId.zeroId(),
88 Constants.TYPE_TREE);
91 private Entry[] entries() {
92 final IResource[] all;
93 try {
94 all = node.members(IContainer.INCLUDE_HIDDEN);
95 } catch (CoreException err) {
96 return EOF;
99 final Entry[] r = new Entry[all.length];
100 for (int i = 0; i < r.length; i++)
101 r[i] = new ResourceEntry(all[i]);
102 return r;
105 static class ResourceEntry extends Entry {
106 final IResource rsrc;
108 private final FileMode mode;
110 private long length = -1;
112 ResourceEntry(final IResource f) {
113 rsrc = f;
115 switch (f.getType()) {
116 case IResource.FILE:
117 if (FS.INSTANCE.canExecute(asFile()))
118 mode = FileMode.EXECUTABLE_FILE;
119 else
120 mode = FileMode.REGULAR_FILE;
121 break;
122 case IResource.FOLDER: {
123 final IContainer c = (IContainer) f;
124 if (c.findMember(".git") != null)
125 mode = FileMode.GITLINK;
126 else
127 mode = FileMode.TREE;
128 break;
130 default:
131 mode = FileMode.MISSING;
132 break;
136 @Override
137 public FileMode getMode() {
138 return mode;
141 @Override
142 public String getName() {
143 return rsrc.getName();
146 @Override
147 public long getLength() {
148 if (length < 0) {
149 if (rsrc instanceof IFile)
150 length = asFile().length();
151 else
152 length = 0;
154 return length;
157 @Override
158 public long getLastModified() {
159 return rsrc.getLocalTimeStamp();
162 @Override
163 public InputStream openInputStream() throws IOException {
164 if (rsrc instanceof IFile) {
165 try {
166 return ((IFile) rsrc).getContents(true);
167 } catch (CoreException err) {
168 final IOException ioe = new IOException(err.getMessage());
169 ioe.initCause(err);
170 throw ioe;
173 throw new IOException("Not a regular file: " + rsrc);
176 private File asFile() {
177 return ((IFile) rsrc).getLocation().toFile();