From: "Shawn O. Pearce" <spearce@spearce.org>
To: Robin Rosenberg <robin.rosenberg@dewire.com>,
Marek Zawirski <marek.zawirski@gmail.com>
Cc: git@vger.kernel.org
Subject: [EGIT PATCH 10/11] Add a TreeWalk iterator implementation for IContainer
Date: Sun, 10 Aug 2008 01:46:25 -0700 [thread overview]
Message-ID: <1218357986-19671-11-git-send-email-spearce@spearce.org> (raw)
In-Reply-To: <1218357986-19671-10-git-send-email-spearce@spearce.org>
Treating the Eclipse workspace as a filesystem backend for TreeWalk
can give us some nice caching on the file modification times and on
directory contents. We also get nice APIs to open a file and read
its contents.
This iterator allows combining a walk over an IContainer with any
other sort of directory walk we may do, like against a stored tree
object in the object database or against the index file, or even
any other IContainer in the workspace (e.g. diff two projects).
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
.../spearce/egit/core/ContainerTreeIterator.java | 181 ++++++++++++++++++++
1 files changed, 181 insertions(+), 0 deletions(-)
create mode 100644 org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java
diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java b/org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java
new file mode 100644
index 0000000..17b8414
--- /dev/null
+++ b/org.spearce.egit.core/src/org/spearce/egit/core/ContainerTreeIterator.java
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * See LICENSE for the full license text, also available.
+ *******************************************************************************/
+
+package org.spearce.egit.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.spearce.egit.core.project.RepositoryMapping;
+import org.spearce.jgit.errors.IncorrectObjectTypeException;
+import org.spearce.jgit.lib.Constants;
+import org.spearce.jgit.lib.FileMode;
+import org.spearce.jgit.lib.ObjectId;
+import org.spearce.jgit.lib.Repository;
+import org.spearce.jgit.treewalk.AbstractTreeIterator;
+import org.spearce.jgit.treewalk.WorkingTreeIterator;
+import org.spearce.jgit.util.FS;
+
+/**
+ * Adapts an Eclipse {@link IContainer} for use in a <code>TreeWalk</code>.
+ * <p>
+ * This iterator converts an Eclipse IContainer object into something that a
+ * TreeWalk instance can iterate over in parallel with any other Git tree data
+ * structure, such as another working directory tree from outside of the
+ * workspace or a stored tree from a Repository object database.
+ * <p>
+ * Modification times provided by this iterator are obtained from the cache
+ * Eclipse uses to track external resource modification. This can be faster, but
+ * requires the user refresh their workspace when external modifications take
+ * place. This is not really a concern as it is common practice to need to do a
+ * workspace refresh after externally modifying a file.
+ *
+ * @see org.spearce.jgit.treewalk.TreeWalk
+ */
+public class ContainerTreeIterator extends WorkingTreeIterator {
+ private static String computePrefix(final IContainer base) {
+ final RepositoryMapping rm = RepositoryMapping.getMapping(base);
+ if (rm == null)
+ throw new IllegalArgumentException("Not in a Git project: " + base);
+ return rm.getRepoRelativePath(base);
+ }
+
+ private final IContainer node;
+
+ /**
+ * Construct a new iterator from the workspace.
+ * <p>
+ * The iterator will support traversal over the named container, but only if
+ * it is contained within a project which has the Git repository provider
+ * connected and this resource is mapped into a Git repository. During the
+ * iteration the paths will be automatically generated to match the proper
+ * repository paths for this container's children.
+ *
+ * @param base
+ * the part of the workspace the iterator will walk over.
+ */
+ public ContainerTreeIterator(final IContainer base) {
+ super(computePrefix(base));
+ node = base;
+ }
+
+ private ContainerTreeIterator(final WorkingTreeIterator p,
+ final IContainer base) {
+ super(p);
+ node = base;
+ }
+
+ @Override
+ public AbstractTreeIterator createSubtreeIterator(final Repository db)
+ throws IncorrectObjectTypeException, IOException {
+ if (FileMode.TREE.equals(mode))
+ return new ContainerTreeIterator(this,
+ (IContainer) ((ResourceEntry) current()).rsrc);
+ else
+ throw new IncorrectObjectTypeException(ObjectId.zeroId(),
+ Constants.TYPE_TREE);
+ }
+
+ @Override
+ protected Entry[] getEntries() throws IOException {
+ final IResource[] all;
+ try {
+ all = node.members(IContainer.INCLUDE_HIDDEN);
+ } catch (CoreException err) {
+ final IOException ioe = new IOException(err.getMessage());
+ ioe.initCause(err);
+ throw ioe;
+ }
+
+ final Entry[] r = new Entry[all.length];
+ for (int i = 0; i < r.length; i++)
+ r[i] = new ResourceEntry(all[i]);
+ return r;
+ }
+
+ static class ResourceEntry extends Entry {
+ final IResource rsrc;
+
+ private final FileMode mode;
+
+ private long length = -1;
+
+ ResourceEntry(final IResource f) {
+ rsrc = f;
+
+ switch (f.getType()) {
+ case IResource.FILE:
+ if (FS.INSTANCE.canExecute(asFile()))
+ mode = FileMode.EXECUTABLE_FILE;
+ else
+ mode = FileMode.REGULAR_FILE;
+ break;
+ case IResource.FOLDER: {
+ final IContainer c = (IContainer) f;
+ if (c.findMember(".git") != null)
+ mode = FileMode.GITLINK;
+ else
+ mode = FileMode.TREE;
+ break;
+ }
+ default:
+ mode = FileMode.MISSING;
+ break;
+ }
+ }
+
+ @Override
+ public FileMode getMode() {
+ return mode;
+ }
+
+ @Override
+ public String getName() {
+ return rsrc.getName();
+ }
+
+ @Override
+ public long getLength() {
+ if (length < 0) {
+ if (rsrc instanceof IFile)
+ length = asFile().length();
+ else
+ length = 0;
+ }
+ return length;
+ }
+
+ @Override
+ public long getLastModified() {
+ return rsrc.getLocalTimeStamp();
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException {
+ if (rsrc instanceof IFile) {
+ try {
+ return ((IFile) rsrc).getContents(true);
+ } catch (CoreException err) {
+ final IOException ioe = new IOException(err.getMessage());
+ ioe.initCause(err);
+ throw ioe;
+ }
+ }
+ throw new IOException("Not a regular file: " + rsrc);
+ }
+
+ private File asFile() {
+ return ((IFile) rsrc).getLocation().toFile();
+ }
+ }
+}
--
1.6.0.rc2.219.g1250ab
next prev parent reply other threads:[~2008-08-10 8:48 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-10 8:46 [EGIT PATCH 00/11] Misc. cleanups and improvements Shawn O. Pearce
2008-08-10 8:46 ` [EGIT PATCH 01/11] Fix RawParseUtils.endOfParagraph to work on all corner cases Shawn O. Pearce
2008-08-10 8:46 ` [EGIT PATCH 02/11] Add test case for the RevCommit parsing code Shawn O. Pearce
2008-08-10 8:46 ` [EGIT PATCH 03/11] Notify AbstractTreeIterator implementations of skipped tree entries Shawn O. Pearce
2008-08-10 8:46 ` [EGIT PATCH 04/11] Allow AbstractTreeIterator subclasses to supply their own path array Shawn O. Pearce
2008-08-10 8:46 ` [EGIT PATCH 05/11] Allow WorkingTreeIterators to define their prefix path when created Shawn O. Pearce
2008-08-10 8:46 ` [EGIT PATCH 06/11] Add getTree to TreeWalk for locating the current iterator instance Shawn O. Pearce
2008-08-10 8:46 ` [EGIT PATCH 07/11] Allow WorkingTreeIterator to track last modified time for entries Shawn O. Pearce
2008-08-10 8:46 ` [EGIT PATCH 08/11] Expose the current entry's length, last modified in WorkingTreeIterator Shawn O. Pearce
2008-08-10 8:46 ` [EGIT PATCH 09/11] Expose idBuffer,idOffset in AbstractTreeIterator to applications Shawn O. Pearce
2008-08-10 8:46 ` Shawn O. Pearce [this message]
2008-08-10 8:46 ` [EGIT PATCH 11/11] Teach NB how to encode/decode an unsigned 16 bit integer Shawn O. Pearce
2008-08-13 20:41 ` [EGIT PATCH 10/11] Add a TreeWalk iterator implementation for IContainer Robin Rosenberg
2008-08-14 4:19 ` Shawn O. Pearce
2008-08-14 5:20 ` Robin Rosenberg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1218357986-19671-11-git-send-email-spearce@spearce.org \
--to=spearce@spearce.org \
--cc=git@vger.kernel.org \
--cc=marek.zawirski@gmail.com \
--cc=robin.rosenberg@dewire.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).